Java-第二次blog作业
一.前言
以及接下来我将根据我的实际情况总结第四、五、六次PTA题目集中最后一题并讲诉自己对Java的学习心得。从这三次PTA作业中学习并使用了Java中的继承,除学习到了许多关于Java继承的使用以外,还通过这几次的PTA作业,对子类和父类的差别及共同点有了深刻理解。在此三次作业中,使用ArrayList实现数组的自增。
二.设计与分析
(1)第四次PTA最后一题
7-3 答题判题程序-4
分数 82
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。本题在答题判题程序-3基础上新增的内容统一附加在输出格式说明之后,用粗体标明。
本次题目主要对前三次答题判题程序进行迭代,所以本次并没有新增太多内容。在本次迭代中,输入新增:选择题、多选题、填空题,输入不要求试卷必须在题目后出现。输出新增:多选题的结果可以有部分正确:"partially correct",输出顺序改变,出现多学生、多试卷的情况。
对于新增部分的输入,我增加了两个问题类的子类:Selectpro、Fillpro,用于创建选择题和填空题。而对于输出中多的结果部分正确的要求,我修改了原先的判断方法,并将判断结果的方法放在问题类中。
修改部分代码如下:
新增类:
点击查看代码
class Selectpro extends Program {
public Selectpro() {
}
public void setAll(String s) {
this.setNo(Integer.parseInt(Grading.getstring(s, "#Z:", "#Q:").trim()));
this.setContent(Grading.getstring(s,"#Q:","#A:").trim());
this.setStandard(s.substring(s.indexOf("#A:")+3).trim());
this.setExist(true);
this.setFlag('Z');
}
}
class Fillpro extends Program {
public Fillpro() {
}
public void setAll(String s) {
this.setNo(Integer.parseInt(Grading.getstring(s, "#K:", "#Q:").trim()));
this.setContent(Grading.getstring(s,"#Q:","#A:").trim());
this.setStandard(s.substring(s.indexOf("#A:")+3).trim());
this.setExist(true);
this.setFlag('K');
}
}
点击查看代码
public String justice(String s) {
String[] str = s.trim().split("\\s+");
for(String strs:str) {
if(!this.standard.contains(strs)) {
return "false";
}
}
if(s.length()<this.standard.length())
return "partially correct";
return "true";
}
报表如下

左边可以看到代码最主要关心的几个方面,能够一目了然看出哪些方面还需要改进。虽然进行了一点改善,但由于是前几次任务的迭代,导致最大圈复杂度改了之后依旧很高。而且,因为前几次没怎么写注释,所以现在也懒得加了。
类图如下

提交结果:


心得:
本次作业难点在于:对多余空格、输入空字符串的处理。总体还是对上次的迭代,迭代不算太难。但测试点是真的难找,有提示都找不出来,导致最后的那个错误还是不知道怎么错的。
此次已经是第四次作业了,所以没有下一次了。在本次作业中,我切实感受到了来自测试点的深深的恶意,各种不同情况的测试点需要我自己找到问题,而且对空格以及空字符串的处理让我精疲力竭。不过由于本次主要是对上几次的迭代,此次并没出现太多问题。提前把各个功能划分到类中和对类的划分让我节省了许多精力,也提升了代码的可阅读性。在修改错误时也因为迭代的原因,所以只需检查本次扩展的部分,极大的节省了时间。其次也简化了代码。让我感受到面向对象编程的便利。
(2)第五次PTA最后一题
7-1 家居强电电路模拟程序-1
分数 75
作者 蔡轲
单位 南昌航空大学
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。
本次题目主要是对继承的使用,我设计了父类:Eletronic,和它的子类:K、F、L、B、D、R,用于表示开关等设备。在父类中设置属性name用于表示设备名称,leftvolt、rightvolt用于表示设备左右电压,rank用于表示控制设备的开关、档位,subvolt表示设备两侧的电压差,lux表示设备的光照强度,rpm表示设备的转速,important表示优先级。其中,优先级用于确定最后的输出顺序。另外设计了排序类:sort,用于根据优先级排序;操作类:operation,用于放置所有的操作。
报表如下:

从报表中可以看出本次代码的注释率较低,可能需要增加注释以提高代码的可读性。每个类中的方法数量和每个方法的语句数量都相对适中,这意味着类和方法的职责分配比较正常,类和方法没有承担太多的职责和逻辑。圈复杂度和最大嵌套深度的值意味着代码中有非常长的嵌套结构,可能难以维护和理解,通过降低这些值可以提高代码的可维护性。不过大多数代码块的语句数量较少,有助于保持代码的简洁和易于理解。
类图如下:

