OOP前三次作业总结
1. 前言
前三次作业(即第四到六次作业)第四次作业大题目是答题程序四第五六次作业大题目是家居强电电路模拟程序,每次作业分别给了一个礼拜的时间去完成,题量较少,难度逐渐升高,以下为依次对三周题目集的知识点,题量和难度进行概述:
-
第四次作业:
主要是在前三次作业大题目的基础上将处理的题目变得更难了,将普通的单选题变成多选题和填空题,处理更加复杂,也要求使用继承知识来处理题目,当然处理器这个大题目以外还有两个题目也是主要考察继承这个知识点 -
第五次作业:
第五次作业有三道题,分别是大题目一
家居强电电路模拟程序1,题目大概是输入设备信息调节信息控制设备调节信息三种信息,然后输出信息按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。特点是只有一条串联电路,电路元件全部被串联在一起,所以实际上并不难,了解元件在电路上的位置,了解每个元件的工作原理即可完成这道题目,当然个别元件处理上有点细节没注意到会导致部分测试点过不去,这个等到踩坑心得部分具体说一下 -
第六次作业:
这次题目集只有一道题目即家居强电电路模拟程序2,这次迭代相比于上一次,它开始引入并联电路,也多了一个新元件,还需要考虑电阻,所以难度相比于上一次大了很多,相比于第一次大题目只需要用一些基础知识点就可以完成,这一次还需要利用多态继承来设计类,类之间关系也变得愈加复杂
2. 设计与分析 -
(1)先分析第四周题目集(结合类图,生成报表内容和题目源代码进行分析)重点分析最后一个大题目
最后一题的分析设计,最后一题在前三题的基础上学生信息、删除题目信息以及多种异常输入的监测,如答案为空字符、仅有学生信息没有答案内容的空白卷、试卷引用、试题引用错误等。同时也增加了更多信息输入,对信息提取整合的能力要求更高,这一次我不仅和之前一样设计了题目类(题号,题目内容,标准答案),试卷类(题目数量,题目清单),答卷类(试卷对象,答案列表,判断结果列表),还有新增的试卷题目类(试卷中题目的顺序号,题目对象,题目分值)和答案类(题目对象,学生答案,每一道题的正确性,对应得分),还设计了学生类,以下是我的类关系图,另外题目类不是普通的题目类,我设计了一个父类总题目类,还设计了三个子类为单选题目类,多选题目类,填空题类,每个子类中具体处理方法肯是不同的,以下是我的类图
-
(2)接下来是第五次作业的设计与分析,这次题目已经开启了新的迭代,也就是开始写新的大题目了要重新开始家居强电电路模拟程序,第一次迭代的处理都还算简单,只不过要细细读懂题目意思,一开始我没看懂题目本意导致走了很多弯路,觉得处理对象太多也太过于复杂,看懂了之后就还好,对于每个电器我都设计了对应的类,分别是开关(成员对象:编号,状态 成员方法:构造方法,修改器和访问器,调节开关的方法,输出电压的方法,输出设备信息的方法)状态默认是开着的,分档调速器(成员变量:编号,档位 成员方法:构造方法,修改器和访问器,调节档位,输出电压,输出设备信息),连续调速器(成员变量:编号 成员方法:构造方法,修改器和访问器,输出电压,输出设备信息),白炽灯(成员变量:编号 成员方法:构造方法,修改器和访问器,输出设备工作状态,输出设备信息),吊扇(成员变量:编号 成员方法:构造方法,修改器和访问器,输出设备工作状态,输出设备信息),日光灯(成员变量:编号 成员方法:构造方法,修改器和访问器,输出设备工作状态,输出设备信息),以下是大致类图,其中控制设备即为分档调速器和连续调速器,受控设备为日光灯,白炽灯和吊扇
不过有一点不同的是,我没有特别设计串联电路类,因为我发现给出的测试样例电路比较简单,可以直接分析和提取其中关键信息,因此我直接在主类中就进行了分析,当然这也导致了我有几个测试的过不去,分析电路的代码如下
while (sc.hasNextLine())
{
String lineh = sc.nextLine();
if ("end".equals(lineh)) {
// 遇到结束标记,停止读取
break;
}
String line2=lineh.substring(1);
// System.out.println(line2);
if(line2.charAt(0)'K')
{kaiguan.Switch();d=kaiguan.getDianya();}
else if(line2.charAt(0)'F')
{
if(line2.charAt(2)=='+')
fenduan.changeGear(1);
else
fenduan.changeGear(0);
d=fenduan.getDianya();
// fenduan.display();
}
else if(line2.charAt(0)=='L')
{
String line[]=line2.split(":");
double k=Double.parseDouble(line[1]);
d=lianxu.getDianya(k);
lianxu.display(k);
}
//数据处理完毕
}
像这样发现了电路中电器的排布规律,就可以直接分析啦,但是感觉还是很不严谨
输出信息的部分如下
if(s1)
kaiguan.display();
else if(s2)
fenduan.display();
if(h1)
diaoshan.display(d);
else if(h2)
baizhi.display(d);
else if(h==3)
riguang.display(d);
*(3)接下来是第六次题目集,第六次题目集币第五次难度上升很多,虽然看起来知识加了一个并联电路,但是实际处理起来很复杂,这次我除了设计第一次题目集的那些基础类,我还设计了一个受控设备的总父类,另外那些电器的基本变量我有添加了默认值为零的电压变量,还有串联电路类(成员变量:编号,存储串联电路上的电器的数组,电路上的电器个数,电路是否有效的标志变量,专门存储电路上开关的数组(为了和总电路上的开关区分开来) 成员方法:构造方法,修改器和访问器,添加数组成员到数组中的方法,计算电路总电阻的方法,将这条电路总电压按电阻比例分配到具体电器中去的方法,判断开关是不是这个电路里的,判断电路是否有效的方法)
以下是串联电路的具体代码
class T{
int num;
private Elefather[] elefathers=new Elefather[100];
//创建一个专门存开关的
private K[] kk=new K[100];
int count=0;
int kp=0;
int h=1;//h是电路是否有效的标志变量,默认值代表无效,即开关时断开的,默认有效
public T(int num){
this.num=num;
}
public int getNum(){
return this.num;
}
public void addElefather(Elefather elefather){
elefathers[count]=elefather;
count++;
if(elefather.getBp()==0)
{kk[kp]=(K)elefather;
kp++;}
}
//计算这条电路电阻
public int getR(){
int r=0;
for(int i=0;i<count;i++){
r=r+elefathers[i].getR();
}
// System.out.println(r);
return r;
}
public int getCount(){
return this.count;
}
public Elefather getElefather(int num){
return elefathers[num];
}
//将得到的这条电路总电压分配到具体的电器中去,就可以输出相关的电器信息了,不可以在这里输出
public void fenpei(double d){//0k,1b,2r,3d,4a
double h=0;
for(int i=0;i<count;i++){
if(elefathers[i].getBp()==0)
{
// K k=(K)elefathers[i];
// k.display();
}
else if(elefathers[i].getBp()==1)
{
h=(10.0/(this.getR()))*d;
elefathers[i].setD(h);
}
else if(elefathers[i].getBp()==2){
h=(5.0/(this.getR()))*d;
elefathers[i].setD(h);
}
else if(elefathers[i].getBp()==3){
// D dd=(D)elefathers[i];
h=(20.0/(this.getR()))*d;
// System.out.println(h);
// dd.display(h);
elefathers[i].setD(h);
}
else if(elefathers[i].getBp()==4){
// A a=(A)elefathers[i];
h=(20.0/(this.getR()))*d;
// a.display(h);
elefathers[i].setD(h);
}
}
}
//判断开启关闭的开关是不是这条电路里的
public int PanduanK(int num)//把开关的编号传入即可
{
int a=0;//不存在则保持值为0
for(int i=0;i<count;i++){
if(elefathers[i].getBp()==0&&elefathers[i].getNum()==num)
{a=1;//存在则返回1
}
}
return a;
}
//如果这个开关就是这条电路的那么开关决定这条电路是否有效
//一条电路上不止一个开关
public void PanduanY(int num){
for(int i=0;i<kp;i++)
{
if(kk[i].getNum()==num)
kk[i].Switch();
}
// for(int i=0;i<kp;i++){
// if(kk[i].getOn()==false)
// h=0;//如果有一个开关没有闭合则电路都无效
// }
// if(h==0)
// h=1;//h值为1代表有效,开关闭合
// else if(h==1)
// h=0;
// return h;
}
public void getT(){
for(int i=0;i<kp;i++){
if(kk[i].getOn()==false)
h=0;//如果有一个开关没有闭合则电路都无效
}
}
public int getH(){
this.getT();
return h;
}
}
还有一个并联电路类也很重要,成员变量是:存储其中串联电路的数组和串联电路的数量,也就是说串联电路做成员,成员方法作用分别是是:添加对应串联电路到数组中去,计算并联电路总电阻,判断并联电路是否有效,收到总电路给这条并联电路返回的电压要分到各串联电路中,以下为具体代码实现
class M{
private T[] tt=new T[100];
int count=0;
public void addT(T t){//把串联电路添加进去
tt[count]=t;
count++;
}
//计算这条并联电路的总电阻
public double getR(){
double a1=0.0;
double a2=0.0;
double a3=0.0;
for(int i=0;i<count;i++){
if(tt[i].getH()==1)//电路有效才加上它的电阻
{a3=(double)tt[i].getR();a1=a1+1.0/(a3);}
// System.out.println(tt[i].getR());
}
a2=1.0/a1;
// System.out.println(a2);
// int h=(int)a2;
return a2;
}
//收到总电路给这条并联电路返回的电压要分到各串联电路中,无效电路电压为0,这一步也把这条电路上的元件信息全部输出
public void fenPeidianya(double d){
for(int i=0;i<count;i++){
if(tt[i].getH()==1)//电路有效才进行分配
{tt[i].fenpei(d);}
else
tt[i].fenpei(0);
}
}
//需要一个判断整个并联电路是否有效的方法,只要其中有一条串联电路有效即可
public int panduanB(){
int h=0;//默认无效
for(int i=0;i<count;i++){
if(tt[i].getH()==1)//只要有一个有效即可
{h=1;break;}
}
return h;//0代表无效,1代表有效
}
}
除此之外,总的一个分析思路也是如下图
读取电路连接信息之后就开始进行线路连接(将元件添加至串并联电路中),再然后是对所有开关进行判断,判断串并联连通性,计算串并联电路总电阻,逐层分压,计算电路元件的工作状态,最后是排序并输出
3.采坑心得
(1)家居强电电路模拟程序1中分档调速器的边界问题,虽然题目背景中只给了四档的档位信息但是实际测试点中会有超出这四档的情况存在,这是很容易错的一个地方
比如我一开始知识这样设计输出电压的
public double getDianya(){
double d=0;
if(gear0)
d=0;
else if(gear1)
d=0.3220;
else if(gear==2)
d=0.6220;
else if(gear3)
d=0.9*220;
else if(gear4)
d=220;
return d;
}
考虑边界问题之后改成了这样就对了
public double getDianya(){
double d=0;
if(gear0||gear<0)
d=0;
else if(gear1)
d=0.3220;
else if(gear==2)
d=0.6220;
else //if(gear3)
d=0.9*220;
// else if(gear4)
// d=220;
return d;
}
(2)家居强电电路模拟程序1中还有一个点就是我一开始设计的时候考虑检测到哪个元件就创建哪个元件,也就是元件对象创建在if语句内,但是之后我还要用这个元件进行电压输入和信息输出这样的操作,这样写就会报错,运行错误,所以我改成了在处理电路信息之前就全部创建所有元件对象,具体代码实现如下
K kaiguan=new K();
F fenduan=new F();
L lianxu=new L();
D diaoshan=new D();
B baizhi=new B();
R riguang=new R();
(3)家居强电电路模拟程序2中很容易忽略的一个点就是容易没有考虑到总电路上开关和分电路开关上的区别,总电路开关没有闭合整条电路都是无效电压为0,单分电路开关无效可能只是这一条电路无效,不影响其他元件电压输入,所以我设计了一个串联电路方法用来判断开关是不是分电路上的,设计了专门数组来存储分电路上的开关,具体代码实现如下
//判断开启关闭的开关是不是这条电路里的
public int PanduanK(int num)//把开关的编号传入即可
{
int a=0;//不存在则保持值为0
for(int i=0;i<count;i++){
if(elefathers[i].getBp()0&&elefathers[i].getNum()num)
{a=1;//存在则返回1
}
}
return a;
}
(4)因为家居强电电路模拟程序2中我用了很多数组,所以数组的越界溢出问题也是易错点,比如你在加入新元素后马上又对数组大小扩充1了一位,那么下一次你使用数组时要注意,最后一个元素时数组大小再减一,这个很重要
(5)因为计算并联电路电阻会要求用多次除法,所以一般都是小数不是整数,我最开始使用的表达式时r=1/a,这样就不对,会出现计算错误,要用r=1.0/a,这样才能得出正确的小数,否则就是计算错误,比如下面这段计算并联电路总电阻的代码
public double getR(){
double a1=0.0;
double a2=0.0;
double a3=0.0;
for(int i=0;i<count;i++){
if(tt[i].getH()==1)//电路有效才加上它的电阻
{a3=(double)tt[i].getR();a1=a1+1.0/(a3);}
// System.out.println(tt[i].getR());
}
a2=1.0/a1;
// System.out.println(a2);
// int h=(int)a2;
return a2;
}
(6)第一次写家居强电电路模拟程序2的时候没有考虑到最后输出元件时,串联电路和主电路是在不同类中处理的,所以不能同时在主类中输出,所以我考虑串联电路元件在串联电路类中处理然后再赋回到主类中的元件数组2,具体代码实现如下
//接下来要把对应正确的电器加到数组中去,需要遍历每一条串联电路
int k0=0;int b1=0;int r2=0;int d3=0;int a4=0;
for(int i=0;i<countT;i++)
{
//遍历串联电路中的每个电器
for(int j=0;j<Ts[i].getCount();j++){
if(Ts[i].getElefather(j).getBp()0)
{//0k,1b,2r,3d,4a
// Ks[k0]=(K)Ts[i].getElefather(j);
// k0++;
}
else if(Ts[i].getElefather(j).getBp()1)
{//0k,1b,2r,3d,4a
Bs[b1]=(B)Ts[i].getElefather(j);
b1++;
}
else if(Ts[i].getElefather(j).getBp()2)
{//0k,1b,2r,3d,4a
Rs[r2]=(R)Ts[i].getElefather(j);
r2++;
}
else if(Ts[i].getElefather(j).getBp()3)
{//0k,1b,2r,3d,4a
Ds[d3]=(D)Ts[i].getElefather(j);
d3++;
}
else if(Ts[i].getElefather(j).getBp()==4)
{//0k,1b,2r,3d,4a
As[a4]=(A)Ts[i].getElefather(j);
a4++;
}
}
}
4.改进建议
1.类设计的更为清晰简练,像本次作业我很多类设计了方法但又没有使用,这样降低了代码的可读性和美观,很拖沓
2.使用更高效的方法,像本次作业大题目我一开始考虑用动态数组来储存多张试卷答卷,这样不会有错但是并不方便,后来我改用了HashMap来储存,键存的是试卷号等等,这样查找起来更方便快捷高效
3.错误处理和异常管理,合理地处理潜在的错误情况,避免程序崩溃。使用异常来处理异常情况,而不是返回错误代码。(崩溃无数次非零返回无数次了
4.代码需要精进,像家居强电电路模拟程序2中我无效代码太多
5.总结
通过本三次作业集我学会了类的基本设计,类之间的关系设计,Java语言中接口的基本概念及使用方法,输入数据分析分割(正则表达式),已封装类的使用,类继承多态,程序设计中常用数据结构的用法等等,仍需学习改进的部分是对HashMap特殊类和类多态的使用,这部分我并不熟练,与此同时在分析数据时经常碰到的空格问题也需要进一步去解决,因为经常导致非零返回。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~