答题判题程序和家具强电电路模拟系统

2859332934qq / 2024-06-09 / 原文

7-1 答题判题程序-4

判题系统4是对之前判题系统3的进一步引申,题目内容上增加了题目类型,变成了有选择题和填空题,选择题还有多选题,两种题型的判题标准也有其特定的设定。那么我们就这次判题系统做一次分析说明。

1.对于选择题来说,输入题目并没有太多改变,而是答案的输出有一些改变,一次输入多个选择,标准答案中如果包含多个正确答案(多选题),正确答案之间用英文空格分隔,这里就意味着分割的处理要发生改变。然后是给分方式的改变,答案包含所有正确答案且不含错误答案给满分;包含一个错误答案或完全没有答案给0分;包含部分正确答案且不含错误答案给一半分,如果一半分值为小数,按截尾规则只保留整数部分,这里在输出的时候也需要改变输出模式。NormalQuestion继承自Question,而选择题类也继承自Question,该类有一个valid标志、一个id、一个content和一个correctAnswers集合。然后,定义了checkAnswer方法来检查给定的答案数组,我们先检查题目是否有效,如果题目无效(可能是在Question基类中定义的某个条件不满足),则直接返回"invalid~0",再将给出的答案数组转换成一个HashSet集合,以便进行快速查找和比较,如果用户没有给出任何答案(即给出的答案集合为空),则返回"false"然后再检查用户给出的答案集合是否与正确答案集合完全相等,由于HashSet比较的是元素的内容而不是顺序,因此我们需要将correctAnswers也转换为一个新的HashSet进行比较,如果给出的答案集合至少包含一个正确答案,则返回"partially correct" 否则返回"false",表示答案完全错误或没有包含任何正确答案。
在这个方法中,首先会检查题目是否有效,然后检查用户是否给出了答案。如果给出了答案,会先尝试判断答案是否完全正确(即与正确答案集合完全相等)。如果不是完全正确,会进一步检查是否至少包含了一个正确答案。根据这些条件,方法会返回相应的字符串结果("true"、"partially correct"或"false")。

2.对于填空题来说是一个道理,只是在给出答案的时候,它是填空的形式。

3.其他的类和之前几次练习是一样的,然后可以分析一下主函数,main方法负责调用两个主要的方法:parseInput用于解析输入,printErrorsAndResults用于打印错误信息和结果。
parseInput 方法,这个方法使用一个Scanner对象来读取标准输入的每一行,并根据行的格式来解析题目、试卷、学生和提交信息。如果遇到格式错误或不认识的格式,会将错误信息添加到errors列表中。parseQuestion 方法,这个方法使用正则表达式来解析题目信息,包括题目类型、题目内容、答案等,并将解析出的题目存储到questions映射中,parseSubmission 方法,这个方法解析学生的提交信息,包括试卷ID、学生ID和每个问题的答案,并将解析出的提交信息存储到对应学生的submissions映射中,大概整体就是这样。

7-1家具强电电路模拟系统-1
在智能家居系统中,强电电路是一个非常重要的组成部分。它负责控制和监测各种家用电器的状态和参数,是实现智能家居自动化的基础。题目内容很复杂,需要一步步去分析,首先拿到这道题就知道,我们首先需要电器父类,需要分析电路,然后把电路连接起来,需要接受设备信息、连接信息和控制设备调节信息,并输出各个设备的状态或参数。

