一、前言

  在家居强电电路模拟程序-1和家居强电电路模拟程序-2的基础之上,最后两次的大作业难度飞升。

  家居强电电路模拟程序-3,引入了互斥开关和受控窗帘,这两者都不同于之前的控制设备和受控设备,对于互斥开关,要考虑他的引脚问题和正接反接,而受控窗帘不是仅仅根据电压差来控制设备的状态了,而是在所有设备完成更新后,再根据电路中设备的光照强度完成受控窗帘的状态更新。并且在最后的电路中新增了多条并联电路情况,也就是说存在多条并联电路串联在一起的情况,这无疑给这一次大作业提升了难度,但好在这都没有颠覆我前两次的设计,可以在我的之前代码的基础上进行修改。

  家居强电电路模拟程序-4,最后一次大作业的难度更是上了一个台阶,要考虑的情况太多了,而且在最终输出的时候要将设备输入和输出引脚的电压值一并输出,而我之前是利用设备的电流来计算设备的压差从而改变设备的状态,可是这一次我明显不能这么做了,因为我要知道的不能仅仅是压差,所以这给我带来了很大的难度。

  通过这几次PTA作业,我更加深入理解了封装、继承和多态等概念,能够更好地设计和组织代码结构,提高代码的复用性和可维护性。同时进一步学习了 Java 的核心概念,包括数据类型、Arrlist、数组、异常处理等。通过实际练习,我更加熟悉了这些概念的用法和原理,能够更灵活地运用于实际项目中。

二、设计与分析

1.家居强电电路模拟程序-3

  在第二次代码的基础上我添加修改了以下类。

  • 互斥开关类

  默认互斥开关的引脚是12相接,如果调用互斥开关的toggle()函数可以切换互斥开关的状态。

  • 受控窗帘类

  受控窗帘的更新方式虽然不是通过压差来实现的,但是也必须传入压差作为参数,之后再根据电路中的光照值来判断受控窗帘的位置。

public void updateStatus(double voltage) {
if (voltage>=50){
if (brightness>=400){
position="0";
}else if (brightness>=300){
position="20%";
}else if (brightness>=200){
position="40%";
}else if (brightness>=100){
position="60%";
}else if (brightness>=50){
position="80%";
}else {
position="100%";
}
}
}
  • 串联电路类

  在串联电路类中,我新增了一个Map<String,Integer> ESwitch来保存串联电路中的所有互斥开关,然后在电路中来判断这条电路连接的是互斥开关的哪两个引脚。

public void identify_pin(List<String> list){
for (String str:list) {
if (str.charAt(0)=='H'){
if (!str.split("-")[1].equals("1")){
ESwitch.put(str.split("-")[0], Integer.valueOf(str.split("-")[1]));
}
}
}
}

  在判断串联电路开关是否完全闭合的时候,需要增加对互斥开关的判断,如果互斥开关同时满足状态为closed和当前连接的引脚为12时返回true表示互斥开关是闭合的,同理,如果互斥开关满足状态为turned on和当前连接的引脚为13时,同样返回true,其余状态均返回false,表示该互斥开关存在的串联电路不是一条通路。

  • 复合电路类

  由于存在多条并联电路串联在一起的情况,所以必须用两个map来分别存储多条并联电路和多条串联电路。在计算总电阻时,要计算串联电路的总电阻值,然后计算并联电路总电阻值,最后计算复合电路中总电阻值(其实也相当于计算串联电路的总电阻值,因为我将每一个并联电路看成一个设备)。
  与串联电路类似,在判断是否为通路时要添加对互斥开关的判断。
  再分配电压给设备更新状态时,受控窗帘要另外考虑,由于受控窗帘不是根据电压差的分配来更新自己的状态的,所以当遇到受控窗帘时需要跳出,而在最后所有设备状态更新后才根据电路中的光照强度来完成受控窗帘的更新。

if (device.getId().charAt(0)=='S'){
continue;
}

  需要添加一个函数用来计算电路中的总光照,由于提供光照的只有白炽灯和日光灯两种设备,所以提取他们更新后的设备光照值相加,最后才来更新受控窗帘的状态。

public void All_brightness(){
double all_brightness=0;
for (Device device:devices.values()) {
if (device.getId().charAt(0)=='R'||device.getId().charAt(0)=='B'){
all_brightness+= Double.parseDouble(device.getStatus());
}
}
for (Device device : devices.values()){
if(device.getId().charAt(0)=='S'){
ControlledCurtain controlledCurtain=(ControlledCurtain)device;
controlledCurtain.setBrightness(all_brightness);
controlledCurtain.updateStatus(controlledCurtain.getInputVoltage());
}
}
}

  最后在输出的时候要添加上新增的两个设备。

  • 解析类

  由于互斥开关存在于两条串联电路中,为了避免存储重复的互斥开关,所以要移除后加进来id相同的互斥开关,将之前已经添加进来的互斥开关分给这个电路,保证这两条串联电路共用一个互斥开关。这是解析类最主要的改动。
  由于存在多条并联电路,所以也需要用map来保存每一条并联电路。

  • 类图设计

  所有类都继承于电路类,这样做的好处就是,当我存在多条并联电路串联在一起的情况时,可以将并联电路看作是一个设备,他也有自己的属性,包括电阻、输入输出电压、电流等,此时的复合电路就相当于一条串联电路,处理起来会方便很多。
