OOP第三次Blog
前言:
(1) 第七次题集只有一道题目——家居强电电路模拟程序-3,这是第三次迭代,这次迭代主要的点有四个。
首先本次迭代添加了线路中存在多个串联起来的并联电路。不同于上次的单并联,本次更复杂。
然后本次还新迭代了一种控制器——互斥开关,互斥开关一共有三个触脚,默认状态是1,2相连,但是互斥开关可以反接所以互斥开关还需要考虑接入的方向,这显然需要需要引入一个新的变量进行判定。然后就是这个互斥开关是有电阻的,并不是理想开关,所以对于短路的判断需要重新考虑。
再然后是串联中包含串联电路,不论是主路还是支路都有可能出现串联电路,这一点还是比较好处理的,本身就是将串联电路设定为了电路设备。
最后是引入了一种受控电器——受控窗帘,收到电压和室内亮度的控制,默认状态为全开。
总体而言本次题解较上次迭代而言难度增幅不算太大。
(2) 第八次题集同样只有一道题目——家居强电电路模拟程序-4,这是本系列题目的第四次迭代,这次迭代引入了很多新的功能,主要有五点。
首先是增加管脚电压的显示,在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。这一点是最让人头疼的地方,需要好好回忆一下高中的电路,同时有几种特殊情况需要注意情况,不然很容易错。
然后是电流限制,电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。
再次是短路检测,如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”。
再然后是并联电路中包含并联,本次迭代考虑并联电路中包含并联电路的情况,即构成并联电路的串联电路可以包含别的并联电路。这一点比较好处理,因为并联电路本身也别看作一个电路设备,在支路的输入时,加入这种情况就行。
最后是二极管,增加二极管元件,其电路特性为:正向导通,反向截止;其电器符号如图4所示,当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。
总体而言,本次迭代的难度增加了很多,让人眼前一黑,主要是管脚电压的显示,确实需要考虑很多情况。
第七次题集
设计与分析:
首先本次迭代比起上次需要将串联电路也设置为一个电路设备类,以下是一个简易类图:
对串联类同时也加入了很多新的方法,以下是部分代码展示:
class Series extends Equipment{
public double getVoltage() {
return voltage;
}
public void setVoltage(double voltage) {
this.voltage = voltage;
}
private double voltage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
public void VoltageDivision()
{
double aver=getVoltage()/getResistor();
for(int i=0;i<list.size();i++)
{
Equipment e= list.get(i);
if(e instanceof Switch || e instanceof Governor || e instanceof ContinueGovernor||e instanceof Hswitch)
continue;
else if(e instanceof Series)
{
e.setVoltage(aver*e.getResistor());
e.VoltageDivision();
}
else
{
e.setVoltage(aver*e.getResistor());
}
}
}
private double resistor;
public double getResistor() {
resistor = 0;
for (int i = 0; i < list.size(); i++) {
Equipment e = list.get(i);
if (e instanceof Switch || e instanceof Governor || e instanceof ContinueGovernor)
continue;
else if(e instanceof Hswitch&&e.IfHswitchPath(this.name))
{
resistor+=e.getResistor();
}
else
{
resistor += e.getResistor();
}
}
return resistor;
}
public boolean IfPathway()
{
for(int i=0;i< list.size();i++)
{
Equipment e= list.get(i);
if(e instanceof Switch)
{
if(e.switchstyle==0)
{
return false;
}
}
else if(e instanceof Parallel&&e.IfPathway()==false)
{
return false;
}
else if(e instanceof Hswitch&&e.IfHswitchPath(this.name)==false)
{
return false;
}
else if(e instanceof Series&&!e.IfPathway())
{
return false;
}
}
return true;
}
public boolean Ifshort()//检查是否短路 短路就是true 不短路就是false
{
boolean flag=true;
for(int i=0;i<list.size();i++)
{
Equipment e= list.get(i);
if(e instanceof Switch&&e.switchstyle==1)
{
continue;
}
else if(e instanceof Series&& e.Ifshort())
{
continue;
}
else
{
flag=false;
break;
}
}
return flag;
}
public ArrayList<Equipment> getList() {
return list;
}
public void setList(ArrayList<Equipment> list) {
this.list = list;
}
private ArrayList<Equipment> list;
Series() {
list = new ArrayList<>();
}
public void addEquipment(Equipment e) {
list.add(e);
}
public Equipment getEquipment(int idex) {
return list.get(idex - 1);
}
}
在串联电路类中对短路和断路的判定方法改了,如果遇见了串联电路,则再次调用该方法,然后就是setVoltage()方法这是负责分压的方法,遇见串联电路时,和遇见其他受控设备一样分压,但是要多加一点,那就是再次分压。
然后就是本次新迭代的受控设备——互斥开关,这个在输入时就需要十分注意它的方向,以下是部分代码:
class Hswitch extends Equipment implements Comparable<Hswitch>{
Hswitch(String name)
{
this.name=name;
}
public void setHchoice(int hchoice)
{
if(hchoice%2==0)
{
Hchoice=2;
}
else
Hchoice=3;
}
private int Hchoice;
String H2;
public void setH2(String tname)
{
H2=tname;
}
String H3;
public void setH3(String tname)
{
H3=tname;
}
@Override
double getResistor() {
if(Hchoice==2)
return 5;
else
return 10;
}
@Override
public boolean IfHswitchPath(String tname)
{
if(Hchoice==2&&H2!=null&&H2.equals(tname))
{
return true;
}
else if(Hchoice==3&&H3!=null&&H3.equals(tname))
{
return true;
}
else
return false;
}
@Override
void display() {
if(Hchoice==2)
{
System.out.println("@"+name+":closed");
}
else
System.out.println("@"+name+":turned on");
}
@Override
public int compareTo(Hswitch o) {
if(this.name.compareTo(o.getName())<0)
return -1;
else
return 1;
}
}
互斥开关中有一个特殊的布尔变量Hchoice,专门判断互斥开关的触脚1与那个触脚相连,
其中的IfHswitchPath()方法用于判断某条路这个互斥开关是否接通,主要用于判断某条串联是否断路。
互斥开关中也实现了Comparable这个接口,在输出是需要进行排序。
最后是本次迭代的一个新的受控设备——受控窗帘,它只受电压和室内光线的控制,所以判断窗帘的打开程度需要最后判断,在所有分压完成后,以下是部分代码:
class Curtains extends Equipment implements Comparable<Curtains>{
private int sumlux;
Curtains(String name)
{
this.name=name;
}
@Override
public void setVoltage(double c) {
voltage=c;
}
public void setSumlux(int sumlux)
{
this.sumlux=sumlux;
}
@Override
double getResistor() {
return 15;
}
@Override
void display() {
if(voltage<50||sumlux<50)
{
System.out.println("@"+name+":100%");
}
else if(sumlux>=50&&sumlux<100)
{
System.out.println("@"+name+":80%");
}
else if(sumlux>=100&&sumlux<200)
{
System.out.println("@"+name+":60%");
}
else if(sumlux>=200&&sumlux<300)
{
System.out.println("@"+name+":40%");
}
else if(sumlux>=300&&sumlux<400)
{
System.out.println("@"+name+":20%");
}
else if(sumlux>=400)
{
System.out.println("@"+name+":0%");
}
}
@Override
void close() {
voltage=0;
}
@Override
public int compareTo(Curtains o) {
if(this.name.compareTo(o.getName())<0)
return -1;
else
return 1;
}
}
其中的sumlux就是所以灯泡的光亮总和,然后和电压一起判定就行了,这是一个比较简单地受控设备,
同时也同其他设备一样,需要实现Comparable接口,从而重写compareTo方法,便于在最后输出之前进行排序。
踩坑心得:
(1) 开关的闭合情况我没有正确判断,我之前是根据字符串方法contain()方法进行判断是否改变情况,而我对于输入信息中的调节开关的信息没有进行字符串的抓取,就导致一些判断错误。
例如:开关K11,遇见判断信息#K112也会进行调节,可是这两个开关并不是一个,导致答案错误。
例如输入:
#T1:[IN K12-1] [K12-2 D2-1] [D2-2 OUT]
#T2:[IN K123-1] [K123-2 D1-1] [D1-2 OUT]
#T3:[VCC K1-1] [K1-2 T1-IN] [T1-OUT T2-IN] [T2-OUT GND]
#K1
#K12
#K123
end
就会造成错误输出:
@K1:turned on
@K12:closed
@K123:closed
@D1:0
@D2:0
因此在输入开关的判断信息是就需要进行字符串的抓取,
就像下面这样:
if(Line.contains("#K"))
{
String regstr="#(K[0-9]+)";
Pattern pattern=Pattern.compile(regstr);
Matcher matcher= pattern.matcher(Line);
String name="";
if(matcher.find())
{
name=matcher.group(1);
}
changNumList.add(name);
}
这样在比较的时候用equal()方法就不会造成错误。
(2) 然后是一个非常非常非常非常不该出现的错误,可是我又错了,我由于有一个双层循环,内层循环数和外层的循环数写反了,导致有时候会出现null的引用,我一直以为是正则表达式出现了错误,找了很久很久才发现,是我写反了,浪费了大量时间。
这件事告诉我们写代码一定要耐心和细心,不然一步错,想要回头找出来是很艰难的过程,也很痛苦。
改进建议:
(1)代码结构优化:
- 重构代码,确保代码遵循良好的编程实践,如代码的封装、继承和多态。
- 优化类的设计,确保每个类都有单一职责,并且职责之间保持清晰的界限。
- 使用包和类层次结构来组织代码,保持清晰的命名规范,方便其他人理解。
(2)性能优化:
-
分析程序的性能瓶颈,并采取相应的优化措施。
-
对于频繁执行的计算,考虑使用更高效的算法或数据结构。
第八次题集
设计与分析:
这次迭代新加入了二极管类,但是类与类之间的基本关系没有变化,
基本类图如下:
本次添加的二极管类,如果正向接入则相当于闭合开关,反向接入则相当于开关打开,所以对于短路和断路这些情况的特殊判定也要增加,以下是部分代码:
class Diode extends Equipment implements Comparable<Diode> {
private int pre;
Diode(String name, int pre) {
this.name = name;
this.pre = pre;
doidepre = pre;
}
@Override
int getRatedcurrent() {
return 8;
}
@Override
public void setVoltage(double c) {
voltage = 0;
}
@Override
double getResistor() {
return 0;
}
@Override
void display() {
if (pre == 1) {
System.out.print("@" + name + ":conduction" + " " + (int) contact1 + "-" + (int) contact2);
} else {
System.out.print("@" + name + ":cutoff" + " " + (int) contact1 + "-" + (int) contact2);
}
if (Ifexceed) {
System.out.println(" exceeding current limit error");
} else {
System.out.println();
}
}
@Override
public int compareTo(Diode o) {
if (this.name.compareTo(o.getName()) < 0)
return -1;
else
return 1;
}
}
其中变量pre就是前驱触脚,根据输入信息确定前驱触脚,然后在进行判断是否断开。
然后是电流的限制,就在电路设备类中都加入了一个方法getRatedcurrent(),用来获取额定电流,并通过方法Ifexceed分流,从而确定每一个电器是否超出限制。
以下是方法代码:
public void Ifexceed(double current) {
for (int i = 0; i < list.size(); i++) {
Equipment e = list.get(i);
if (e instanceof Parallel) {
e.Ifexceed(current);
} else if (e instanceof Series) {
e.Ifexceed(current);
} else if (e instanceof Hswitch) {
if (e.IfHswitchPath(this.name) && current > e.getRatedcurrent()) {
e.Ifexceed = true;
}
} else {
if (current > e.getRatedcurrent()) {
e.Ifexceed = true;
} else
e.Ifexceed = false;
if(e instanceof Diode)
{
if(current==0)
{
e.Ifdiode=false;
}
else
{
e.Ifdiode=true;
}
}
}
}
}
对每一条支路进行分流,确定它的电流,串联电路电流相等。
然后是管脚电压的计算,首先确定总路的电压,然后确定·总路中所有设备(当然也包括并联和串联等)的电压,
然后依次减去,可以得到每个用电器两端的电压,如果是并联或者串联,则继续调用相应方法。
主要判断短路和断路的情况,其中断路是还要考虑断开的设备的触脚电压可能是0,这需要额外判断。
同时注意这次题目将受控窗帘的默认情况改了,和上次不一样。
以下是计算的部分代码:
public void footvoltage(double v, double v1) {
~~~
double total = v;
for (int i = 0; i < list.size(); i++) {
Equipment e = list.get(i);
if (e instanceof Governor || e instanceof ContinueGovernor)
continue;
else if (e instanceof Series) {
e.footvoltage(total, total - e.getVoltage());
total -= e.getVoltage();
} else if (e instanceof Parallel) {
e.footvoltage(total, total - e.getVoltage());
total -= e.getVoltage();
} else if (e instanceof Hswitch) {//有问题
if (e.ifhswitch) {
e.contact1 = total;
if (e.IfHswitchPath2(this.name)) {
e.contact2 = total - e.getVoltage();
} else {
e.contact3 = total - e.getVoltage();
}
total -= e.getVoltage();
} else {
if (e.IfHswitchPath2(this.name)) {
e.contact2 = total;
e.contact1 = total - e.getVoltage();
} else {
e.contact3 = total;
e.contact1 = total - e.getVoltage();
}
total -= e.getVoltage();
}
} else {
if (e.Ifrigth) {
e.contact1 = total;
e.contact2 = (total - e.getVoltage());
total -= e.getVoltage();
} else {
e.contact2 = total;
e.contact1 = (total - e.getVoltage());
total -= e.getVoltage();
}
}
}
}
这只是正常的情况,断路和短路的代码过于繁琐,就不展示了。
最后还有一个短路检测,这个就很简单了,只有直接判断总路是不是短路,如果是直接输出就行,然后return。
if (mainPathway.Ifshort())//短路
{
System.out.println("short circuit error");
return;
}
踩坑心得:
这次题集难度很大,特殊情况也很多,所以真的踩了很多坑,以下是几个重点的坑:
(1) 首先是读题没有仔细看,想当然的以为窗帘这些受控电器没有变化和上次一样,结果它改了,默认情况改成了全开。
导致错了一个测试点,最后仔细看题终于发现了。
(2) 还有就是电路的电压触脚没有弄清楚,高中电路没有学好,如果并联的一条电路断路了,它的触脚电压可能为0,如果
他有多个断开的设备,则开头和结尾的断开设备中间的所有电器的触脚都是0。
例如输入:
#T1:[IN K1-1] [K1-2 OUT]
#T2:[IN K2-1] [K2-2 K3-1] [K3-2 B2-1] [B2-2 OUT]
#M1:[T1 T2]
#T3:[VCC M1-IN] [M1-OUT B1-1] [B1-2 GND]
#K1
end
错误输出:
@K1:closed 220-220 exceeding current limit error
@K2:turned on 220-0
@K3:turned on 0-220
@B1:200 220-0 exceeding current limit error
@B2:0 0-0
正确的输出:
@K1:closed 220-220 exceeding current limit error
@K2:turned on 220-0
@K3:turned on 0-220
@B1:200 220-0 exceeding current limit error
@B2:0 220-220
(3) 如果并联电路短路,则每条短路的电路均分电流,其他电路电流为0。
我下意识以为只会有一条短路电流,所有第一条短路会分全部电流,其他的则全部是0。
这就会导致电路设备是否超出电路限制做出影响。
例如输入:
#T1:[IN K1-1] [K1-2 OUT]
#T2:[IN K4-1] [K4-2 OUT]
#T4:[IN K3-1] [K3-2 OUT]
#M1:[T1 T2 T4]
#T3:[VCC K2-1] [K2-2 M1-IN] [M1-OUT B1-1] [B1-2 GND]
#K1
#K3
#K2
end
我的错误输出:
@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:closed 220-220 exceeding current limit error
@K4:turned on 220-220
@B1:200 220-0 exceeding current limit error
正确输入为:
@K1:closed 220-220
@K2:closed 220-220 exceeding current limit error
@K3:closed 220-220
@K4:turned on 220-220
@B1:200 220-0 exceeding current limit error
改进建议:
(1)代码结构优化:
- 重构代码,确保代码遵循良好的编程实践,如代码的封装、继承和多态。
- 优化类的设计,确保每个类都有单一职责,并且职责之间保持清晰的界限。
- 使用包和类层次结构来组织代码,保持清晰的命名规范,方便其他人理解。
(2)性能优化:
-
分析程序的性能瓶颈,并采取相应的优化措施。
-
对于频繁执行的计算,考虑使用更高效的算法或数据结构。
-
在写代码时,加入多一些错误异常处理,这可以很好的帮助调试代码,发现错误。
总结
在本次家居强电电路模拟程序的迭代中,我主要关注了以下几个方面的改进:
- 电路复杂度的提升:我们引入了更复杂的电路结构,如多个串联的并联电路和包含串联电路的并联电路。这样的设计使得程序能够更真实地模拟现实生活中的电路布局。
- 新功能的加入:在第七次迭代中,我们增加了互斥开关和受控窗帘的功能。这些新功能的加入使得程序更加贴近实际应用,并为用户提供了更多的操作可能性。
- 代码结构的优化:在代码设计方面,我们采取了模块化设计、使用设计模式、文档和注释等措施,以提高代码的可读性和可维护性。
- 性能优化和错误处理:在第八次迭代中,我们优化了程序的性能,并引入了电流限制和短路检测等错误处理机制。这些改进使得程序更加健壮和可靠。
总的来说,这几次迭代确实很有锻炼效果,我能明显感觉到我的代码调试能力增强了,遇到错误会不断的测试,找到错误,然后修改。
我明白了持续学习的重要性。在未来项目开发过程中,我们可能遇到了许多新问题和挑战。为了找到解决方案,我不得不查阅相关资料,学习新的知识和技能。这种持续学习的过程让我不断进步,也让我意识到只有不断学习,才能适应不断变化的技术环境。
此外,我认识到编程不仅仅是一门技术,更是一种解决问题的能力。在项目开发过程中,我们需要面对各种各样的技术难题。通过不断尝试和思考,我们找到了解决问题的方法。这种解决问题的能力让我更加自信,也让我明白了编程的价值所在。
最后,我感激这几次PTA给我带来的成长和收获。在这个过程中,我提高了自己的编程技能,还收获了丰富的经验。这些经验和技能将对我未来的学习和职业发展产生深远的影响。
还有对课程的一些建议,希望PTA的练习题量可以增加一点,但是测试点也给一点提示,然后也可以使大作业的设计更加符合事实。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~