其中,Eletronic类作为父类,包含了所有子类可能出现的属性,这样子类只需使用自己所需要的部分,简化了代码。并且每个类都封装了自己的属性和方法,通过 getter 和 setter 方法来访问和修改属性。同时系统设计允许通过添加新的子类来扩展电子元件的类型,这使得本次程序具有良好的扩展性。通过将通用属性和方法集中在 Electronic 类中,因为任何通用的更改只需要在一个地方进行,这让程序的维护变得更加容易。
父类代码如下:
点击查看代码
class Eletronic {
private String name;
private double leftvolt;
private double rightvolt;
private double rank = 0;
private double subvolt = 0;
private double lux = 0;
private double rpm = 0;
private int important = 0;//优先级
public Eletronic() {
}
public Eletronic(String name, double leftvolt, double rightvolt) {
this.name = name;
this.leftvolt = leftvolt;
this.rightvolt = rightvolt;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getLeftvolt() {
return leftvolt;
}
public void setLeftvolt(double leftvolt) {
this.leftvolt = leftvolt;
}
public double getRightvolt() {
return rightvolt;
}
public void setRightvolt(double rightvolt) {
this.rightvolt = rightvolt;
}
public void setRightvolt() {
;
}
public double getRank() {
return rank;
}
public void setRank(double rank) {
this.rank = rank;
}
public double getSubvolt() {
return subvolt;
}
public void setSubvolt() {
if(Math.abs(getLeftvolt() - getRightvolt()) >= 220)
subvolt = 220;
this.subvolt = Math.abs(getLeftvolt() - getRightvolt());
}
public double getLux() {
return lux;
}
public void setLux(double lux) {
this.lux = lux;
}
public double getRpm() {
return rpm;
}
public void setRpm(double rpm) {
this.rpm = rpm;
}
public double gainlux() {return 0;}
public void amendrank() {
;
}
public void amendrank(String s) {
;
}
public double gainrpm() {return 0;}
public int getImportant() {
return important;
}
public void setImportant(int important) {
this.important = important;
}
public void print() {
;
}
}
心得:
本次难点、关键点主要有:电路模拟的复杂性:需要模拟不同类型的控制设备(开关、分档调速器、连续调速器)和受控设备(白炽灯、日光灯、吊扇)的行为。状态管理:每个设备都有特定的状态或档位,需要正确地初始化并在模拟过程中更新这些状态。电压计算:需要根据连接信息和设备的调节信息计算电路中各点的电压,这涉及到电压的传递和转换。设备行为模拟:模拟设备如灯和风扇的亮度和转速与电压的关系,需要根据电压差来确定设备的工作状态。输入信息解析:需要解析输入信息,包括设备信息、连接信息和控制设备调节信息,这可能涉及到复杂的字符串处理。输出格式要求:输出信息需要按照特定的格式,包括设备状态的转换(如开关的开/关状态转换为文字描述)。精度处理:在计算过程中需要使用 double 类型来避免精度误差,但在输出时需要截断小数部分。约束条件的遵守:需要遵守题目中提到的约束条件,如不考虑两个输出引脚短接、调速器串联、并联接入或反馈接入等。
(2)第六次PTA最后一题
7-1 家居强电电路模拟程序-2
分数 100
作者 蔡轲
单位 南昌航空大学
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。以下题目介绍中加粗的部分为本次迭代在“家居强电电路模拟程序-1”的基础上增加的功能要求。
本次增加:受控设备:落地扇。工作电压区间为 [80V,150V],对应转速区间为 80-360 转/分钟。电压在[80,100)V 区间对应转速为 80 转/分 钟,[100-120)V 区间对应转速为 160 转/分钟,[120-140)V 区间对应转速为 260 转/分钟,超过 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况),本次迭代考虑电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落地扇的电阻为 20。本次迭代的连接信息不单独输入,包含在线路信息中。包括本次迭代出现并联电路。
报表如下:

从该图可以看出本次的Java代码质量相对较好,具有较高的注释率,适中的方法数量和语句数,以及较低的平均和最大复杂度。然而,最大嵌套深度为7可能需要进一步关注,以确保代码的可读性。此外,块直方图显示大多数代码块较短,这有助于降低代码的复杂度和提高可维护性。
类图如下:

