题目集7~8的总结性Blog
一 、前言:
总结两次次题目集的知识点、题量、难度等情况
知识点
这两次题目集综合考察了java语言三大特性中的多态,子类与父类的继承关系、方法重写,信息处理、比较,排序输出,类的对象创建有无参数的不同构造方法、属性的访问权限等知识点,对类的设计要求提高,java中的封装与继承,多个类的设计,类与类之间的关系考虑,向下转型,compare接口的使用,集合接口的实例化,迭代器,数据的查找、排序,字符串处理,正则表达式,类型转换,类与对象、方法的使用,方法的调用与返回,多个类的关系与使用、链表或哈希表、遍历方法,面向对象的封装性,类的设计等知识点。集合了前几次的知识点于一体考察。
题目及题量、难度
nchu-software-oop-2024-上-7:
7-1 家居强电电路模拟程序-3
是之前电路模拟程序的第三次迭代,增加了两种电器:互斥开关和窗帘,增加了考虑多个并联电路串联在一起的情况、一条串联电路中包含其他串联电路的情况。难点有很多,比如互斥开关的连接状态判断,多并联电路的互相影响。
nchu-software-oop-2024-上-8:
7-1 家居强电电路模拟程序-4
超级超级难,没有设计思路。这次迭代增加了很多内容:增加管脚电压的显示,最大电流的限制显示,短路检测,并联电路中包含并联电路,增加了二极管。我对管脚电压的显示没有什么设计思路,可能是因为之前几次没有怎么考虑过引脚电压,只考虑过引脚的顺序。在增加的部分中短路的检测和最大电流的限制显示还是很简单的,难点在于引脚电压。
二、第三次的家居强电电路模拟程序分析
设计与分析
第三次的家居强电电路模拟程序类图以及SourceMontor的生成报表内容:


这一次的迭代中增加了一种开关(互斥开关H类)和一种受控设备(窗帘S类)。H类继承SW类,S类继承Lead类。
对于互斥开关,有三个引脚,输入该元器件信息时要注意不同引脚连的不同的对应的电路。互斥开关的切换与开关的切换略有不同,要切换电路接通状态还有改变电阻。需注意的一点就是输出互斥开关的状态时是输出互斥开关中引脚1和引脚2的接通状态。
对于窗帘,窗帘的打开程度与整个电路中电器发出的亮度有关,所以我写了一个light方法用于计算整个电路中的光照强度。
- H类:用于表示互斥开关。包含了一个无参构造方法和一个有参构造方法,用于初始化互斥开关对象。
提供了:
Z方法:用于切换开关。原先是引脚12接通切换后变为引脚13接通且电阻变为10,原先是引脚13接通切换后变为引脚12接通且电阻变为2。
print方法:用于输出该互斥开关的引脚12的接通状态。 - S类:用于表示并联电路,包括光照强度(light)、窗帘的打开比例(b)。包含了一个无参构造方法和一个有参构造方法,用于初始化窗帘对象。
提供了:
light方法:用于计算整个电路中的光照强度。
U方法:用于计算该窗帘的打开比例。根据不同的光照强度设置不同的打开比例。
print方法:用于输出该窗帘的打开比例。
点击查看代码
class H extends SW{//互斥开关
public H() {}
public H(int lead1,String name) {
super(lead1,name);
switch (lead1) {
case 1: {
h=2;
x=1;
break;
}
case 2: {
h=2;
x=1;
break;
}
case 3: {
h=3;
x=1;
break;
}
default:
throw new IllegalArgumentException("Unexpected value: " + lead1);
}
k=9;
R=5;//12连
hsString=this.name+"-"+"2";
}
public void Z()
{
if(x==1)
{h=3;hsString=this.name+"-"+h;
x=0;R=10;}
else if (x==0)
{x=1;h=2;hsString=this.name+"-"+h;
R=5;}
}
public void print()
{
if(x==1)
System.out.println("@"+name+":closed");
else
System.out.println("@"+name+":turned on");
}
}
class S extends Lead{//窗帘
double light=0;
double b=1;
public S() {}
public S(int lead1,String name) {
super(lead1,name);
k=10;
R=15;
}
public double light(Array array) {
for (int i = 0; i < array.arrayList.size(); ++i) {
if (array.arrayList.get(i).k==4||array.arrayList.get(i).k==5)
//System.out.print(array.arrayList.get(i).name+" "+array.arrayList.get(i).light(array));
light+=array.arrayList.get(i).light(array);
}
return light;
}
public void U() {
if (u<50||light==0) {
b=1;
}
else if(light>=50&&light<100){
b=0.8;
}
else if(light>=100&&light<200) {
b=0.6;
}
else if(light>=200&&light<300) {
b=0.4;
}
else if(light>=300&&light<400) {
b=0.2;
}
else {
b=0;
}
b=b*100;
}
public void print() {
//System.out.println(light+" "+b);
this.U();
System.out.println("@"+name+":"+ (int)b+"%");
}
}
踩坑心得
我主要是卡在互斥开关。。。


