OOP第三次Blog作业
前言
距离上一次写Blog作业已经过去差不多一个月了,但在这段时间之中我与代码的交锋无时无刻不在进行,先不说结果怎么样,单就这过程就值得人细细琢磨,并且令人印象深刻。当然,经过这一段时间艰苦的磨练,我也学到了许多之前不曾了解的东西复习巩固了已经学过的知识点,我相信我的编程能力也会有所提升,同时,他们都说写代码最考验的就是耐心,我觉得确实如此,有的时候某一个或某几个测试点过不了就会比较影响心情,然后就会想着把它改正确,这过程需要不断的debug,这么就没锻炼耐心呢?不过话说回来,无论学哪一个科目,耐心都是必不可少的!
下面开始7~8次PTA的总结性报告:
- 所涉及到的知识点:
- List的应用
- 正则表达式
- HashMap、setMap等
- 简单工厂模式的应用
- 继承与多态
- 接口的灵活运用
- 有关电路知识的考查
- 题量:
7~8次的pta练习每次都仅仅有一道题目,but!你以为每次一道题目就很好写完吗?就会很快写完吗?大错特错!这里的一道题目考察了多方面知识的灵活运用。 - 难度:
前面提到题量不多,但考察的内容多,这无疑会增加题目的难度,这两次的PTA考查的深度较之前确实大有增加,而且题目的测试点考虑的情况也是多方面的,但是依然有同学能拿到满分!
设计与分析
家居强电电路模拟程序三
nchu-software-oop-2024-上-7
这次的迭代题目集相较于第二次迭代有了以下新增内容:
- 互斥开关
互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。
开关电路示意图如图1所示,左边是汇总引脚,编号为1;右边两个是分支引脚,右上的输出引脚为2,右下输出引脚为3。图中1、2、3引脚均可以是输入引脚,当1为输入引脚时,2、3引脚为输出引脚;1为输出引脚时,2、3引脚为输入引脚。
互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。
互斥开关的默认状态为1、2引脚接通,1、3引脚断开。
图1中所示的互斥开关可以反过来接入电路,即汇总引脚接往接地端,两个分支引脚接往电源端。
为避免短路,互斥开关设置了限流电阻,12引脚之间默认电阻为5,13引脚之间默认电阻为10。
2. 受控窗帘
受控窗帘的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。窗帘电阻为15
当电路中所有灯光的光照强度总和在[0,50)lux范围内,窗帘全开;
在[50,100)lux范围内,窗帘打开比例为0.8;
在[100,200)lux范围内,窗帘打开比例为0.6;
在[200,300)lux范围内,窗帘打开比例为0.4;
在[300,400)lux范围内,窗帘打开比例为0.2;
在400lux及以上范围内,窗帘关闭。
当电压低于50V,窗帘不工作,默认为全开状态。
如果电路中没有灯或者灯全部关闭,光照强度为0,窗帘处于全开状态。
- 电路连接
本次迭代考虑多个并联电路串联在一起的情况。
本题考虑一条串联电路中包含其他串联电路的情况。例如:
#T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND]
本例中T1\T2两条串联电路T3的一个部分,本题考虑这种类型的输入。
- 类图如下:
从这张类图中可以看到一共有16个类,相较于上次迭代的14个类,这次增加了互斥开关类和受控窗帘类,互斥开关类的设计和应用都是蛮难的,因为互斥开关有三个引脚,而且不同的引脚可能出现在不同的串联电路中,对应互斥开关的不同情况,串联电路的连通情况可能不相同,为此,我在串联电路类中添加了一个属性,代表该串联电路是对应互斥开关的第几个引脚,然后在判断串联电路是否连通时也做了一些修改:
通过判断串联电路的引脚和互斥开关的引脚是否相等来判断其是否连通。当然,这就需要在存储互斥开关相关信息的时候获取其引脚:
- SourceMonitor生成报表:
ennnnnn从图中看来,相较于上次的最大进步就是注释的比例,已经达到了预期范围。不过最大圈复杂度还是超过了预期的范围,看来以后还是要尽量少用点if-else等对圈复杂度贡献较大的语句啊。由此看来学习编程之路任重而道远啊!!! - 踩坑心得:
做题之前要认真分析题目!(尽管题目实在是太长了还是要认真看!
)就比如这次题目,刚开始的时候,对于这次迭代我还是只注意到了互斥开关和受控窗帘,后来才发现电路连接方面还有变化,于是做了如下修改:
就是串联中可能还会有串联的情况,我是把里面一层串联中的电气设备都放到外面一层的串联中。 - 改进建议
- if-else可以少用,这样可以提高代码质量。
- 并联中应该考虑有三层串联一起并联的情况。(我当时没有考虑这种情况,所以并没有得满分,老师设置测试点时考虑的情况还是很全面的! )
家居强电电路模拟程序八
nchu-software-oop-2024-上-6
这次迭代可谓是发生了巨大变化,不仅电器增加了二极管,就连输出都有很大变化,要输出每个引脚的电流,和每个电器的电压,以及电路中的电流是否超过最大电流时输出情况也有所不同:
- 新增的电器二极管:
增加二极管元件,其电路特性为:正向导通,反向截止;其电器符号如图4所示,当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。
图2 二极管符号
二极管的标识符为’P’,左侧管脚编号为1,右侧管脚编号为2。
二极管如果两端电压相等,没有电流流过,分以下两种情况输出:
a、如果两端电压为0,二极管的导通/截止状态由接入方向决定,1号引脚靠近电源则状态为导通,反之为截止。
b、如果两端电压不为0,二极管导通。
2. 输出格式:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、互斥开关、受控窗帘、二极管(见第6部分说明)的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。
输出格式:
@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位)+" "+设备所有引脚的电压(按编号从小到大顺序依次输出,电压的小数部分直接丢弃,保留整数输出,电压之间用”-”分隔)
说明:
连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。
开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed
如:
@K1:turned on 32-15
@B1:190 68-17
@L1:0.60 220-176
互斥开关按1、2引脚的接通状态显示,1,2接通-1,3断开时显示closed,1,3接通-1,2断开时显示turned on。
如:
@H1:turned on
受控窗帘显示窗帘打开的百分比,如:
@S1:80%
3. 增加管脚电压的显示
在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。(格式详见输出信息部分)
4. 电流限制
电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。
例如:@B1:190 68-17 exceeding current limit error
本题各类电器的最大限定电流如下:
开关20、分档调速器18、连续调速器18、白炽灯9、日光灯5、吊扇12、落地扇14、互斥开关20、受控窗帘12、二极管8。
- 短路检测
如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error” - 并联电路中包含并联
本次迭代考虑并联电路中包含并联电路的情况,即构成并联电路的串联电路可以包含别的并联电路。例如如下输入的电路,并联电路M2的其中一条串联电路T4中包含了另一条并联电路M1:
#T1:[IN D2-1] [D2-2 H1-2] [H1-1 OUT]
#T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]
#M1:[T1 T2]
#T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]
#T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]
#M2:[T4 T5]
- 本题包含以下电路图中的所有连接情况:
- 类图如下:
这次多增加了一个二极管类。由于这次输出的结果相较于之前有了较大的改变,需要得出电路中的电流,电器各个引脚的电压,所以增加了方法:
public void getpower(T t,double input,double output){
if(t.getRes()==0){
for(int i=0;i<t.getList().size();i++) {
if (t.getList().get(i).getId().contains("K")) {
t.getList().get(i).setPin1(input);
if(t.getList().get(i).getState().equals("closed")){
t.getList().get(i).setPin2(input);
}else {
break;
}
}
else if(t.getList().get(i).getId().contains("H")){
int g=t.getA();
if(g==2){
t.getList().get(i).setPin2(input);
}
if(g==3){
((MutexSwitch)t.getList().get(i)).setPin3(input);
}
else{
t.getList().get(i).setPin1(input);
}
} else if (t.getList().get(i).getId().contains("P")) {
if( ((Diode)t.getList().get(i)).getState().equals("cutoff")){
t.getList().get(i).setPin2(input);
input=0;
}
else{
t.getList().get(i).setPin1(input);
t.getList().get(i).setPin2(input);
}
} else if (t.getList().get(i).getId().contains("M")) {
for(int k=0;k<((M)t.getList().get(i)).getList().size();k++){
getpower(((M)t.getList().get(i)).getList().get(k),input,0);
}
} else{
t.getList().get(i).setPin1(input);
t.getList().get(i).setPin2(input);
}
}
}else{
double pindif=input-output;
double ele=pindif/t.getRes();
for(int i=0;i<t.getList().size();i++){
if(!(t.getList().get(i).getId().contains("M")))
t.getList().get(i).setEle(ele);
}
for(int i=0;i<t.getList().size();i++){
if(!(t.getList().get(i).getId().contains("M"))){
if(t.getList().get(i).getId().contains("H")){
int p=t.getA();
if(p==1){
t.getList().get(i).setPin1(input);
} else if (p==2) {
t.getList().get(i).setPin2(input);
} else if (p==3) {
((MutexSwitch)t.getList().get(i)).setPin3(input);
}
input = input - ele * t.getList().get(i).getRes();
}else {
t.getList().get(i).setPin1(input);
input = input - ele * t.getList().get(i).getRes();
t.getList().get(i).setPin2(input);
if(t.getList().get(i).getId().contains("S")){
((Curtain)t.getList().get(i)).getS(getall(tmo));
}
}
}
else if(t.getList().get(i).getId().contains("M")){
for(int k=0;k<((M)t.getList().get(i)).getList().size();k++){
double pindif1=t.getList().get(i).getRes()*ele;
double output1=input-pindif1;
getpower(((M)t.getList().get(i)).getList().get(k),input,output1);
}
input=input-t.getList().get(i).getRes()*ele;
}
}
}
}
同时判断某串联电路是否是通路也有所不同,这次不仅仅只看开关是否关闭,二极管接入电路的方向也要考虑:
public boolean istrue(T t){
boolean flag=true;
for(int i=0;i<t.getList().size();i++){
if(t.getList().get(i).getId().contains("K")){
if(t.getList().get(i).getState().equals("turned on")){
flag=false;
break;
}
}
if(t.getList().get(i).getId().contains("H")){
if((t.getA()==2)&&(((MutexSwitch)t.getList().get(i)).getA()==3)){
flag=false;
break;
}
if(t.getA()==3&&(((MutexSwitch)t.getList().get(i)).getA()==2)){
flag=false;
break;
}
}
if(t.getList().get(i).getId().contains("P")){
if(((Diode)t.getList().get(i)).getState().equals("cutoff")){
flag=false;
break;
}
}
if(t.getList().get(i).getId().contains("M")){
int p=0;
for(int j=0;j<((M)t.getList().get(i)).getList().size();j++){
if(istrue(((M)t.getList().get(i)).getList().get(j)))
p++;
}
if(p==0){
flag=false;
break;
}
}
}
return flag;
}
- SourceMonitor生成报表:
哎~这次还是有问题,还是最大圈复杂度!但是呢,有的情况是真的避免不了啊,就比如解析输入字符串,看来,还需要找更好的方法来解决这个问题。 - 踩坑心得:
计算电路中电阻还是挺麻烦的,所以后来我在串联电路类,并联电路类中分别写了一个计算电阻的函数:
串联电路:
public double getRes(){
double all=0;
if(istrue(this)) {
for (int i = 0; i < list.size(); i++) {
all = all + list.get(i).getRes();
}
}
return all;
}
并联电路:
public double getRes(){
double all=0;
for(int i=0;i<list.size();i++){
if(istrue(list.get(i))) {
all = all + (1 / list.get(i).getRes());
}
}
return 1/all;
}
- 改进建议:
这次的得分不是很高,后来我看了下,有一部分原因出在电器中引脚的电压值,就比如白炽灯,它两个引脚无论正接还是反接,效果都是一样的,但是引脚的电压值却不同,而我在解析输入的时候并没有判断是不是正接,也就是说我在存储的时候默认是正接,这导致后来输出每个引脚电压值的时候可能会出现相反的结果,所以,如果要改进的话我觉得可以在解析输入的时候判断一下电气设备的引脚的输入顺序。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)