第4~6次PTA大作业总结
第4~6次PTA总结
一、前言
在第4至第6次PTA大作业中,我们依次完成了答题判题程序4及家居强电电路模拟程序的1和2。通过前三次大作业的锻炼,我已基本掌握了Java的核心知识,并能灵活运用。经过前几次的积累与反思,我在类的设计上积累了宝贵的经验,能够更加全面地考虑设计细节,注意后续代码的迭代。同时,我也在代码注释和命名规范上变得更加注重,确保了代码的可读性和维护性。
1.答题判题程序4
(1)知识点总结
由于题目新增了选择题和填空题,我们需要使用父类和子类的继承结构。此外,答题判题程序4与程序3类似,都需要使用Map来存储题目、试卷和学生等信息,并通过正则表达式解析输入,确保其格式符合要求。
(2)题量
本题的题量与第三次大作业相当,任务较为繁重。为了完美完成任务,需妥善处理多种输入格式错误和乱序输入的情况,这要求对各种可能的情形进行全面考虑,需要投入大量时间。此外本题目还需要考虑选择题以及填空题部分正确的情况。
(3)难度
我认为,本次大作业相较于前几次大作业,在难度上有了较大的提升。本次大作业不仅引入了新的题型——选择题和填空题,而且还涉及到部分正确答案的判定,并且本题目还要求我们熟练掌握父类和子类的继承结构,这无疑增加了任务的复杂性。
2.家居强电电路模拟程序1
(1)知识点总结
由于本次大作业未涉及输入错误格式的判断,因此无需使用正则表达式,可以通过substring
和split
等方法直接对输入进行分割和解析。此外,本次大作业还需要利用Map
来存储各个电器的状态和相关数据。本次大作业的核心知识点在于父类与子类的继承结构,让控制设备以及受控设备继承设备类,这样的设计提高了代码的复用性,以及系统的灵活性。
(2)题量
鉴于这是家居强电电路模拟程序的首次大作业,我认为本次大作业的题量相对较小,只需要处理一个串联电路。
(3)难度
鉴于这是家居强电电路模拟程序的首次大作业,本次大作业只有一条线路且所有元件串联,难度属于比较小,只需要考虑清楚一条线路中有多个开关的情况,即可顺利完成。
3.家居强电电路模拟程序2
(1)知识点总结
与家居强电电路模拟程序1类似,本次大作业同样未涉及输入错误格式的判断,因此无需使用正则表达式。可以直接通过substring
和split
等方法对输入进行分割和解析。同时,本次大作业依然需要应用父类与子类的继承结构。
不同于上次,本次我选择了TreeMap
来存储各个电器的状态及相关数据。使用TreeMap
能够实现按照键值对存入的设备自动进行排序,这不仅减少了手动排序的工作量,还优化了代码结构。
(2)题量
本次大作业相较于家居强电电路模拟程序1,题量显著增加,属于中等偏上。新增了并联电路的处理,这意味着需要考虑更多设备的状态及其相互影响。我们必须根据每个电器的电阻来计算其分压,进而确定并输出每个电器的工作状态。这要求我们对电路原理有更深入的理解,并在编程实现时更加细致和精确。
(3)难度
本次大作业相较于家居强电电路模拟程序1,难度显著提升,达到了中等偏上的水平。本次作业不仅需要处理多种不同类型的设备和复杂的连接方式,还加入了并联电路的元素。这要求我们不仅要准确判断电路的断开与闭合状态,还要精确计算分压和电阻,这需要我们进行细致的分析和周密的考虑。
二、设计分析
1.答题判题程序4
答题判题程序4相比于答题判题程序4新增了填空题与选择题,以及答案部分正确的判断。
由于前三次答题判题程序的类设计较为混乱,所有的类都集中于答卷类中处理并输出结果,于是我对整体结构进行重新设计。为此,我修改并新增了一些类,以改善代码的组织结构并完成该本次大作业。
1.类图:
2.时序图:
3.source monitor报表:
4.代码分析:
1.选择题类、填空题类、普通题目类
选择题类、填空题类以及普通题目类均继承自题目类,选择题类和填空题类各自添加了判断答案正确性的方法。通过使用正则表达式,将标准答案和输入的答案按空格或“或”进行分割,再对比分割后的答案,以确定答案的正确性并输出相应的结果。
2.答卷类
由于之前的答卷类功能过于冗杂,导致整体代码结构混乱,我对其进行了简化,减少了答卷类的职责。
修改前,答卷类不仅负责存储答卷信息,还包含了题库、答卷集、学生集等属性,并承担了最终结果的判断与输出职责。这种设计导致类的职责过于集中,使得代码结构臃肿,不易维护和扩展。
修改后,答卷类仅负责存储答卷相关的信息。这样不仅使代码结构更加清晰,也提高了代码的可维护性和可读性。
3.判断类
为了简化答卷类,我新创建了一个判断类来承担原先答卷类中被削减的职责。
判断类整合了题库类、答卷集类、学生集类和试卷集类的功能,通过调用这些类的方法并处理它们存储的信息,实现了最终结果的判断与输出。这不仅使各模块职责更加明确,也提升了代码的整体结构和可维护性。
4.解析类
通过正则表达式验证输入的合法性,若输入合法,则解析输入并将其存储到相应的类中。
5.试卷集类
使用Map存储输入的多个试卷。
6.学生集类
使用Map存储输入的多个学生。
7.答卷集
使用Map存储输入的多个答卷。
8.题库类
使用Map存储输入的多个题目。
2.家居强电电路模拟程序1
由于本题目仅涉及一个串联电路,整体难度相对较低。主要任务是对不同设备创建相应的类,成功解析用户的输入信息,对指定设备执行相关操作,并按顺序输出各设备的状态。
1.类图:
2.时序图:
3.source monitor报表:
4.代码分析:
1.设备类
设备类包含电压和设备编号等属性,并提供了一些基本方法,是所有其他特定设备类的父类。
2.开关类
开关类继承自设备类,并且新增了开关转态的属性以及一些基本方法,除此之外还新增了改变状态的方法setState()
,开关的初始状态为false,代表开关断开,每次调用setState()
,开关状态取反。
3.分档调速器类
分档调速器继承自设备类,新增了档位属性及一些基本方法。此外,还添加了档位改变方法changeGears(String symbol)
和改变电压方法changeVoltage(double voltage)
。通过判断输入的符号,可以增加或减少档位,而电压则根据当前档位的变化进行调整。
4.连续调速器类
连续调速器继承自设备类,新增了档位属性及一些基本方法。此外,还添加了改变电压的方法changeVoltage(double voltage)
,电压值等于档位乘以原始电压。
5.白炽灯类
白炽灯类继承自设备类,新增了亮度属性及一些基本方法。此外,还添加了改变亮度的方法ChangeBrightness(double voltage)
。根据不同电压值,白炽灯会输出不同的亮度。
6.日炽灯类
日炽灯类继承自设备类,新增了亮度属性及一些基本方法。此外,还添加了改变亮度的方法ChangeBrightness(double voltage)
。根据不同电压值,日炽灯会输出不同的亮度。
7.风扇类
风扇类继承自设备类,新增了转速属性及一些基本方法。此外,还添加了改变转速的方法ChangeSpeed(double voltage)
。根据不同电压值,风扇类会输出不同的转速。
8.设备库类
使用Map
存储不同设备的相关数据。根据题目要求,需要按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇的顺序依次输出所有设备的状态或参数,每个设备占一行。同类设备需按编号从小到大的顺序输出。为此,我为每种设备类分别创建了一个Map
,并将它们按编号顺序依次存储在各自的Map
中。
private Map<Integer,Devices> KMap = new HashMap<Integer,Devices>();
private Map<Integer,Devices> FMap=new HashMap<Integer,Devices>();
private Map<Integer,Devices> LMap=new HashMap<Integer,Devices>();
private Map<Integer,Devices> BMap=new HashMap<Integer,Devices>();
private Map<Integer,Devices> RMap=new HashMap<Integer,Devices>();
private Map<Integer,Devices> DMap=new HashMap<Integer,Devices>();
完成本次题目后,我了解到可以使用TreeMap
来存储设备的相关信息。通过以设备标识符加编号作为索引,TreeMap
支持自定义排序规则,能够自动对设备进行排序,从而优化了代码结构,提高了效率。
9.解析类
这个类是我此次题目代码中的核心部分,主要通过split
和substring
方法实现对用户输入每一行的解析。如果输入的是设备信息,将解析出的设备类型及其编号存储到对应的设备库Map
中;如果是设备操作信息,则根据设备编号从设备库中调取相应的设备,并执行相应的操作。
10.输出类
这个类的主要职责是按照顺序输出设备库中存储的设备信息。
这个类有一个关键之处在于判断电路最终的断开或闭合状态。我通过一个名为switchFlag
的变量来实现这一点,每次将switchFlag
与当前开关的状态进行逻辑运算,最终确定整个电路的开关状态。
switchFlag &= ((Switch) device).getState();
3.家居强电电路模拟程序2
相较于家居强电电路模拟程序1,本次题目新增了并联电路及电阻的处理。为此,我们需要增加一个串联电路类和一个并联电路类,并将串联电路或并联电路视为一个整体设备,计算其总电阻。首先,根据总电阻计算电路中各部分的分压,然后将这些分压值应用于串联电路或并联电路中,进一步计算其中各设备的具体电压及其状态。本次题目中,使用TreeMap
能够通过索引自动对设备进行排序,从而提升编码效率。此外,通过将断开的开关的电阻视为无穷大,极大地方便了最终判断电路是否处于断开状态。
1.类图:
2.时序图:
3.source monitor报表:
4.代码分析:
1.设备类
相较于前一个模拟程序,本次更新引入了电阻属性。现在,系统需基于电路中各组件的电阻值来计算电压分配,进而确定各组件的具体工作状态。
2.串联电路类
串联电路类继承自设备类,并使用TreeMap
来存储其包含的设备信息。TreeMap
的键是设备的索引,值是对应的设备对象。为了确保设备按索引顺序自动排序,TreeMap
使用了自定义比较器CustomComparator
进行初始化。
串联电路类中定义了一个方法void AllResistance()
,用于计算整个串联电路的总电阻。在计算过程中,可以将整个串联电路视为一个单一的电气设备,通过累加TreeMap
中所有设备的电阻值来得到总电阻。基于计算出的总电阻,可以进一步计算每个设备上的分压,从而确定每个设备的工作状态。
Comparator<String> customComparator = new Comparator<String>() {
public int compare(String o1, String o2) {
// 提取标识符和数字部分
String prefix1 = o1.replaceAll("[0-9]", "");
String prefix2 = o2.replaceAll("[0-9]", "");
Integer num1 = Integer.valueOf(o1.replaceAll("[^0-9]", ""));
Integer num2 = Integer.valueOf(o2.replaceAll("[^0-9]", ""));
// 定义标识符的顺序
String order = "KFLBRDAM";
// 比较标识符的顺序
int indexComparison = Integer.compare(order.indexOf(prefix1), order.indexOf(prefix2));
// 如果标识符相同, 则比较数字
if (indexComparison == 0) {
return num1.compareTo(num2);
} else {
return indexComparison;
}
}
};
3.并联电路类
并联电路类继承自设备类,并包含一个属性串联电路集,用于存储组成并联电路的多个串联电路。
并联电路类中定义了一个方法double AllResistance()
,用于计算整个并联电路的总电阻。在计算过程中,可以将整个并联电路视为一个单一的电气设备,通过计算所有串联电路的总电阻来得出并联电路的总电阻。基于计算出的总电阻,可以进一步计算并联电路的分压,从而确定其工作状态。
4.最终电路类
最终电路类继承自设备类,并包含一个TreeMap
类型的属性circuitMap
,用于存储最终电路中的所有设备。circuitMap
的键是设备的索引,值是对应的设备对象,包括并联电路和串联电路,它们均以电气设备的形式存入。
最终电路类中可以通过计算最终电路的总电阻,再结合各个设备的电阻值和总电阻来计算每个设备的分压,从而确定每个设备的工作状态。
5.串联电路集类
串联电路集类包含一个HashMap
类型的属性circuitMap
,用于存储所有串联电路的信息。circuitMap
的键是电路的标识符,值是对应的串联电路对象。
6.设备库类
设备库类包含一个TreeMap
类型的属性devicesTreeMap
,用于存储整个电路中所有受控设备和控制设备的信息。devicesTreeMap
的键是设备的唯一标识符,值是对应的设备对象。该属性最终用于按顺序输出所有受控设备和控制设备的状态。
7.解析输入类
解析输入类包含以下属性:设备库、并联电路、串联电路集和总电路。该类的作用是通过substring
和split
方法解析用户输入,并将解析后的信息存入相应的类中。
8.输出类
输出类包含以下属性:设备库、最终电路、并联电路和串联电路库。该类的主要功能是:
- 循环遍历最终电路中的所有设备,根据计算的分压值更新每个设备的状态。
- 如果遍历到的设备是并联电路,则进一步循环遍历该并联电路中的所有串联电路,根据并联电路的分压值依次计算并更新每个串联电路中设备的状态。
三、采坑心得
- 在编写答题判题程序4时,由于答题判题程序3的类设计存在诸多问题,导致我在开发过程中遇到了不少困难,特别是一些类承担了过多的职责,甚至出现了相互引用的情况,这使得系统的结构变得复杂且难以理解。同时,程序中缺乏足够的注释,导致代码的可读性和可维护性大打折扣。在这种情况下,我不得不花费大量的时间重新设计类的结构,理清各个类之间的关系和职责。为了避免类似问题的发生,我深刻认识到在未来的类设计中,必须严格遵循合理的职责划分和清晰的分工,每个类应当只承担单一的职责,避免出现职责重叠或过度耦合的情况。此外,类与类之间的关系要尽量简化,减少不必要的相互依赖,确保系统具备更高的可维护性和可扩展性。在设计类时,也要注意添加充分的注释,帮助后续开发人员更好地理解代码逻辑,从而减少因理解偏差带来的额外开发时间和错误。
- 在写家居强电电路模拟程序1时,我意识到自己在Java基础语法方面的知识还不够全面,导致在设计时未能充分利用Java的一些内置功能。例如,最初我没有了解到
TreeMap
可以实现自动排序,反而为每个设备单独设置了一个HashMap
,这种做法不仅增加了代码的复杂度,还浪费了大量的开发时间。通过这一经验,我认识到,熟悉并灵活运用Java的标准库和内置功能,能够有效简化代码,减少重复工作,从而优化代码结构,提高程序的性能和可维护性。 - 在写家居强电电路模拟程序2时,程序中大量使用了
switch-case
和if-else
语句,导致代码逻辑变得繁杂,圈复杂度较高。这种设计不仅使得代码的可读性和可维护性降低,还可能影响程序的执行效率,尤其是当条件判断过多时,增加了代码的复杂度和出错的风险。在这种情况下,我意识到需要优化程序结构,减少不必要的条件判断,可以使用更简洁和高效的设计模式。
四、改进建议
1.答题判题程序4
- 代码中的解析部分目前是直接在主类中编写解析函数,通过这些函数来解析用户输入。为了提高代码的模块化和可维护性,可以将解析部分单独抽象为一个专门的类。这样做可以提高代码的模块化、增强可维护性、促进代码复用。
- 由于第三次类设计较为混乱,导致类的结构和逻辑不够清晰,影响了代码的可读性和可维护性。在第四次设计中,我们在第三次的基础上进行了重新设计、优化与改进,但仍可能存在一些类的设计不够完善的情况。为了进一步提升代码质量,需要进一步对代码进行优化与完善。
2.家居强电电路模拟程序1
- 由于最初不了解
TreeMap
的自动排序功能,在设计设备库时为每个设备单独设置了一个HashMap
。这导致了代码的冗余和不必要的复杂性。实际上,可以使用TreeMap
来存储设备信息,利用其自动排序特性来管理设备的顺序。这样不仅可以简化代码结构,还能提高数据管理和查询的效率。 - 使用了大量的
switch-case
和if-else
语句,这导致代码结构变得冗长且复杂。过多的条件判断不仅增加了代码的维护难度,还可能影响程序的可读性和性能。为了改善这一情况,可以使用以下几种优化方法:- 使用多态:通过定义抽象类或接口,并让不同的子类实现特定的行为,可以减少大量的条件判断。
- 查找表:使用哈希表或其他数据结构来存储条件和对应的操作,从而避免复杂的条件判断。
- 函数指针或Lambda表达式:在支持函数指针或Lambda表达式的语言中,可以将条件逻辑封装成函数,并通过函数指针或Lambda表达式来调用。
- 可以将白炽灯和日炽灯重新抽象出一个抽象父类——灯类,将亮度作为灯的属性,并将改变亮度的方法定义为抽象方法。同理,对于连续调速器和分档调速器,也可以进行相同的操作。
3.家居强电电路模拟程序2
- 可以将落地风扇和吊扇重新抽象出一个抽象父类——风扇类,将转速作为风扇的属性,并将改变转速的方法定义为抽象方法。
- 解析并联电路中的设备的代码采用了三层嵌套的
for
循环。这种多层嵌套的循环结构虽然能够有效地遍历和处理复杂的电路结构,但也可能导致代码复杂度增加,影响可读性和维护性。可以使用递归方法来处理并联电路中的设备,这样可以使代码更加简洁和易读。 - 使用了大量的
switch-case
和if-else
语句,这导致代码结构变得冗长且复杂。过多的条件判断不仅增加了代码的维护难度,还可能影响程序的可读性和性能。为了改善这一情况,可以使用以下几种优化方法:- 使用多态:通过定义抽象类或接口,并让不同的子类实现特定的行为,可以减少大量的条件判断。
- 查找表:使用哈希表或其他数据结构来存储条件和对应的操作,从而避免复杂的条件判断。
- 函数指针或Lambda表达式:在支持函数指针或Lambda表达式的语言中,可以将条件逻辑封装成函数,并通过函数指针或Lambda表达式来调用。
- 可以将设备类设为抽象类,并将计算电阻的方法设为抽象方法。由于普通设备、串联电路和并联电路的电阻计算方法不同,因此可以在各个子类中具体实现该方法。
五、总结
通过完成第4至第6次PTA大作业,我在Java编程的学习过程中积累了丰富的实践经验。每一次的任务不仅帮助我巩固了Java语言的基础知识,更让我深刻理解了面向对象编程的核心思想,并在实际问题中得到了应用和强化。尤其是在类设计、代码结构优化以及如何高效处理复杂逻辑等方面,我获得了宝贵的经验。在这三次大作业中,我逐步掌握了更加高级的Java特性和设计模式。通过使用继承、多态、抽象类、接口等面向对象编程特性,我能够更好地组织代码,简化设计,提升代码的可维护性和可扩展性。例如,在答题判题程序4中,我通过引入父类和子类的继承结构,优化了类的职责分配,使得代码更加简洁、易读且便于维护。而在家居强电电路模拟程序中,我通过使用TreeMap
来实现设备的自动排序,大大提高了数据管理的效率。在开发过程中,我遇到了很多问题,并通过不断的思考和反思来找到解决方案。例如,在答题判题程序4中,原本类的设计过于冗杂,职责划分不清晰,导致了系统难以维护。为了改进,我重新设计了类的结构,并将相关功能进行了合理拆分,最终使得程序结构更为清晰。类似的问题也出现在家居强电电路模拟程序1和2中,在实现设备管理和电路运算时,我不断优化了数据结构的使用,避免了不必要的重复工作。此外,我在开发过程中,逐渐意识到代码的复杂度和执行效率之间的平衡,避免过多的条件判断,减少嵌套和冗余的代码,这不仅提升了程序的性能,也提高了代码的可读性和可维护性。通过对每个大作业的总结,我也发现了许多可以改进的地方。例如,在家居强电电路模拟程序1中,由于最初未能充分利用TreeMap
的自动排序功能,我的设计比较繁琐,导致了不必要的重复工作。虽然最终我通过优化改进了这一部分,但在编写代码时,提前熟悉并充分利用Java的标准库和内置功能,能够更高效地解决问题。在答题判题程序4的设计中,由于原始类的结构设计不佳,我花费了较多时间进行重构。未来在设计类时,我会更加注重合理的职责划分和简洁的结构,避免过多的耦合,确保类的高内聚低耦合,以提高代码的可维护性和可扩展性。通过这三次大作业,我不仅提升了Java编程的能力,也加深了对面向对象设计的理解。在未来的编程实践中,我将更加注重代码的结构化和模块化设计,合理使用设计模式来解决复杂问题。对于大型项目,我会更加关注代码的可读性和可维护性,采用合适的工具和框架,简化开发过程,提升开发效率。同时,我也会持续学习新技术和最佳实践,不断优化编程技能,为更高层次的编程挑战做好准备。总的来说,通过这三次大作业,我获得了大量的实践经验,深入了解了如何在实际项目中应用Java的各项特性,同时也发现了自己的不足,并在实践中不断进步。随着技术水平的提升,我相信自己能够在未来的编程工作中迎接更加复杂的挑战,并不断提升自己的综合能力。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)