样例四卡了很久很久

而我的

- 在设计互斥开关时,一开始我默认输入引脚为1时这条电路连的另一个引脚就是2,没有考虑到引脚输入顺序的问题。还有一个需要注意的点在于互斥开关所连的两条电路的状态会受到该互斥开关的连接影响,切换开关时对应的电路状态也可能随之变化。一定一定要记得切换开关后重新判断下电路的状态!我一开始就漏了修改电路状态和电路内元器件的状态、电压等。
- 这次的电路信息变复杂了 ,一条串联电路中也可以含有其他的串联电路,一条串联电路中也可以含有多条并联电路,我一开始把电路信息单独存储,导致串联电路中有串联电路时会找不到,或者不会将串联电路连入主电路等。所以我改变了电路的信息的存储。
- 窗帘的打开比例计算!这里这个比例与整个电路中电器发出的光照强度对应成比例,一定要注意是整个电路,而且要注意计算光照强度应该在所有开关状态切换完毕、所有电器都完成工作后再计算。计算中要注意题目默认规则:所有数据以double类型存储,输出整型(连续调档器除外),所以在计算光照强度时也是用double类型保存数据。
- 电器元件输出时的顺序!没有考虑按字典序排序啊,导致有几个测试点没有通过。我的输出顺序只是对类型排了序,对于同类型的不同电器元件,输出顺序与输入顺序一致,这里是不对的,类型排完序应该对名字排序即字典序排序。
改进建议
- 在串联电路series类中设计了一个方法函数用于判断互斥开关与该电路是否连通。
点击查看代码
public int h(Lead lead,String s,int num) {
Pattern pattern=Pattern.compile("(H\\d+)-(\\d+)");//互斥开关名字与连接引脚
Matcher matcher=pattern.matcher(lead.hsString);//该电路的互斥开关信息
Matcher matcher2=pattern.matcher(s);//被比较的互斥开关
if (matcher.matches()) {
if (matcher2.matches()) {
//System.out.println(lead.hsString+" "+s);
if (matcher.group(1).equals(matcher2.group(1))) {
if (matcher.group(2).equals(matcher2.group(2))) {
return 1;//连通
}
else {
return 0;//断开
}
}
}
}
else {
return 1;}//连通
return 1;//连通
}
- 在窗帘S类中设计了一个方法函数用于计算整个电路里的光照强度。
点击查看代码
public double light(Array array) {
for (int i = 0; i < array.arrayList.size(); ++i) {
if (array.arrayList.get(i).k==4||array.arrayList.get(i).k==5) //会发出光照的电器
//System.out.print(array.arrayList.get(i).name+" "+array.arrayList.get(i).light(array));
light+=array.arrayList.get(i).light(array);
}
return light;
}
- 在电器元件类里修改了排序接口,增加了对字符串的比较。
点击查看代码
public int compareTo(Object o) {
Lead student=(Lead)(o);
if (this.k==student.k) {
return this.name.compareTo(student.name);
}
return this.k-student.k;
}
三、第四次的家居强电电路模拟程序分析
这次的代码大作业没怎么写,就拿了十五分,写了下短路的判断,没有什么思路,就简单分析下。