相较上一次类图,本次迭代增加了串联电路类、并联电路类,用于存放串联及并联电路的信息。并且在父类中增加了rohm作为电阻属性,增加function类保存所有对电路的信息如是否短路、断路的获取。
新增部分代码如下:
点击查看代码
class A extends Eletronic {//吊扇类
public A() {
this.setImportant(6);
this.setRohm(20);
}
public A(String name, double leftvolt, double rightvolt) {
super(name, leftvolt, rightvolt);
this.setRohm(20);
}
public double gainrpm() {
if(this.getSubvolt() < 80)
setRpm(0);
else if(this.getSubvolt() < 100) {
setRpm(80);
} else if (this.getSubvolt() < 120) {
setRpm(160);
} else if (this.getSubvolt() < 140) {
setRpm(260);
} else {
setRpm(360);
}
return this.getRpm();
}
public void print() {
BigDecimal rpm = new BigDecimal(this.gainrpm());
rpm = rpm.setScale(0, RoundingMode.DOWN);
System.out.println("@" + this.getName() + ":" + rpm);
}
}
class Tcircuit {
public String id;
public double rohm = 0;
public ArrayList<Eletronic> tcircuit = new ArrayList<>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<Eletronic> getTcircuit() {
return tcircuit;
}
public void setTcircuit(ArrayList<Eletronic> tcircuit) {
this.tcircuit = tcircuit;
}
public double getRohm() {
return rohm;
}
public void setRohm(double rohm) {
this.rohm = rohm;
}
}
class Mcircuit {
public String id;
String mcircuit;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMcircuit() {
return mcircuit;
}
public void setMcircuit(String mcircuit) {
this.mcircuit = mcircuit;
}
}
class function {
public static ArrayList<Eletronic> sort(ArrayList<Eletronic> ele) {
for(int i=0;i<ele.size();i++) {
for(int j=i+1;j<ele.size();j++) {
if(ele.get(i).getImportant()>ele.get(j).getImportant()||(ele.get(i).getImportant()==ele.get(j).getImportant()&&ele.get(i).getName().compareTo(ele.get(j).getName())>-1)) {
Eletronic t = ele.get(i);
ele.set(i,ele.get(j));
ele.set(j,t);
}
}
}
return ele;
}
public static boolean getK(Tcircuit t) {
boolean flag = true;
for(Eletronic ele:t.tcircuit) {
if(ele.getName().contains("K")&&ele.getRank()<1)
flag = false;
}
return flag;
}
public static boolean shortcircuit(Tcircuit t) {
boolean flag = true;
for(Eletronic ele:t.tcircuit) {
if(!ele.getName().contains("K")) {
flag = false;
break;
}
}
if(getK(t)&&flag) {
return true;
} else {
return false;
}
}
public static void setluxrpm(Tcircuit t,double i) {
for (Eletronic ele : t.tcircuit) {//设置支路亮度、转速
ele.setSubvolt(i);
ele.gainlux();
ele.gainrpm();
}
}
}
提交结果


经过思考和询问同学后发现是由于double的精度导致本来计算电压为200的值,变成197.999999997,省略小数后变成197导致错误。不过由于发现的太晚,没时间改了所有只能不了了之,在下一次PTA大作业前将解决该问题。
心得:
本次迭代难点主要有:并联电路的引入导致电路总电阻不好计算,另外并联导致可能出现短路的情况,需考虑到短路导致的支路总电阻为0。还有新加入的设备也需要再写一个子类继承Electrol类。不过好在上次代码写的还好,进行扩展没花费太多时间。主要在于错误测试点的寻找,本次测试点一点提示信息都没有,导致我们很难发现问题出现在哪。我觉得这是非常不合理的,就应该给出足够的提示信息。没有谁能保证自己的代码一次过,而且一点信息都没有,导致时间全浪费在找错误的测试点上了,导致就算最后找到问题也不一定有时间修改。此外,本来PTA就已经导致课后时间的极大削减,经过寻找测试点的问题后,更是没多少时间去写别的作业,别的作业也是有截止时间的。
三.踩坑心得
这三次主要踩的坑就是对错误测试点对应问题的寻找,以及对double类型精度问题的解决上。出现非零返回的问题已经算是最好解决的错了,因为它会直接告诉你错误的语句。并且非零返回一般是因为定义和使用数组导致越界或出现空指针。还有在第六次作业中,并联导致的短路问题的处理,以及在这次大作业中光顾着处理并联电路,没考虑到处理单一的串联电路问题了。此外,还有对封装后的属性的获取需要用到get、set方法,直接写的话,属性的值会对不上。
四.改进建议
将重复的代码片段(如在Operation类中的if语句块)抽象成方法,以减少代码重复。将大型的类和方法拆分成更小的单元,以提高代码的可读性和可维护性。遵循Java的命名约定,例如类名应该以大写字母开头,方法和变量名应该以小写字母开头。避免在循环中进行不必要的计算,例如在sumRohm方法中,如果发现短路,应立即返回0,而不是继续循环。
五.总结
通过这三次PTA作业,我逐步实现了一个功能完善的答题判题程序以及开始了家居强电电路模拟程序的设计。对Java中继承的掌握也更加深刻。以及从这几次迭代中深刻体会到了最开始如果设计好的话,后续的迭代也将更轻松。在这几次的大作业中,我更多的考虑了代码的可读性和可扩展性。如增加代码中注释的编写和尽可能让单一的一个类中就只具有它对应的方法。这让我代码的迭代更轻松,也更简洁了。这些经验对我未来的编程学习和实践将非常有帮助。

浙公网安备 33010602011771号