该系统的核心是各种家用电器设备,它们被抽象为 Java 类。最基础的是 BaseDevice 类,定义了设备的通用属性和方法,包括:
1.设备类型 dt
2.设备 ID id
3.电压输入pin1和pin2
4.设备状态status
5.档位系数shifterVal
6.开关操作
7.电位计算getPotential()
BaseDevice 类还提供了一些受保护的方法,供子类使用,如 potentialOf() 计算输出电压。而基于 BaseDevice,系统定义了几种具体的设备类:
continuousGovernor: 连续调速器,实现了potentialOf()方法,根据输入电压和档位系数计算输出电压。
ShiftGovernor: 分档调速器,实现了forward()和backward()方法调节档位,同时也实现了potentialOf() 方法。
Switch: 开关设备,继承自BaseDevice。
Fan: 吊扇设备,继承自MonitorDevice (监控设备),实现getRotateSpeed()方法计算转速。
FluorescentLamp: 日光灯,继承自 Lamp (灯具),实现了 getBrightness() 方法计算亮度。
IncandescentLamp: 白炽灯,也继承自 Lamp,实现了 getBrightness() 方法。这些设备类的设计遵循了面向对象的原则,通过继承和多态实现了代码的复用和扩展性。
控制设备也需要处理。除了设备类,该系统还需要处理设备之间的连接和控制关系。在 Main 类的 main() 方法中,通过读取输入信息,构建了三个列表,分别是baseDeviceList: 存放所有的设备对象,connectedDeviceList: 存放串联连接的设备对象,controllerList: 存放可控制的设备对象。在处理输入信息时,会根据不同的格式,将设备对象添加到对应的列表中。比如以#开头的行,表示一个控制设备,会被添加到 controllerList。最后,系统会对这些列表进行排序和处理,输出设备的状态和参数信息。具体的逻辑如下:
1.如果controllerList不为空,且设备数量小于baseDeviceList,则将未被控制的设备添加到controllerList。
2.对controllerList进行排序,按设备 ID 升序排列。
3.遍历controllerList,根据设备类型输出相应的状态或参数信息。
4.从connectedDeviceList中移除已经输出的设备对象。
5.如果controllerList为空且connectedDeviceList也为空,则将 baseDeviceList 中的所有设备输入电压设置为 0 和 220V。
6.如果controllerList不为空,则根据开关状态,计算connectedDeviceList 中设备的输入电压,并输出。
这次新学到了一点关于枚举类的知识,在这里说明一点,枚举类(Enum)在Java中是一种特殊的数据类型,它允许开发者定义一组命名的常量。枚举类是一种类型安全的方式,用于表示一组固定的值。在上述代码中,枚举类 DeviceTypeEnum 被用来表示设备类型的种类,枚举类是通过enum关键字来定义的。在代码中,DeviceTypeEnum 是一个枚举类,它定义了几种设备类型,枚举有一些方法,比如values()返回一个包含所有枚举常量的数组,name()返回名称,of(String s)接受一个字符串参数,并返回与该字符串名称匹配的枚举常量。如果找不到匹配的常量,它将返回null。

7-1家具强电电路模拟系统-2
这一次的练习加入了并联电路,就是把串联电路并到一起,还加入了电阻和落地灯,就要考虑电路的连接和电流,分压等问题,前面的代码写的就不太好了,所以重新开始写了一遍,首先是类,其实类没有多大变化,就是父类,然后继承。我主要分析主函数的实现。主程序在用户输入电路配置和控制命令后,生成设备及电路实例,并展示设备的最终状态。
输入时的操作是这样的:
List inputLines = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
// Read input lines from console until "end"
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.trim().equalsIgnoreCase("end")) {
break;
}
inputLines.add(line.trim());
}
然后我们就分析输入,并且创建每个电器的对象并且储存到deviceMap中去,方便后面遍历列表。

然后private static List parseSeriesCircuits(String[] inputLines) 是处理电路,解析串联电路:当输入行以#T开头时,代码会尝试解析串联电路。它通过分割冒号(:)来获取电路ID和设备连接字符串,然后进一步分割空白字符以获取各个连接。设备连接解析:代码使用正则表达式来匹配设备连接字符串,但正则表达式可能不正确。它应该匹配设备ID和另一个ID或数字,但目前只匹配设备ID和后续的任何字符。构建串联电路:如果找到有效的设备连接,代码会将这些设备添加到串联电路的列表中,并创建一个新的 SeriesCircuit 对象。解析并联电路:当输入行以#M开头时,代码会解析并联电路。它获取并联电路的ID和包含串联电路ID的列表,然后构建并联电路。

applyControlCommands方法是用于应用控制命令的,它处理一系列输入命令,根据命令类型对设备进行操作。以下是该方法的分析:
初始化:方法开始时,将所有连续控制器(ContinuousController)的控值设置为0。
处理开关命令:如果命令以 #K 开头,它将解析设备标识符,并切换该设备的开关状态。
处理步进控制器命令:如果命令符合 #F\d+[+-] 的模式,它将解析设备标识符,并根据命令尾部的+或-来增加或减少步进控制器的步数。
处理连续调档命令:如果命令符合 #L\d+:\\d+\\.\\d{2} 的模式,它将解析设备标识符和控值,然后设置相应连续控制器的控值。

然后最后一部分是输出,private static void outputDeviceStatus(List devices),先定义了一个 deviceOrder 列表,该列表指定了设备类型的输出顺序。然后,它使用这个顺序对传入的 devices 列表进行排序。
排序规则如下:首先根据设备类型在 deviceOrder 列表中的索引进行比较,如果设备类型相同,则根据设备编号进行比较,设备编号通过调用 getDeviceNumber 方法获得。
排序后,方法遍历排序好的设备列表,并根据设备的实际类型输出相应的状态信息。
getDeviceNumber(Device device):这个方法接收一个 Device 对象,并通过 getDeviceIdentifier 方法获取设备的标识符。然后,它从标识符中提取数字部分,将其转换为整数并返回。getDeviceIdentifier(Device device):这个方法用于获取设备的标识符。它通过遍历 deviceMap 映射来查找与传入设备对象相匹配的键(即标识符)。如果找到匹配项,则返回该键;否则返回空字符串。

然后返回一开始给主电路传电压,Main.mainCircuit.setInputVoltage(220);最后outputDeviceStatus(devices)输出结果。