Blog-2
前言
在过去的学习阶段,我经历了一个逐步深入的编程训练过程。这些题目涵盖了答题判题模拟、电路设备模拟以及多设备组合模拟等多个方面。每个题目都逐步增加了复杂性和难度,从基本的设备状态管理到复杂电路的模拟与计算。
(1)答题判断程序-4
题目: 设计实现答题程序,模拟一个小型的测试,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
知识点总结:
1.对于继承和多态的使用。
2.对于不同格式的输入输出的拆分以及分类封装。
3.异常处理的正确使用。
4.对处理输入时的有序记录。
题量: 本次迭代新增两种题型,选择题和填空题
难度: 本次题目要使用到继承和多类,对多态的了解学习花费了时间,在原有代码上迭代上新题型具有难度。
(2)家居强电电路模拟程序-1只是简单的设计一个串联电路,问题设计并不困难。
题目: 模拟电路设备,包括灯和风扇,要求根据电压差模拟设备的工作状态。
新知识点:
- 设计多个类(如A,F,K)并理解它们之间的协作关系。通过类与类之间的交互,模拟现实中的电路连接。
- 学习如何通过电压差来计算设备的状态,比如灯的亮度和风扇的转速。
题量: 对各个类的设计和整体电路的设计
难度: 家居强电电路模拟程序-1只是简单的设计一个串联电路,问题设计并不困难。
(3)综合设备管理程序-3
题目: 模拟复杂电路,涉及串联和并联电路的模拟,需要处理电阻、电压分布和设备状态的综合管理。
新知识点:
复杂电路的模拟,学习如何模拟复杂的电路结构,包括串联和并联电路的组合,理解电阻、电压和电流的关系。
题量:
1.允许用户输入任意数量的设备和连接信息,程序的适应性和灵活性更高。
2.并且可以随意调整输入的顺序,这直接影响到对设备的解析和输出结果的顺序,使得整合设备的过程更加复杂。
3.对电路的处理变得更加困难,要考虑的情况变多
难度: 比起家居强电电路模拟程序-1,新迭代了并联电路,远远加大了难度。
设计与分析
(1)答题判题程序-4
类图:
在这个程序中,我们设计了几个核心类来模拟控制设备的行为。以下是主要类的分析:
- Main 类
- 职责:作为程序的入口点,负责读取输入、解析输入、处理测试试卷和提交的答卷。
- 静态集合:存储题目、试卷、学生和提交的答卷。
方法:
main:程序的主入口,读取输入直到遇到 "end"。
parseInput:根据输入的类型,调用不同的解析方法。
processTestPapers:检查每张试卷的总分是否为100分,如果不是,则输出警告。
processSubmissions:对每个提交的答卷进行评分。
- Question 类
- 职责:表示一个题目,包含题目的ID、内容和标准答案。
方法:
evaluateAnswer:评估学生的答案是否正确。
MultiChoiceQuestion 类
职责:表示一个多项选择题,继承自 Question 类。
属性:包含所有正确的答案。
方法:
evaluateAnswer:评估学生的答案是否包含所有正确的选项且没有错误选项。
calculateScore:根据学生的答案计算分数。
- FillInTheBlankQuestion 类
- 职责:表示一个填空题,继承自 Question 类。
方法:
evaluateAnswer:评估学生的答案是否与标准答案完全匹配或部分匹配。
calculateScore:根据学生的答案计算分数。
- TestPaper 类
- 职责:表示一张试卷,包含多个题目和对应的分值。
方法:
addQuestion:添加一个题目及其分值到试卷中。
getTotalScore:计算试卷的总分。
getId:返回试卷的ID。
- Student 类
- 职责:表示一个学生,包含学生的ID和姓名。
- Submission 类
- 职责:表示一个学生的答卷,包含学生的ID、试卷ID和对应题目的答案。
方法:
addAnswer:添加一个题目的答案到答卷中。
evaluate:评估答卷上的每个答案,并计算总分。
(2)家居强电电路模拟程序-1
类图:
抽象基类 Device
属性:
id:设备的标识符。
inputVoltage:设备的输入电压,默认为0。
方法:
构造函数:初始化设备ID。
getStatus:抽象方法,用于获取设备的状态。
getId:返回设备的ID。
connectPin:连接设备的引脚(默认实现为空)。
toggle:切换设备状态(默认实现为空)。
stepUp:增加设备的一个状态级别(默认实现为空)。
stepDown:减少设备的一个状态级别(默认实现为空)。
set:设置设备的输入电压。
getInputVoltage:获取设备的输入电压。
具体设备子类
K 类(开关):
属性:isClosed 表示开关是否关闭。
方法:toggle 切换开关状态,set 根据开关状态传递电压。
F 类(分档调速器):
属性:level 表示分档调速器的级别。
方法:stepUp 和 stepDown 调整级别,set 根据级别传递电压。
L 类(连续调速器):
属性:level 表示连续调速器的级别。
方法:setdang 设置级别,set 根据级别传递电压。
B 类(白炽灯):
属性:brightness 表示白炽灯的亮度。
方法:set 根据输入电压设置白炽灯亮度。
R 类(日光灯):
属性:isOn 表示日光灯是否开启。
方法:set 根据输入电压开启或关闭电阻。
D 类(电扇):
属性:speed 表示电扇的速度。
方法:set 根据输入电压设置电扇速度。
Main 类
属性:
voltage:静态变量,表示电源电压。
方法:
main:程序入口,读取输入并处理设备状态。
createDevice:根据设备ID创建具体的设备实例。
parseConnectionInfo:解析连接信息,创建并连接设备。
applyControlInfo:应用控制信息,如开关操作。
printDeviceStatus:打印所有设备的状态。
(3)家居强电电路模拟程序-2
类图:
在这个程序中,我们需要处理更复杂的电路结构,包括串联和并联电路。以下是主要类的分析:
抽象基类 Device
属性:
id:设备的标识符。
inputVoltage:设备的输入电压。
resistance:设备的电阻值。
hasVoltage:表示设备是否带有电压。
方法:
构造函数:初始化设备ID。
getStatus:抽象方法,用于获取设备的状态。
getId:返回设备的ID。
connectPin:连接设备的引脚(默认实现为空)。
toggle:切换设备状态(默认实现为空)。
stepUp:增加设备的一个状态级别(默认实现为空)。
stepDown:减少设备的一个状态级别(默认实现为空)。
set:设置设备的输入电压。
getInputVoltage:获取设备的输入电压。
getResistance:获取设备的电阻值。
getTotalResistance:获取设备的总电阻值(默认实现返回电阻值)。
电路结构类
SeriesCircuit 类(串联电路):
属性:devices 存储串联的设备列表。
方法: addDevice 添加设备到串联电路,getStatus 获取电路状态,set 设置电路电压,getTotalResistance 计算总电阻,checkForOpenCircuit 检查电路是否开路。
ParallelCircuit 类(并联电路):
属性:devices 存储并联的设备列表,equivalentResistance 等效电阻值。
方法: addDevice 添加设备到并联电路,getStatus 获取电路状态,set 设置电路电压,calculateEquivalentResistance 计算等效电阻,getTotalResistance 获取等效电阻值。
具体设备子类
Switch 类(开关):
属性:isClosed 表示开关是否关闭,connectedDevice 连接的设备。
方法: getResistance 返回电阻值(开关关闭时为0),getStatus 获取开关状态,toggle 切换开关状态,set 设置开关电压并传递给连接的设备。
Dimmer 类(分档调速器):
属性:level 表示分档调速器的级别,connectedDevice 连接的设备。
方法: getResistance 返回电阻值(调光器为0),getStatus 获取调光器状态,stepUp 和 stepDown 调整级别,set 设置调光器电压并更新连接的设备。
Lamp 类(日光灯):
属性:level 表示日光灯的亮度级别,connectedDevice 连接的设备。
方法: getResistance 返回电阻值(灯泡为0),getStatus 获取灯泡状态,setLevel 设置亮度级别,set 设置灯泡电压并更新连接的设备。
Bulb 类(白炽灯):
属性:brightness 表示白炽灯的亮度。
方法: getResistance 返回电阻值,getStatus 获取灯泡状态,set 根据输入电压设置灯泡亮度。
Resistor 类(连续调速器):
属性:isOn 表示连续调速器是否开启。
方法: getResistance 返回电阻值,getStatus 获取连续调速器状态,set 根据输入电压设置连续调速器状态。
MotorD 类和 MotorA 类(电扇):
属性:speed 表示电扇的速度。
方法:getResistance 返回电扇值,getStatus 获取电扇状态,set 根据输入电压设置电扇速度。
Main 类
属性:
voltage:静态变量,表示电源电压。
方法:
main:程序入口,读取输入并处理设备状态。
createDevice:根据设备ID创建具体的设备实例。
parseConnectionInfo:解析连接信息,创建并连接设备。
applyControlInfo:应用控制信息,如开关操作。
printDeviceStatus:打印所有设备的状态。
采坑心得
在源码提交过程中,我们遇到了以下几个主要问题:
- 关于电路的正确分析:
- 家居强电电路模拟程序-1中:没有考虑到一个电路中拥有多个开关的情况,只是错误的设置电路电压
如:
点击查看代码
如:
for (Device device : sortedDevices) {
if (device instanceof K || device instanceof F || device instanceof L) {
device.set(Main.voltage);
flag = true;
}
正确代码:
// 检查是否有任何 K 设备是打开的
boolean isAnySwitchOpen = sortedDevices.stream().filter(device -> device instanceof K).anyMatch(device -> !((K) device).isClosed);
// 根据开关的状态设置电压
if (isAnySwitchOpen) {
Main.voltage = 0;
} else {
Main.voltage = 220;
}
点击查看代码
double parallelResistanceSum = 0;
for (Device device : devices.values()) {
if (device instanceof ParallelCircuit) {
ParallelCircuit parallelCircuit = (ParallelCircuit) device;
parallelResistanceSum += 1.0 / parallelCircuit.getTotalResistance(); // Accumulate reciprocals
}
}
if (parallelResistanceSum > 0) {
totalResistance += 1.0 / parallelResistanceSum; // Add equivalent resistance
}
- 在ParallelCircuit中,calculateEquivalentResistance方法未处理空的或无效的devices集合情况,可能导致1.0 / reciprocalSum抛出ArithmeticException(除以零)。
修复代码:
点击查看代码
public void calculateEquivalentResistance() {
double reciprocalSum = 0;
boolean hasShortCircuit = false;
boolean allOpenCircuits = true;
for (Device device : devices) {
if (device instanceof SeriesCircuit) {
SeriesCircuit seriesCircuit = (SeriesCircuit) device;
if (seriesCircuit.checkForOpenCircuit()) {
seriesCircuit.set(0); // Set voltage to 0 for open circuits
} else {
allOpenCircuits = false;
double seriesResistance = seriesCircuit.getTotalResistance();
if (seriesResistance == 0) {
hasShortCircuit = true;
} else {
reciprocalSum += 1.0 / seriesResistance;
}
}
}
}
if (hasShortCircuit) {
equivalentResistance = 0;
} else if (allOpenCircuits || reciprocalSum == 0) {
equivalentResistance = Double.POSITIVE_INFINITY;
} else {
equivalentResistance = 1.0 / reciprocalSum;
}
}
代码结构和组织
- 代码结构清晰:代码分为多个类,每个类负责特定的功能,如
Question
、Student
、TestPaper
等。 - 输入解析逻辑集中:通过
parseInput
方法集中处理不同类型的输入,保持了主流程的简洁。 - 注释和文档:为类和方法添加注释,解释其功能和用法,尤其是在复杂的逻辑部分。
- 命名一致性:确保方法和变量的命名一致且有意义,以提高代码可读性。
面向对象设计
- 类的使用:使用类来封装不同的实体(如问题、学生、考试卷),符合面向对象设计原则。
- 多态性:不同类型的问题(选择题、填空题)通过继承实现多态行为。
改进建议:
- 封装:将类的字段设为私有,并通过getter和setter方法访问,保护数据完整性。
- 抽象和接口:考虑使用抽象类或接口来定义通用行为,增强代码的可扩展性。
功能和性能
- 功能完整:代码实现了从解析输入到评估提交的完整流程。
- 性能合理:使用合适的数据结构(如
Map
和List
)来存储和管理数据。
改进建议:
- 消除重复代码:提取公共逻辑以减少代码重复,例如在解析不同类型问题时。
- 错误处理:加强输入验证和异常处理,以提高程序的鲁棒性。
- 优化输出:提供更详细和用户友好的输出信息,帮助用户理解程序状态。
总结
这次的家居强电电路模拟程序-2比较困难,无法将串联、并联的部分理清,导致了方法和类无法很好地串连起来,写地满烂。继承以及多态是面向对象编程中实现代码复用、提高代码灵活性、迭代和可维护性的重要工具,
应该多以学习利用。