image


2.家居强电电路模拟程序-4

  最后一次大作业可谓是难度飙升,需要在我原来的基础上修改很多东西,比如说最终要输出设备的输入电压和输出电压,由于我之前的分配电压是计算总电阻来计算电流,最后再分配压差,所以没有运用到输入输出引脚电压值,所以需要改的东西非常多,加上临近期末周,所以我没有完成最后一次的大作业。


三、踩坑心得

1.第一次提交的时候犯了一个很傻的错误,导致一半的分没有得到,还好及时发现了这个错误没有纠结的太久。
image
首先可以发现问题主要集中在含义互斥开关的测试点中,所以我从互斥开关寻找问题,最后发现居然在最开始的正则表达式那里出了问题,忘了吧互斥开关的H添加进正则表达式里了,导致无法判断互斥开关的状态!!!
改正:
image
最后修改了这个问题提交上去已经得了九十几分了。

2.这次提交发现还是但串联电路含互斥开关的问题,所以我就自己编写了一个样例:

#T3:[VCC B2-1] [B2-2 K1-1] [K1-2 S1-1] [S1-2 H1-3] [H1-1 GND]
#K1
end

image
得到:
image
结果发现这并不是一条通路,白炽灯却能工作。最后我发现是因为在复合电路时,我忘记判断引脚的状态了,比如说上述例子的情况,应该被判断为不是一条通路,所以不进行分配电压的操作。


四、改进建议

  1.没有留有足够的修改空间,后续新功能加入困难
  在最后一次的大作业中需要加入的管脚电压,由于没有考虑过并且函数设计相对死板,没法直接加入计算的方法,所以修改起来实在困难,只能放弃。在今后的代码设计中,也要充分考虑未来新需求增加的可能性,实现功能的随时增加。

  2.抽象类使用不够灵活
  首先,没有将这些共有方法放在抽象类中意味着每个控制器类都需要单独实现这些方法,这会导致大量的重复代码。这不仅增加了代码的长度,也使得代码的维护变得困难。每当需要修改这些共有方法的行为时,开发者需要在每个控制器类中分别进行更改,这很容易引发错误和遗漏。

  3.学会自己寻找测试点
  在代码出现问题没有通过某些测试点的时候,要学会自己举例,通过这个例子进行调试,因为有些逻辑上的错误是很难看出来的,只有运用好了调试这个功能,才能更快的发现自己的错误所在


五、总结

  这两次题集虽然第一次完成的还可以,但是第二次由于时间紧张又或是难度太大我被吓退了,总之没有很好地完成。不过通过这几次的大作业我还是学习到了很多,我首先根据题目要求,对家居强电电路模拟系统进行了详细的需求分析与设计。通过构建系统的类图,明确了各个类的属性、方法以及它们之间的关系与交互。在开发过程中,我采用了面向对象的设计方法,将不同的“家具”作为独立的对象进行建模,通过封装属性和行为来确保对象的独立性和可扩展性。
  我觉得收获最大的还是我学会了如何进行调试,在许多逻辑上的代码不能一下子找到错误,而通过调试就能很快地锁定问题,从而解决问题,我觉得无论是做什么,都要掌握会调试的能力,这可以帮助我们很快地解决一些隐藏在代码中的不易被发现的问题。在最后几次的大作业中,我熟练的运用调试工具,这帮助我解决了很多没有通过的测试点!!
  虽然自己已经完成了许多代码的编写,但我知道我写的一定不是最好的,所以我认为可以拿出一些优秀的作业,供我们拜读,从其他人的代码中学到一些自己没有掌握的知识,我认为对我们以后写代码也是很有帮助的。另外的遗憾就是,没有完成最后一次的大作业,我认为我可以利用以后课外的时间,好好的完成一下最后一次大作业,我相信这样我的编程能力会更上一个台阶!
  最后,我觉得从这几次大作业来说,我的java编程能力得到了很大的进步,特别是在面向对象设计、数据结构应用和算法优化方面,我逐渐能够更加熟练地运用Java的各种特性,如继承、封装、多态等,同时在实际项目中也锻炼了我解决实际问题的能力。通过不断的实践,我不仅提升了编程技术,还增强了我的逻辑思维和问题分析能力,为以后更复杂的项目开发奠定了坚实的基础。