南昌航空大学 22207209-侯智慧-第二次blog作业
一、前言
在过去的一个月中,我全身心地投入到了Javapta课程的学习中,尤其是三次极具挑战性的大作业。这些作业不仅是对我Java编程技能的考验,也是我在计算机科学领域不断探索和成长的重要里程碑。
最近的一次大作业是关于家庭电路管理系统的开发。最初接触这个项目时,我感到有些不知所措。这个项目要求我们运用不同的Java特性,从基本的面向对象编程到复杂的数据结构和算法优化,以实现一个能够模拟和管理家庭电路的应用程序。
在这个项目中,我需要设计一个系统来模拟家庭电路的各种组件,比如开关、插座、灯泡等,并实现它们之间的交互。面对这些挑战,我逐渐意识到,学习编程不仅仅是掌握语法和工具,更是培养一种解决问题的思维方式。
在项目进行过程中,我不断遇到各种技术难题和逻辑陷阱。有时候,一个小小的错误可能会花费数小时甚至数天去调试和修复。然而,正是在这些反复试错和不断迭代的过程中,我的编程能力得到了显著提升。我学会了如何更有效地调试代码,如何优化算法以提高程序效率,以及如何在团队协作中利用版本控制工具来管理项目。
此外,这个作业也让我深刻体会到理论与实践相结合的重要性。在课堂上学到的概念,只有通过实际编码和项目应用,才能真正内化为自己的技能。每次成功解决一个棘手的问题,或者在项目中实现一个新功能,都会让我感受到极大的成就感和满足感。
在这篇博客中,我将详细分享这个家庭电路项目的背景、我所采用的解决方案,以及在过程中积累的经验和教训。我希望这些分享不仅能帮助其他正在学习Java的同学,也能为那些对编程充满好奇和热情的人提供一些有用的启示。编程之路漫漫,但每一步的努力和探索都值得我们珍惜和回味。让我们一起继续这段充满挑战的学习旅程吧!
二、设计与分析
1.第四次作业7-3 答题判题程序-4
(1)难度分析:
这道题目涉及多种类型的题目处理,包括选择题和填空题,每种题目类型都有其特定的评分规则。此外,题目还要求处理多张试卷和多名学生的答卷信息,并根据学号和试卷号进行排序输出。
- 题目解析与输入处理:
需要解析不同格式的输入信息,包括选择题、填空题、试卷信息、学生信息等。每种输入格式都有其特定的标识符(如#Z:、#K:、#T:等),需要正确识别并解析。
输入信息可能无序,因此需要在解析时做好信息的存储和关联。 - 评分规则的实现:
选择题和填空题有各自不同的评分规则,尤其是在处理多选题和部分正确的答案时,需要仔细判断学生答卷与标准答案的匹配程度。
需要考虑部分正确答案的得分计算,并处理得分截尾的问题。 - 多张试卷和多名学生的处理:
需要正确关联试卷信息和学生答卷,并根据试卷的题目分值进行评分。
在输出时,需要根据学号和试卷号进行排序,这涉及到对数据结构的选择和排序算法的实现。 - 输出格式的要求:
输出不仅包括每道题目的评分结果,还需要计算每名学生在每张试卷上的总分。
需要检测试卷的总分是否为100分,并在不满足时输出相应的警告信息。
(2)知识点分析:
- 面向对象编程(OOP):
抽象类和继承:Question类是一个抽象类,定义了所有题目的基本属性和方法。SingleChoiceQuestion、MultipleChoiceQuestion、FillInTheBlankQuestion继承自Question,并实现了抽象方法evaluateAnswer。
封装:类中的属性通常是私有的,通过公共方法(getter和setter)访问,以保护数据的完整性。
多态:通过使用抽象类和接口,允许不同的题目类型实现自己的答案评估方法。 - 集合框架:
List和Set:使用ArrayList来存储题目、试卷、学生和答卷信息。HashSet用于处理多选题和填空题的答案匹配。
Map:HashMap用于在答卷中存储题号和学生答案的对应关系。 - 字符串处理:
使用String.split()方法对输入字符串进行分割,以提取相关信息。
使用trim()方法去除字符串首尾的空格,确保数据的准确性。
使用正则表达式对输入格式进行验证和匹配。
(3)类图和顺序图设计
(4)踩坑心得 - 填空题缺少情况
N:1 #Q:1+1= #A:2
K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴
T:1 1-5 2-10
X:20201103 Tom
S:1 20201103 #A:1-5 #A:2-七弦琴或瑶琴
end
当答案变换顺序,也应该是满分
Set
Set
用或字分隔可以将正确答案匹配出来,无论什么顺序都可以匹配成功。
- 填空题缺少情况
N:1 #Q:1+1= #A:2
K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴
T:1 1-5 2-10
X:20201103 Tom
S:1 20201103 #A:1-5 #A:2-瑶琴或古琴
end
当有一个答案是错误的应该0分
for (String studentAns : studentAnswers) {
for (char c : studentAns.toCharArray()) {
if (!trimmedAnswer.contains(String.valueOf(c))) {
return getContent() + "~" + studentAnswer + "~false";
}
}
}
检查学生答案中是否有错误字符,有错误字符该题就为0分
*格式错误
N:1 #Q:1+1= #A:2
Z:2 #Q:党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信 #A:A B C D
T:1 1-5 2-9
X:20201103 Tom
S:1 20201103 #A:1-5 #A:2-A C
end
S:1 20201103 #A:1-5 #A:2-A C 这个输入无论后面有多少的空格,只需要删除答案后面的一个空格就可以
// 判断答案是否为空格,如果是,则删除
if (answer.endsWith(" ")) {
answer = answer.substring(0, answer.length() - 1); // 删除最后一个空格
}
2.第五次作业7-1 家居强电电路模拟程序-1
(1)难度分析:
- 电路模拟的复杂性
设备多样性:题目要求模拟多种设备,包括开关、分档调速器、连续调速器、白炽灯、日光灯和吊扇。每种设备都有不同的工作特性和状态参数,需要分别进行建模和模拟。
电路连接:需要处理设备之间的连接信息,确保按照正确的电路连接顺序进行模拟。尤其是在处理串联和并联电路时,需要确保连接的正确性和完整性。
电压和状态计算:设备的输出状态或参数(如亮度、转速)依赖于输入电压或电位差,需要根据设备的特性进行正确的计算和模拟。 - 输入解析的复杂性
多种输入格式:输入信息包括设备信息、连接信息、控制设备调节信息等,格式各异,需要设计灵活的解析器来处理不同类型的输入。
输入约束:需要验证输入的合法性,例如确保连接信息按照电路顺序输入,调速器的输入端只接VCC等。 - 输出要求的复杂性
格式化输出:根据设备的类型和状态,输出格式需要符合特定的要求,如开关的状态显示、连续调速器的档位保留两位小数等。
排序输出:需要按设备类型和编号顺序输出设备状态,这要求在输出阶段进行排序处理。 - 面向对象设计的复杂性
类设计:需要设计合理的类结构来表示各种设备、电路连接、输入解析和输出处理。类之间的关系、继承、接口设计等都需要仔细考虑。
多态和封装:利用面向对象的多态和封装特性,设计设备的行为接口,以便在模拟过程中灵活调用不同设备的特定行为。 - 算法和逻辑的复杂性
状态更新和模拟:在接收到调节信息后,需要实时更新设备的状态,并重新计算受控设备的输出状态。
电路模拟:在后续迭代中,随着电路结构的复杂化(如并联电路、嵌套电路等),需要设计更复杂的算法来模拟电路行为。
(2)知识点分析: - 抽象类与继承
CircuitEquipment: 作为所有电路设备的基类,包含设备的基本属性和方法,如设备ID和输出电压。
ControlledDevice和ControlDevice: 分别继承自CircuitEquipment,用于表示受控设备和控制设备,进一步扩展了设备的特性,如亮度、速度和状态。 - 多态与接口实现
各种设备类如Switch、Dimmer、ContinuousDimmer、WhiteBulb、DaylightBulb、HairDryer等,继承自CircuitEquipment或其子类,实现了各自的calculateOutPut方法,体现了多态的应用。 - 状态管理
开关和调速器: 通过状态变量(如state、level、speedRatio)和相应的方法(如toggle、increaseLevel、decreaseLevel、setSpeedRatio)来管理设备的状态。 - 输入输出处理
InPut类: 负责解析用户输入,创建设备实例并添加到电路中,并根据控制指令调整设备状态。
OutPut类: 负责输出设备的当前状态,按设备ID排序后输出各设备的状态信息。 - 集合与排序
使用ArrayList存储设备,利用Collections.sort对设备按ID排序,便于输出时的有序处理。 - 用户输入解析
字符串处理: 通过解析输入字符串来识别设备连接信息和控制命令,使用split、substring等方法提取信息。 - 逻辑控制
使用条件语句(如if、switch)来实现对设备状态的判断和相应的输出电压或亮度、速度的计算。 - 面向对象设计
代码通过面向对象的方式设计,具有良好的可扩展性和模块化,便于后续添加新的设备类型或功能。
(3)类图和顺序图设计
(4)踩坑心得及改进建议 - 开关在后面的情况
这段代码中实现了开关在任何地方都可以实现完整的功能
关键实现细节: - 设备连接和状态更新:
SeriesCircuit类中有一个Listdevices用于存储电路中的所有设备。
设备可以按任意顺序添加到电路中,并不要求开关必须在前面。 - 输出电压计算:
在calculateOutputs方法中,首先遍历所有设备,计算控制设备(如开关、调光器)的输出电压。
通过Math.min函数找到所有控制设备中的最小输出电压,这个最小值用于设置受控设备(如灯泡、风扇)的电压。
这种设计允许开关和其他控制设备在电路中的任意位置,只要它们的状态发生变化,就会影响到整个电路的输出。 - 设备状态更新:
在InPut类中,用户输入的控制命令(如#K1)会触发相应设备的状态更新。
调用toggle()方法改变开关状态后,立即调用calculateOutPut()来更新输出电压。
紧接着,circuit.calculateOutputs()会重新计算整个电路的输出,确保所有设备的状态根据最新的控制设备状态进行更新。
3.第六次作业7-1 家居强电电路模拟程序-2
(1)难度分析 - 代码结构与设计
面向对象设计:代码采用了面向对象的设计,定义了多个抽象类和具体类来表示不同的电路设备。这种设计提高了代码的可扩展性和可维护性,但也增加了理解和实现的复杂性。
继承与多态:使用继承和多态来实现不同设备的行为,这要求开发者对这些概念有深入的理解,尤其是在处理复杂的电路逻辑时。 - 功能实现
多种设备类型:支持多种控制设备(开关、分档调速器、连续调速器)和受控设备(白炽灯、日光灯、吊扇、落地扇),每种设备都有不同的特性和行为。这需要为每种设备单独实现逻辑,并确保它们能够正确交互。
电阻和电压计算:引入了电阻的概念,并实现了电压的分配和计算。需要根据电路的拓扑结构计算总电阻,并根据电阻比例分配电压,这涉及到电路分析的基本原理。 - 算法复杂性
电路模拟算法:实现了串联和并联电路的模拟,包括电阻计算和电压分配。这需要设计高效的算法来处理电路的复杂拓扑结构。
输入解析:解析复杂的输入格式,包括设备标识、连接信息、控制信息、串联和并联电路信息。需要设计一个稳健的解析器来处理潜在的输入错误。 - 边缘情况
电路异常情况:需要考虑电路中可能出现的异常情况,如短路、开路等,并确保程序能够正确处理这些情况。
输入错误处理:需要设计程序来处理可能的输入错误或异常情况,如格式错误、不合法的连接信息等。
(2)知识点分析 - 抽象类与继承:
CircuitEquipment 是一个抽象类,定义了电路设备的基本特征(如 ID、输出电压、电阻等)。
ControlledDevice 和 ControlDevice 继承自 CircuitEquipment,分别代表受控设备和控制设备,扩展了特定的属性和方法。
具体设备类(如 Switch、Dimmer、WhiteBulb 等)继承自上述抽象类,实现了具体的行为。 - 多态性:
抽象方法 calculateOutPut 在不同设备类中有不同实现,体现了多态性。
通过多态性,可以在不修改代码的情况下扩展新的设备类型。 - 封装与信息隐藏:
各个类通过私有属性和公共方法封装内部状态,提供对外的接口。
通过方法(如 toggle、handleControl)来操作设备状态,隐藏了内部实现细节。 - 电路设计:
使用 SeriesCircuit 和 ParallelCircuit 类模拟串联和并联电路,包含设备的连接和电阻、电压的计算。
通过设备的组合,实现复杂电路的模拟。 - 面向接口编程:
设备的控制和状态更新通过接口(如 calculateOutPut)进行,而不是直接操作对象,增强了代码的灵活性和可扩展性。 - 集合与数据结构:
使用 List 存储设备,Map 存储设备和电路映射,Set 用于去重和状态跟踪。
这些集合类的使用提高了数据管理效率和代码的可读性。
(3)类图和顺序图设计
(4)踩坑心得及改进建议 - 计算串联电路和并联电路的电阻
在计算串联电阻的时候需要考虑电路里面是否有开关,如果开关是断开状态,则整个电路的电阻设置为0,不可以设置为无穷大,这样会导致并联电路的电阻计算错误。
在计算并联电路的电阻时,当两个开关都时闭合状态而且都是闭合,就会导致短路的情况。
三、总结
在过去的几个月中,深入学习Java编程的过程中,我经历了从基础到复杂的多个项目挑战。这些项目不仅让我掌握了Java的语法和特性,还培养了我解决问题的能力和编程思维。
通过第一次作业,我巩固了面向对象编程的基础知识,理解了类的定义、构造方法、数据封装、常量定义和方法重写的重要性。这为我在后续项目中设计和实现复杂的类结构奠定了基础。
随着作业难度的增加,我开始接触到集合操作、字符串处理和输入输出等中级知识点。这些技能在第二次作业中得到了充分的应用。我学会了如何有效地解析和处理输入数据,特别是在应对格式复杂的输入时,如何利用正则表达式和字符串操作来提取有用的信息。
第三次作业则是对我编程能力的全面考验。面对多种输入类型、复杂的数据结构设计和多样的错误处理,我逐步提高了代码的健壮性和可维护性。我认识到,良好的代码结构和清晰的逻辑是解决复杂问题的关键。
在整个学习过程中,我也积累了许多经验和教训。比如,正确处理输入中的空格和格式问题,确保程序的输出与预期一致;在设计数据结构时,保持数据之间的关联性和一致性;在处理错误时,优先处理那些对程序影响最大的错误。
这些项目不仅提高了我的编程技术,也让我更加理解理论与实践相结合的重要性。每次解决一个难题或实现一个新功能,都会带给我极大的成就感和满足感。编程之路充满挑战,但每一次努力和探索都值得珍惜。未来,我将继续这段充满挑战的学习旅程,不断提升自己的技能和知识水平。