设计与分析
这次的大作业增加了很多内容:
- 管脚电压的显示:这个内容我没太有设计思路,可能是之前偷懒了,在前几次电路程序的设计时,引脚没有与电压相关,只是单纯的输入输出,也没有把这个作为连接电路的依据,上次写互斥开关时才开始考虑引脚。而这次显示管脚的电压把我难住了,一开始我认为两边的电压不应该一样吗?后来想想物理,好像不太对,两管脚的电压差是这个电器元件的电压,明白了这个后,电路中单电器或电器加电阻为0的多电器的还好,电压只需要考虑那个电阻不为0的电器元件,但是多元件且电阻都不为0的怎么办呢,我没有什么思路。
- 电流限制:每个电器会有最大电流,这个部分我写了一点,拿窗帘来举个例吧,我在电器元件Lead类中增加了I属性用于表示最大电流。在输出电器元件信息时进行电流判断,超过则输出“exceeding current limit error”。
点击查看代码
class S extends Lead{//窗帘
double light=0;
double b=1;
public S() {}
public S(int lead1,String name) {
super(lead1,name);
k=10;
R=15;
I=12;
}
public double light(Array array) {
for (int i = 0; i < array.arrayList.size(); ++i) {
if (array.arrayList.get(i).k==4||array.arrayList.get(i).k==5)
//System.out.print(array.arrayList.get(i).name+" "+array.arrayList.get(i).light(array));
light+=array.arrayList.get(i).light(array);
}
return light;
}
public void U() {
if (u<50||light==0) {
b=1;
}
else if(light>=50&&light<100){
b=0.8;
}
else if(light>=100&&light<200) {
b=0.6;
}
else if(light>=200&&light<300) {
b=0.4;
}
else if(light>=300&&light<400) {
b=0.2;
}
else {
b=0;
}
b=b*100;
}
public void print() {
//System.out.println(light+" "+b);
this.U();
l();
if(x==1)
{
if (this.i>this.I) {
System.out.println("@"+name+":"+ (int)b+"%"+" "+lead1+"-"+lead2+" exceeding current limit error");
}
else
System.out.println("@"+name+":"+ (int)b+"%"+" "+lead1+"-"+lead2);
}
else if(x==0)
System.out.println("@"+name+":"+ (int)b+"%"+" "+lead1+"-"+lead2);
}
}
- 短路检测:对每个串联电路进行检测。所以我直接在操作方法中增加对串联电路的判断,一旦发现就结束整个程序的运行,输出“short circuit error”。
点击查看代码
for(int i=0;i<=ss;i++)
{
//System.out.println(series[i].x+" "+series[i].R+series[i].name);
if(series[i].x==1&&series[i].R==0)
{
System.out.println("short circuit error");
System.exit(0);
}
}
-
并联电路中包含并联:我改变了并联的存储,增加并联电路时同时将该电路增加到所有电器元件的链表中,这样并联电路内查找其他并联电路也能找到并将其作为自己的一部分。
-
增加了一个电器元件-二极管:正向通过,反向截止,这对输入二极管信息时就要考虑输入的管脚顺序,而我之前忽略了管脚的顺序,所以设计起来有点没思路了。在补充以下之前我还是设计了一下二极管的类。但是补充后没思路了就没继续设计了。

点击查看代码
class P extends Lead{//二极管
public P() {}
public P(int lead1,String name) {
super(lead1,name);
k=11;
R=0;
I=8;
if(lead1==1)
this.x=1;
else
this.x=0;
}
public void print() {
l();
if(this.x==1) {
if (this.i>this.I) {
System.out.println("@"+name+":conduction"+" "+lead1+"-"+lead2+" exceeding current limit error");
}
else
System.out.println("@"+name+":conduction"+" "+lead1+"-"+lead2);}
else
System.out.println("@"+name+":cutoff"+" "+lead1+"-"+lead2);
}
}
四、总结:
在这两次大作业中只完成了一次,也是感觉自己写的很不好,虽然第三次电路模拟程序拿到了满分,但是写的很乱,有很多函数方法都没有做到单一职责原则,用了很多if-else,虽然也在尽量用一用switch语句了。代码中也有很多功能一样的语句重复重复重复没有合并,写的时候老是想到什么写什么,提前设计的总是在真正实践中改了又改,还是设计的意识不够强,设计思路不够清晰。
在这学期的面向对象设计课程的八次大作业中,感觉到每一次大作业老师都在培养我们提前设计的意识,这几次大作业老师发布的时间总是比预计的晚,但是老师会提前把题面发出来,目的应该就是让我们提前思考,设计一下,这样开始写的时候不会毫无头绪、杂乱无章(虽然我做的不是很好,但是每一次大作业都感觉自己进步了一点点)。
从第一次设计答题判题程序到最后一次的家居强电电路模拟程序,代码的复杂性越来越高,代码也越来越长。记得第一次听老师说大作业的代码长度从300行会到700行到1000行甚至更多,我的第一反应是我做的到吗?写不出来这么多吧,而事实时在最后一次拿到满分的大作业中我的代码长度是900行,挺长了。一次次的迭代中类越来越多,类与类之间的关系也越来越复杂。
在我完成的这八次大作业中,虽然除了最后一次的迭代没有设计思路,其他都拿到了满分,但是仍然有很多可以改进的地方:依然没有很好的实现函数单一职责,但是一次比一次强吧,总算会把功能相同类似的代码合并成一个函数了。记得之前的代码主类里只有一个主函数,在一次次的迭代中我学会分类了,将一些功能单拎出来成为一个函数,虽然有些函数的功能比还是很复杂;没有提前设计的意识,总是想到什么写什么,想用那个数据就直接用了,没有考虑数据的私有化,就直接调用,导致代码的安全性、灵活性都不高。不过经过这一学期的大作业磨练后,我明白了提前设计的重要性,提前设计真的能帮助我们在实践功能时有明确的思路,知道写这些是为了干什么。最后啊,最后一次的大作业真的好难,然后就是可惜看不到老师是怎么写这些题目的,感觉每次代码的改进都是自己慢慢悟出来的,如果能在作业截至后看到老师是怎么具体实现我认为很难实现的功能,应该能学到更多。

浙公网安备 33010602011771号