题目一:答题程序设计与实现
功能解析
题目一要求设计一个模拟答题系统,功能包括:
题目管理:
输入题目信息,包括题号、内容和标准答案。
支持删除某些题目,使其无效化。
试卷管理:
输入试卷信息,包括试卷编号、包含的题目及每题分值。
验证试卷总分是否满足预设标准(如 100 分)。
学生答题管理:
输入学生信息和答题记录。
根据试卷信息和学生答案对比计算得分。
结果输出:
输出每个题目的答题结果(正确、部分正确或错误)。
输出学生得分及答题详情。
代码设计与关键模块
代码主要采用了面向对象设计,核心类包括:
Question:表示一个题目,包含题号、题干、标准答案及状态信息。
TestPaper:表示一张试卷,记录试卷编号、题目列表及分值分布。
Answer:表示一个学生提交的答案,包含学生编号、答题记录及对应得分。
Student:表示学生信息,包括学号和姓名。
类与方法详解
- Question 类
表示一道题目的基本信息。
属性:
num:题号(int)。
questions:题干内容(String)。
answer:标准答案(String)。
isTrue:题目是否有效(boolean)。
方法:
getNum():获取题号。
getAnswer():获取标准答案。
isIstrue():判断题目是否有效。
setIstrue(boolean):设置题目状态(有效/无效)。
示例:
Question q1 = new Question(1, "What is 2+2?", "4");
System.out.println(q1.getAnswer()); // 输出: 4
2. TestPaper 类
表示一张试卷及其结构。
属性:
count:试卷编号(int)。
nums:包含的题号列表(ArrayList
scores:对应题号的分值列表(ArrayList
方法:
getCount():获取试卷编号。
getNum():获取题号列表。
getScore():获取题目分值列表。
示例:
ArrayList
ArrayList
TestPaper test1 = new TestPaper(101, nums, scores);
System.out.println(test1.getScore()); // 输出: [10, 20, 30]
3. Answer 类
表示学生提交的一份答卷及答题记录。
属性:
num:试卷编号(int)。
id:学生编号(String)。
number:答题号列表(ArrayList
answers:学生的答案列表(ArrayList
scores:对应每题的得分列表(ArrayList
方法:
getNum():获取试卷编号。
getAnswers():获取学生答案列表。
getScores():获取得分列表。
setScores(ArrayList
示例:
ArrayList
ArrayList
Answer ans1 = new Answer(101, "20230001", numbers, answers);
System.out.println(ans1.getAnswers()); // 输出: [4, 3]
4. Student 类
表示一个学生的基本信息。
属性:
id:学号(String)。
name:姓名(String)。
方法:
getId():获取学号。
getName():获取姓名。
示例:
Student stu1 = new Student("20230001", "Alice");
System.out.println(stu1.getName()); // 输出: Alice
主类 Main 的解析
主类 Main 是答题程序的核心执行模块,其功能涵盖了:
数据的输入与解析:
解析题目信息、试卷信息、学生信息和答题记录。
校验输入格式是否正确,并将数据存储到对应的对象和列表中。
功能实现:
管理题目和试卷的动态操作,如删除题目。
根据试卷与答题记录,对学生答案进行比对,计算得分。
结果输出:
输出每道题的答题情况(正确、部分正确、错误)。
输出学生的总得分及得分详情。
核心结构与功能模块
Main 类由以下几部分组成:
- 数据存储与初始化
使用多个集合存储不同数据类型:
questionlist:存储所有题目。
testList:存储所有试卷。
studentArrayList:存储所有学生。
answerArrayList:存储所有答题记录。
delList:存储被标记为删除的题目编号。
代码示例:
ArrayList
ArrayList
ArrayList
ArrayList
ArrayList
2. 输入解析与处理
(1) 解析题目输入
通过正则表达式提取题目信息(如编号、题干、标准答案)。
创建 Question 对象并添加到 questionlist。
代码示例:
if (input.startsWith("#N:")) {
String pattern = "#N:(\d+) #Q:(.+) #A:(\d+)";
Pattern p = Pattern.compile(pattern);
Matcher question = p.matcher(input);
if (question.find()) {
Question qs = new Question(
Integer.parseInt(question.group(1)),
question.group(2),
question.group(3)
);
questionlist.add(qs);
} else {
System.out.println("wrong format:" + input);
}
}
功能:
通过正则表达式校验输入格式。
如果校验通过,将题目信息存入对象中。
(2) 解析试卷输入
试卷输入格式包含试卷编号、题号列表及其对应分值。
正则提取题号和分值后,创建 TestPaper 对象并存储。
代码示例:
else if (input.startsWith("#T:")) {
String testPattern = "^#T:(\d+)(?: (\d+-\d+))*";
Pattern testP = Pattern.compile(testPattern);
Matcher test = testP.matcher(input);
if (test.matches()) {
int count = Integer.parseInt(test.group(1));
ArrayList
ArrayList
Pattern pp = Pattern.compile("(\\d+)-(\\d+)");
Matcher m = pp.matcher(input);
while (m.find()) {
questionnum.add(Integer.parseInt(m.group(1)));
scorelist.add(Integer.parseInt(m.group(2)));
}
TestPaper newTest = new TestPaper(count, questionnum, scorelist);
testList.add(newTest);
} else {
System.out.println("wrong format:" + input);
}
}
(3) 解析学生与答题记录
学生信息:
格式:#X:<学生编号> <学生姓名>。
创建 Student 对象并存入 studentArrayList。
答题记录:
格式:#S:<试卷编号> <学生编号> #A:<题号>-<答案>。
提取答题记录及答案,创建 Answer 对象。
代码示例:
else if (input.startsWith("#X:")) {
String pattern = "(\d{8})\s(\w+)";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(input);
while (m.find()) {
String id = m.group(1);
String name = m.group(2);
Student newStudent = new Student(id, name);
studentArrayList.add(newStudent);
}
}
else if (input.startsWith("#S:")) {
String pattern = "^#S:(\d+) (\d{8}) ((?:#A:\d+-[\w\s]+)+)";
Pattern answerPattern = Pattern.compile(pattern);
Matcher m = answerPattern.matcher(input);
if (m.matches()) {
int count = Integer.parseInt(m.group(1));
String ID = m.group(2);
String answersPart = m.group(3);
ArrayList
ArrayList
Pattern answerMatcher = Pattern.compile("#A:(\\d+)-(\\w+)");
Matcher ansMatcher = answerMatcher.matcher(answersPart);
while (ansMatcher.find()) {
nums.add(Integer.parseInt(ansMatcher.group(1)));
answers.add(ansMatcher.group(2));
}
Answer newAnswer = new Answer(count, ID, nums, answers);
answerArrayList.add(newAnswer);
} else {
System.out.println("wrong format:" + input);
}
}
展开
3. 题目删除逻辑
支持通过 #D:<题号> 格式输入,标记题目为无效。
代码示例:
else if (input.startsWith("#D:")) {
String pattern = "^#D:N-(\d+)";
Pattern delp = Pattern.compile(pattern);
Matcher m = delp.matcher(input);
if (m.find()) {
delList.add(Integer.parseInt(m.group(1)));
for (int i : delList) {
for (int j = 0; j < questionlist.size(); j++) {
if (questionlist.get(j).getNum() == i) {
questionlist.get(j).setIstrue(false);
}
}
}
} else {
System.out.println("wrong format:" + input);
}
}
4. 答题结果计算与输出
根据试卷中的题号,从题目列表中查找对应题目。
对比学生答案和标准答案,判断答题结果:
全对:得满分。
部分正确:得一半分。
错误或无效题目:得 0 分。
代码示例:
for (TestPaper paper : testList) {
if (paper.getCount() == newAnswer.getNum()) {
for (int i = 0; i < paper.getNum().size(); i++) {
boolean questionFound = false;
boolean answerProvided = false;
boolean isValidQuestion = false;
// 查找题目
for (Question question : questionlist) {
if (paper.getNum().get(i) == question.getNum()) {
questionFound = true;
if (question.isIstrue()) {
isValidQuestion = true;
}
break;
}
}
// 比较答案
for (int x = 0; x < newAnswer.getNumber().size(); x++) {
if (i + 1 == newAnswer.getNumber().get(x)) {
answerProvided = true;
break;
}
}
// 计算分数
if (answerProvided && isValidQuestion) {
// 正确性判定逻辑...
}
}
}
}
展开
5. 总分校验
验证试卷总分是否为 100 分:
if (totalScore != 100) {
System.out.println("alert: full score of test paper1 is not 100 points");
}
程序运行逻辑
输入解析:基于正则表达式处理多种输入类型,如题目、试卷、答题记录等。
String pattern = "#N:(\d+) #Q:(.+) #A:(\d+)";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(input);
if (m.find()) {
Question qs = new Question(...); // 创建题目
}
题目与试卷管理:
保存所有题目、试卷的有效信息。
支持通过编号删除题目。
答案对比与得分计算:
将学生答案与标准答案对比。
判定正确、部分正确和错误,分配对应得分。
if (allCorrect && !anyIncorrect) {
studentScore += paper.getScore().get(i);
} else if (correctCount > 0) {
studentScore += paper.getScore().get(i) / 2; // 部分得分
}
结果输出:
输出学生得分。
输出每道题的答题结果。
改进建议
输入验证模块化:
将不同输入类型的正则解析抽取为工具方法,提高复用性。
答题逻辑优化:
增加题目随机生成、打乱顺序的功能,模拟实际考试。
性能优化:
使用哈希表存储题目与答案,加快匹配与比对速度。
序列化支持:
实现题库和答题记录的存储与加载功能,提升系统实用性。
题目二:智能家居强电电路模拟系统
功能需求解析
设备管理:
包含多种设备类型,如开关(SwitchDevice)、调速器(SteppedSpeedController、ContinuousSpeedController)、灯具(WhiteIncandescentLamp、DaylightLamp)、风扇(FanDevice)。
每个设备有独特的属性和行为。
电路模拟:
电路由多个设备串联连接,输入电压通过设备链传递和处理。
设备状态控制:
支持通过命令调整设备状态,如切换开关、调节速度、设置参数等。
输出结果:
模拟电路后输出设备的状态或计算值(如灯的亮度、风扇的速度)。
设计与实现分析
系统设计采用面向对象编程,核心在于抽象设备行为、设备继承关系,以及电路的拓扑管理。
类图
以下是该题目的类图,用于描述设备继承结构和电路管理的关系:
各类与方法介绍
- Device 类
设备的抽象基类,定义了设备的通用属性和行为。
属性:
id:设备唯一标识符。
type:设备类型(如开关、调速器等)。
number:设备编号。
方法:
getOutputVoltage(double inputVoltage):根据输入电压计算输出电压,子类需实现。
2. ControlDevice 类
继承 Device,表示控制设备,用于调节电压或控制设备链的状态。
方法:
toggle():切换设备的状态(如开关开启或关闭)。
2.1 SwitchDevice 类
开关设备,用于控制电路的通断。
属性:
state:开关状态(0 为开通,1 为关闭)。
方法:
getOutputVoltage(double inputVoltage):如果开关关闭,输出电压为输入电压;如果开关开启,输出为 0。
toggle():切换开关状态。
代码示例:
SwitchDevice switchDevice = new SwitchDevice("K1", 1);
switchDevice.toggle(); // 切换状态
System.out.println(switchDevice.getOutputVoltage(220)); // 输出电压
2.2 SteppedSpeedController 类
分档调速器,用于调节电压分级输出。
属性:
currentStep:当前档位(0-3)。
方法:
getOutputVoltage(double inputVoltage):根据当前档位输出比例电压。
increaseStep():提高档位。
decreaseStep():降低档位。
代码示例:
SteppedSpeedController controller = new SteppedSpeedController("F1", 1);
controller.increaseStep(); // 提高档位
System.out.println(controller.getOutputVoltage(220)); // 输出电压
2.3 ContinuousSpeedController 类
连续调速器,用于根据参数比例调节输出电压。
属性:
parameter:调节比例(0.00-1.00)。
方法:
getOutputVoltage(double inputVoltage):按比例输出电压。
setParameter(double newParam):设置新的调节比例。
代码示例:
ContinuousSpeedController continuousController = new ContinuousSpeedController("L1", 1);
continuousController.setParameter(0.5); // 设置比例
System.out.println(continuousController.getOutputVoltage(220)); // 输出电压
3. ControlledDevice 类
继承 Device,表示受控设备,用于模拟响应电压变化的设备状态。
方法:
computeState(double inputVoltage):根据输入电压计算设备状态。
getOutputVoltage(double inputVoltage):受控设备不改变电压,直接输出 0。
3.1 WhiteIncandescentLamp 类
白炽灯设备,亮度根据输入电压计算。
属性:
brightness:灯的亮度(0-200)。
方法:
computeState(double inputVoltage):根据输入电压计算亮度。
getBrightness():返回当前亮度。
3.2 DaylightLamp 类
日光灯设备,亮度为两种状态(0 或 180)。
属性:
brightness:灯的亮度(0 或 180)。
方法:
computeState(double inputVoltage):根据输入电压切换亮度。
3.3 FanDevice 类
风扇设备,转速根据输入电压计算。
属性:
speed:风扇转速(0-360)。
方法:
computeState(double inputVoltage):根据输入电压计算转速。
getSpeed():返回当前转速。
代码示例:
FanDevice fan = new FanDevice("D1", 1);
fan.computeState(100); // 输入电压
System.out.println(fan.getSpeed()); // 输出转速
主类 Main 的解析
主类 Main 是智能家居强电电路模拟系统的核心控制模块,负责以下主要任务:
输入解析与设备链初始化:
解析输入的设备链配置(连接格式)和命令(操作格式)。
创建设备实例并构建电路连接。
电路仿真:
模拟电压从电源(VCC)传递到地(GND)的过程。
通过设备链传递电压并计算各设备状态。
命令执行:
根据用户输入的命令调整设备状态(如切换开关、调节调速器档位或参数)。
输出设备状态:
按设备类型和编号顺序,输出每个设备的状态或计算值。
核心逻辑模块
- 数据存储与初始化
主类初始化时,存储输入数据,并构建设备链及命令列表:
设备链存储:通过 List
设备映射:通过 Map<String, Device> 存储设备的唯一标识符(如 K1、D2)与设备实例的映射关系,便于快速查询。
命令列表:存储命令行用于状态调整。
代码示例:
List
List
Map<String, Device> devicesMap = new HashMap<>();
List
2. 设备链解析
输入的设备链格式(如 [VCC K1-1] [K1-2 D2-1] [D2-2 GND])表示设备的连接关系。
每个连接点由两个端口组成,解析端口并确定设备的输入输出。
根据设备类型和编号创建相应的设备实例(通过 Device 子类)。
按设备连接顺序,依次构建设备链。
代码示例:
for (String conn : connectionLines) {
String content = conn.substring(1, conn.length() - 1).trim();
String[] pins = content.split("\s+");
if (pins.length != 2) continue;
String pinA = pins[0];
String pinB = pins[1];
String deviceId = pinB.split("-")[0];
// 根据设备类型创建设备实例
Device device = devicesMap.getOrDefault(deviceId, createDevice(deviceId));
if (device != null && !deviceChain.contains(device)) {
deviceChain.add(device);
devicesMap.put(deviceId, device);
}
}
辅助方法:
private Device createDevice(String deviceId) {
char type = deviceId.charAt(0); // 获取设备类型(K, F, L, B, R, D)
int number = Integer.parseInt(deviceId.substring(1));
switch (type) {
case 'K': return new SwitchDevice(deviceId, number);
case 'F': return new SteppedSpeedController(deviceId, number);
case 'L': return new ContinuousSpeedController(deviceId, number);
case 'B': return new WhiteIncandescentLamp(deviceId, number);
case 'R': return new DaylightLamp(deviceId, number);
case 'D': return new FanDevice(deviceId, number);
default: return null; // 未知设备类型
}
}
3. 命令解析与执行
用户输入的命令控制设备状态(如切换开关、调节调速器档位等)。命令格式包括:
切换开关:#K1 表示切换开关 K1。
调节档位:#F1+ 或 #F1- 表示增加或减少档位。
设置参数:#L1:0.5 表示将调速器 L1 的参数设置为 0.5。
逻辑处理:
遍历命令列表,根据命令类型操作对应设备。
代码示例:
for (String cmd : commandLines) {
if (cmd.startsWith("#K")) { // 切换开关
String deviceId = cmd.substring(1);
Device device = devicesMap.get(deviceId);
if (device instanceof SwitchDevice) {
((SwitchDevice) device).toggle();
}
} else if (cmd.startsWith("#F")) { // 调节分档控制器
String deviceId = cmd.substring(1, cmd.length() - 1);
char operation = cmd.charAt(cmd.length() - 1);
Device device = devicesMap.get(deviceId);
if (device instanceof SteppedSpeedController) {
if (operation == '+') ((SteppedSpeedController) device).increaseStep();
else if (operation == '-') ((SteppedSpeedController) device).decreaseStep();
}
} else if (cmd.startsWith("#L")) { // 设置连续控制器参数
String[] parts = cmd.split("