IT评测·应用市场-qidao123.com技术社区

标题: PTA标题集4~6的总结性Blog [打印本页]

作者: 圆咕噜咕噜    时间: 2024-11-22 15:27
标题: PTA标题集4~6的总结性Blog
· 前言

本次的三个作业,由答题判题程序- 4、家居强电电路模拟程序- 1、家居强电电路模拟程序 -2构成。
答题判题程序-4是对前三次判题程序的末了升级,计划多个子类继承于基础题类来实现对每种题型的判断和计算分值;而家居强电电路模拟程序-1则是对输入的各个设备在串联关系中的状态更新,其中涉及到设备电压的计算和开关状态的判断,以及受控设备的状态输出;末了家居强电电路模拟程序-2则在前一题的基础上增加了并联的内容,在逻辑处置惩罚上更加的复杂了。本文将系统性总结这三次标题集的知识点、题量及难度,并分析其中的焦点内容和实现方法。
· 标题集概述

· 答题判题程序 - 4:

标题分析:

计划与分析


聚集类型
排序
流操作
封装
继承与代码复用
多态
组合
单一职责
源码结构分析


main类中调用:
inputHandler.readExamData(exam, testPapers, answerSheets, testIds, students);来处置惩罚用户输入
点击查看代码
  1.     // 读取题目、试卷和答卷数据
  2.     public void readExamData(Exam exam, Map<Integer, List<QuestionScore>> testPapers, Map<Integer, List<AnswerSheet>> answerSheets, List<Integer> testIds, Map<Integer, Student> students) {
  3.         while (true) {
  4.             String inputLine = scanner.nextLine();
  5.             if (inputLine.equals("end")) {
  6.                 break;  // 输入结束
  7.             }
  8.             // 解析题目信息
  9.             try {
  10.                 if (inputLine.startsWith("#N:")) {
  11.                     Pattern questionPattern = Pattern.compile("#N:(\\d+)\\s+(?:(#Q:(.+?))\\s+#A:(.+?))");
  12.                     Matcher matcher = questionPattern.matcher(inputLine);
  13.                     if (matcher.matches()) {
  14.                         int num = Integer.parseInt(matcher.group(1));
  15.                         String questionContent, standardAnswer;
  16.                         // 判断匹配的顺序并获取对应的 group
  17.                         if (matcher.group(3) != null) {
  18.                             // #Q 在前
  19.                             questionContent = matcher.group(3);
  20.                             standardAnswer = matcher.group(4);
  21.                         } else {
  22.                             // #A 在前
  23.                             questionContent = matcher.group(6);
  24.                             standardAnswer = matcher.group(5);
  25.                         }
  26.                         exam.addQuestion(num, new BasicQuestion(num, questionContent, standardAnswer));
  27.                     } else {
  28.                         System.out.println("wrong format:" + inputLine);
  29.                     }
  30.                 }                // 解析多选题
  31.                 else if (inputLine.startsWith("#Z:")) {
  32.                     Pattern mcPattern = Pattern.compile("#Z:(\\d+)\\s+#Q:(.+?)\\s+#A:(.+)");
  33.                     Matcher matcher = mcPattern.matcher(inputLine);
  34.                     if (matcher.matches()) {
  35.                         int num = Integer.parseInt(matcher.group(1));
  36.                         String questionContent = matcher.group(2);
  37.                         String standardAnswer = matcher.group(3);
  38.                         exam.addQuestion(num, new ChoiceQuestion(num, questionContent, standardAnswer));
  39.                     } else {
  40.                         System.out.println("wrong format:" + inputLine);
  41.                     }
  42.                 }
  43.                 // 解析填空题
  44.                 else if (inputLine.startsWith("#K:")) {
  45.                     Pattern fbPattern = Pattern.compile("#K:(\\d+)\\s+#Q:(.+?)\\s+#A:(.+)");
  46.                     Matcher matcher = fbPattern.matcher(inputLine);
  47.                     if (matcher.matches()) {
  48.                         int num = Integer.parseInt(matcher.group(1));
  49.                         String questionContent = matcher.group(2);
  50.                         String standardAnswer = matcher.group(3);
  51.                         exam.addQuestion(num, new FillInTheBlankQuestion(num,questionContent, standardAnswer));
  52.                     } else {
  53.                         System.out.println("wrong format:" + inputLine);
  54.                     }
  55.                 }
  56.                 // 解析试卷信息
  57.                 else if (inputLine.startsWith("#T:")) {
  58.                     Pattern testPattern = Pattern.compile("#T:(\\d+) ((\\d+-\\d+ ?)+)");
  59.                     Matcher matcher = testPattern.matcher(inputLine);
  60.                     if (matcher.matches()) {
  61.                         int testPaperId = Integer.parseInt(matcher.group(1));
  62.                         List<QuestionScore> paperQuestions = new ArrayList<>();
  63.                         String[] parts = matcher.group(2).split(" ");
  64.                         for (String part : parts) {
  65.                             String[] tValues = part.split("-");
  66.                             int questionNum = Integer.parseInt(tValues[0]);
  67.                             int score = Integer.parseInt(tValues[1]);
  68.                             paperQuestions.add(new QuestionScore(questionNum, score));
  69.                         }
  70.                         testPapers.put(testPaperId, paperQuestions);
  71.                         int totalScore = paperQuestions.stream().mapToInt(QuestionScore::getScore).sum();
  72.                         if (totalScore != 100) {
  73.                             System.out.println("alert: full score of test paper " + testPaperId + " is not 100 points");
  74.                         }
  75.                     } else {
  76.                         System.out.println("wrong format:" + inputLine);
  77.                     }
  78.                 }
  79.                 // 解析学生信息
  80.                 else if (inputLine.startsWith("#X:")) {
  81.                     Pattern studentPattern = Pattern.compile("#X:(.+)");
  82.                     Matcher matcher = studentPattern.matcher(inputLine);
  83.                     if (matcher.matches()) {
  84.                         String[] parts = inputLine.substring(3).split("-");
  85.                         for (String part : parts) {
  86.                             String[] studentData = part.split(" ");
  87.                             int studentId = Integer.parseInt(studentData[0].trim());
  88.                             String studentName = studentData[1].trim();
  89.                             students.put(studentId, new Student(studentId, studentName));
  90.                         }
  91.                     } else {
  92.                         System.out.println("wrong format:" + inputLine);
  93.                     }
  94.                 }
  95.                 // 解析答卷信息
  96.                 else if (inputLine.startsWith("#S:")) {
  97.                     Pattern answerPattern = Pattern.compile("#S:(\\d+) (\\d+)(\\s+(#A:\\d+-(.+)*)*)*");
  98.                     Matcher matcher = answerPattern.matcher(inputLine);
  99.                     if (matcher.matches()) {
  100.                         String[] parts = inputLine.split("#");
  101.                         int testPaperId = Integer.parseInt(parts[1].split(" ")[0].split(":")[1].trim());
  102.                         int studentId = Integer.parseInt(parts[1].split(" ")[1].trim());  // 提取学号
  103.                         AnswerSheet answerSheet = new AnswerSheet(testPaperId);
  104.                         if (parts.length > 2) {
  105.                             for (int i = 2; i < parts.length; i++) {
  106.                                 if (parts[i].startsWith("A:")) {
  107.                                     String[] answerParts = parts[i].split("-");
  108.                                     if (answerParts.length == 2) {
  109.                                         int questionNum = Integer.parseInt(answerParts[0].split(":")[1].trim());
  110.                                         String str = answerParts[1]; // 去除可能的空格
  111.                                         String answer = removeLastSpace(str);
  112.                                         answerSheet.addAnswer(questionNum, answer);
  113.                                     }
  114.                                 }
  115.                             }
  116.                         }
  117.                         answerSheets.computeIfAbsent(studentId, k -> new ArrayList<>()).add(answerSheet);  // 将答卷关联到学生
  118.                     } else {
  119.                         System.out.println("wrong format:" + inputLine);
  120.                     }
  121.                 }
  122.                 // 解析删除题目信息
  123.                 else if (inputLine.startsWith("#D:N-")) {
  124.                     Pattern deletePattern = Pattern.compile("#D:N-(\\d+)");
  125.                     Matcher matcher = deletePattern.matcher(inputLine);
  126.                     if (matcher.matches()) {
  127.                         int questionNum = Integer.parseInt(inputLine.split("-")[1].trim());
  128.                         exam.removeQuestion(questionNum);  // 移除题目
  129.                     }
  130.                     else {
  131.                         System.out.println("wrong format:" + inputLine);
  132.                     }
  133.                 }
  134.             } catch (Exception e) {
  135.                 System.out.println("wrong format");
  136.             }
  137.         }
  138.     }
复制代码
该函数 readExamData 用于从输入中解析并加载试卷系统的相关数据,包括标题、试卷、答卷和门生信息。它通过扫描输入的每一行,根据不同的前缀(如 #N:、#T: 等)区分处置惩罚不同类型的数据。
解析的逻辑主要包括以下部分:
函数通过逐行处置惩罚输入,使用正则表达式确保数据格式的精确性,并对异常或格式错误的输入提供告诫提示,同时确保将各类数据有序地存储到相应的结构中(如 Map、List 等),为试卷系统的后续操作提供数据支持。
AnswerSheet类用于记载考生对某张试卷的答题环境,以及根据试卷内容输出答案详情和得分环境。该类包含了试卷编号、标题信息、考生的答案,以及输出答案和计算得分的逻辑。
outputAnswers方法输出考生的答案以及其对应的精确性。

实现细节:
outputScores类输出考生在每道题上的得分以及总分。

实现细节:
时序图


踩坑心得

1. 乱序输入问题
- 问题形貌:
比如 #N, #Z, #K, #T, #X, #S 等只要是精确格式的信息,可以以任意的先后顺序输入各类不同的信息。比如试卷可以出现在标题之前,删除标题的信息可以出现在标题之前等。
  1. else if (inputLine.startsWith("#S:")) {
  2.                     Pattern answerPattern = Pattern.compile("#S:(\\d+) (\\d+)( (#A:\\d+-(.+)*)*)*");
  3.                     Matcher matcher = answerPattern.matcher(inputLine);
  4.                     if (matcher.matches()) {
  5.                         String[] parts = inputLine.split("#");
  6.                         int testPaperId = Integer.parseInt(parts[1].split(" ")[0].split(":")[1].trim());
  7.                         int studentId = Integer.parseInt(parts[1].split(" ")[1].trim());  // 提取学号
  8.                         List<QuestionScore> paperQuestions = testPapers.get(testPaperId);
  9.                         AnswerSheet answerSheet = new AnswerSheet(testPaperId, paperQuestions);
  10.                         if (parts.length > 2) {
  11.                             for (int i = 2; i < parts.length; i++) {
  12.                                 if (parts[i].startsWith("A:")) {
  13.                                     int questionnum = Integer.parseInt(parts[i].split("-")[0].split(":")[1].trim());
  14.                                     String answer = parts[i].split("-")[1].trim();
  15.                                     answerSheet.addAnswer(questionnum, answer);
  16.                                 }
  17.                             }
  18.                         }
  19.                         answerSheets.computeIfAbsent(studentId, k -> new ArrayList<>()).add(answerSheet);  // 将答卷关联到学生
  20.                     }
复制代码
在上面的代码中举行#S答卷内容的解析,如果按代码的逻辑先获得testPapers.get(testPaperId);就会导致乱序输入试卷在答卷前报错。
解决思路:
AnswerSheet answerSheet = new AnswerSheet(testPaperId);修改AnswerSheet类构造方法,
List questionScores = testPapers.get(testPaperId);
answerSheet.setPaperQuestions(questionScores);在输出类中获取questionScores 再将该值赋给该对象。
2. 多选题、填空题判分逻辑问题
- 问题形貌:
①如果多选题答卷答案与标准答案部分相同,且没有包含不包括在标准答案中的答案,就判断为部分精确,分数计算为该题分数的一半,多余小数直接舍去。
②如果为填空题同理多选题,但标准答案以或连接多个答案,所以可以根据字符拆分精确答案来计算分值。
解决思路
  1.     @Override
  2.     public boolean isPartiallyCorrect(String answer) {
  3.         String[] correctAnswers = this.standardAnswer.split(" ");
  4.         String[] userAnswers = answer.split(" ");
  5.         Set<String> correctSet = new HashSet<>(Arrays.asList(correctAnswers));
  6.         Set<String> userSet = new HashSet<>(Arrays.asList(userAnswers));
  7.         // 判断用户的答案是否为正确答案的子集,且没有多余选项
  8.         return correctSet.containsAll(userSet) && !userSet.equals(correctSet);
  9.     }
复制代码
  1.     @Override
  2.     public CorrectnessLevel getAnswerCorrectnessLevel(String answer) {
  3.         if (isCorrect(answer)) {
  4.             return CorrectnessLevel.CORRECT;
  5.         } else if (isPartiallyCorrectForFillIn(answer)) {
  6.             return CorrectnessLevel.PARTIALLY_CORRECT;
  7.         } else {
  8.             return CorrectnessLevel.INCORRECT;
  9.         }
  10.     }
  11.     // 填空题的部分正确判断
  12.     private boolean isPartiallyCorrectForFillIn(String answer) {
  13.         String[] part = standardAnswer.split("或");
  14.         for (String ne : part) {
  15.             if (answer.equals(ne.trim())) {
  16.                 return true;
  17.             }
  18.         }
  19.         return false;
  20.     }
复制代码
这些判断逻辑根据以下结构体来简化操作逻辑:
  1.     public enum CorrectnessLevel {
  2.         CORRECT,
  3.         PARTIALLY_CORRECT,
  4.         INCORRECT
  5.     }
复制代码
改进发起

· 家居强电电路模拟程序 - 1

标题分析

1. 电路设备分类

设备分为控制设备受控设备两类,每类包含多种具体设备。
2. 电路规则

3. 输入与输出

4. 功能实现焦点

运行逻辑分析

1. 初始化设备

2. 解析输入

3. 建立电路连接

4. 实行命令

5. 状态输出

知识点总结

1. 面向对象编程 (OOP)

2. 继承与类层次计划

3. 电路仿真逻辑

4. 数据结构

5. 输入处置惩罚

6. 流式操作与排序

7. 异常处置惩罚与约束

源码结构分析

1. 焦点模块

2. 电路管理模块

3. 主程序模块

4. 类图计划如下:


以下是程序中几个主要方法的解说,包括它们的功能、实现原理及作用:
1. Circuit.setConnections()

功能:
将所有已添加的设备按照连接关系(connect 方法记载)构建实际的电路。
实现逻辑:
作用:
  1. for (String[] connection : connections) {
  2.     String pin1 = connection[0].split("-")[0];
  3.     String pin2 = connection[1].split("-")[0];
  4.     if (devices.get(pin2) instanceof Ground) {
  5.         Ground GND = (Ground) devices.get(pin2);
  6.         GND.setPreviousDevice(devices.get(pin1));
  7.     }
  8.     devices.get(pin1).connectTo(devices.get(pin2));
  9. }
复制代码
2. VCC.setVoltage()

功能:
为电路提供电压源,并向下传递电压到连接的下一个设备。
实现逻辑:
作用:
  1. public void setVoltage() {
  2.     this.nextDevice.setInputVoltage(voltage);
  3. }
复制代码
3. Switch.toggleStatus()

功能:
切换开关的状态(开/关)。
实现逻辑:
作用:
  1. public void toggleStatus() {
  2.     this.status = !this.status; // 切换状态
  3.     updateState();              // 更新设备状态
  4. }
复制代码
4. StepSpeedController.updateState()

功能:
根据档位(level)调整设备的输出电压,并传递给下一个设备。
实现逻辑:
作用:
  1. @Override
  2. void updateState() {
  3.     this.outputVoltage = getVoltageRatio(level) * inputVoltage; // 根据档位比例计算输出电压
  4.     if (nextDevice != null) {
  5.         if (nextDevice instanceof ControlledDevice) {
  6.             ((ControlledDevice) nextDevice).setInputVoltage(outputVoltage);
  7.         } else if (nextDevice instanceof Switch) {
  8.             ((ControlDevice) nextDevice).setInputVoltage(outputVoltage);
  9.         }
  10.     }
  11. }
复制代码
5. Light.updateState()

功能:
更新灯的亮度,根据电位差(dianshicha)计算亮度值并设置。
实现逻辑:
作用:
  1. @Override
  2. protected void updateState() {
  3.     setDianshicha(); // 计算电位差
  4.     int brightness = 0;
  5.     if (dianshicha < 10) {
  6.         brightness = 0;
  7.     } else if (dianshicha > 10 && dianshicha <= 220) {
  8.         double ratio = (dianshicha - 10) / (220 - 10);
  9.         brightness = (int) (50 + ratio * 150);
  10.     }
  11.     this.setBrightness(brightness);
  12. }
复制代码
5. 顺序图计划如下:


踩坑心得

问题 1:建立串联设备之间关系的困难

在电路计划中,设备是串联的(比如 VCC -> 开关 -> 灯),更新设备状态时需要沿着串联关系逐一传播电压,但一开始不清楚如何在程序中表达这种连接关系并递归更新状态。
解决方案:

实现代码示例:
  1. devices.values().stream()
  2.     .filter(device -> device instanceof Switch)
  3.     .sorted(Comparator.comparing(device -> device.name))
  4.     .forEach(device -> {
  5.         Switch s = (Switch) device;
  6.         System.out.println("@" + s.name + ":" + (!s.status ? "turned on" : "closed"));
  7.     });
复制代码
问题 2:未精确处置惩罚开关的状态对电压传播的影响

假设电路为:VCC -> 白炽灯 -> 开关。
问题分析:

改进方案:

实现代码示例:
  1. abstract class Device {
  2.     protected Device nextDevice;       // 下一个连接设备
  3.     protected double inputVoltage;    // 当前设备输入电压
  4.     public void connectTo(Device nextDevice) {
  5.         this.nextDevice = nextDevice;  // 建立连接
  6.     }
  7.     // 更新设备状态,子类需要重写
  8.     abstract void updateState();
  9.     public void setInputVoltage(double voltage) {
  10.         this.inputVoltage = voltage;
  11.         updateState(); // 根据输入电压更新自身状态
  12.         if (nextDevice != null) {
  13.             nextDevice.setInputVoltage(this.inputVoltage); // 递归传播电压
  14.         }
  15.     }
  16. }
复制代码
改进发起

1. 改进串联设备关系的灵活性

2. 设备状态传播逻辑优化

3. 增强扩展性

4. 计划上的职责分离

· 家居强电电路模拟程序 - 2

标题分析


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4