答题判题程序(大作业1-3)

答题判题程序(大作业1-3)

一.前言

在过去的几周时间,设计并实现了三个版本的答题程序,模拟一个小型的测试系统。每个版本都在前一个版本的基础上进行了功能的扩展和改进。通过这些项目,不仅深化了对Java编程语言的理解,还掌握了如何设计复杂系统的能力。


PTA第一次作业

这是一个基础版本,主要涉及题目信息的输入和答案的判断。题量较小,难度较低,主要考察基本的字符串处理和逻辑判断能力。通过这个版本的实现,熟悉了基本的输入输出处理,并对题目和答案的基本匹配逻辑进行了梳理。


PTA第二次作业

在此版本中,引入了试卷信息和答卷信息的处理。题量增加,难度中等,要求设计更复杂的数据结构来管理题目与试卷的关系。通过这个版本的实现,学习了如何处理更复杂的数据结构和关系,并在程序中实现了基本的试卷和答卷匹配逻辑。


PTA第三次作业

这是最复杂的版本,增加了学生信息和删除题目信息的处理。题量大,难度高,需要处理更多的边界情况和异常输入。通过这个版本的实现,进一步增强了对复杂系统的理解和处理能力,特别是在处理异常和边界条件方面的能力。

二.设计于分析

PTA作业三次迭代后代码分析

SourceMontor报表

image
总行数: 143
语句数: 94
17.0% 的代码行包含分支语句,
0.7% 的代码行包含注释,
类和接口数量: 4
平均每个类有 2.5 个方法。
方法和复杂性
平均每个方法有 6.9 条语句。
最复杂的方法是 Main.process(),位于第 79 行。
复杂度为 10,
最大块深度为 6,
复杂性分析
最大复杂度: 10,
最深块所在行号: 107,最大块深度为 6,显示出代码某些部分可能过于复杂。

类图

image


Main 类

main(String[]): 主入口方法。
addTestPaper(String): 添加试卷的方法。
addAnswerSheet(String): 添加答题纸的方法。
process(): 处理流程的方法。
addQuestion(String): 添加问题的方法。
TestPaper 类

addQuestion(int, int): 添加问题的方法,接受两个整数参数。
getTotalScore(): 返回总分的方法。


Question类
属性:

id: 问题的唯一标识符。
content: 问题的实际内容。
answer: 问题的标准答案。
作用:

代表一个考试问题,包含问题的基本信息和正确答案

点击查看代码
class Question {
    int id;
    String content;
    String answer;

    public Question(int id, String content, String answer) {
        this.id = id;
        this.content = content;
        this.answer = answer;
    }
}

AnswerSheet类
属性:

testPaperId: 关联的试卷编号。
answers: 用户提交的答案列表。
作用:

代表一份答题纸,存储用户的答案并关联到特定的试卷。

点击查看代码
class AnswerSheet {
    int testPaperId;
    List<String> answers;

    public AnswerSheet(int testPaperId, List<String> answers) {
        this.testPaperId = testPaperId;
        this.answers = answers;
    }
}

TestPaper类
属性:

id: 试卷的唯一标识符。
questions: Map,将题目编号映射到该题目的分值。
方法:

addQuestion(int questionId, int score): 将题目及其分值添加到试卷中。
getTotalScore(): 计算试卷中所有题目的总分。
作用:

管理一个试卷的题目及其分值。

点击查看代码
class TestPaper {
    int id;
    Map<Integer, Integer> questions; // 题目编号到分值的映射

    public TestPaper(int id) {
        this.id = id;
        this.questions = new LinkedHashMap<>();
    }

    public void addQuestion(int questionId, int score) {
        questions.put(questionId, score);
    }

    public int getTotalScore() {
        return questions.values().stream().mapToInt(Integer::intValue).sum();
    }
}

Main类
属性:

questionBank: 存储所有问题的 Map。
testPapers: 存储所有试卷的 Map。
answerSheets: 存储所有答题纸的 List。
方法:

addQuestion(String input): 从输入字符串解析并添加问题。
addTestPaper(String input): 从输入字符串解析并添加试卷。
addAnswerSheet(String input): 从输入字符串解析并添加答题纸。
process(): 处理答题纸,验证答案并计算得分。
main(String[] args): 程序的入口,处理用户输入并调用其他方法。
作用:

管理整个考试系统的逻辑,包括问题、试卷和答题纸的添加和处理。

点击查看代码
public class Main {
    Map<Integer, Question> questionBank = new HashMap<>();
    Map<Integer, TestPaper> testPapers = new HashMap<>();
    List<AnswerSheet> answerSheets = new ArrayList<>();

    public void addQuestion(String input) {
        String[] parts = input.split(" #");
        int id = Integer.parseInt(parts[0].split(":")[1].trim());
        String content = parts[1].split(":")[1].trim();
        String answer = parts[2].split(":")[1].trim();
        questionBank.put(id, new Question(id, content, answer));
    }

    public void addTestPaper(String input) {
        String[] parts = input.split(" ");
        int id = Integer.parseInt(parts[0].split(":")[1].trim());
        TestPaper paper = new TestPaper(id);
        for (int i = 1; i < parts.length; i++) {
            String[] qAndScore = parts[i].split("-");
            int questionId = Integer.parseInt(qAndScore[0]);
            int score = Integer.parseInt(qAndScore[1]);
            paper.addQuestion(questionId, score);
        }
        testPapers.put(id, paper);
    }

三.踩坑心得

1. 输入格式解析

问题:正则表达式解析输入格式时可能会出现匹配错误,尤其是在处理复杂的输入格式时。

心得:确保正则表达式的准确性,并对每种可能的输入格式进行详尽的测试。可以通过添加日志或打印调试信息来检查每个步骤的解析结果。


2. 数据结构选择

问题:选择不当的数据结构可能导致效率低下。例如,使用List存储试卷的题目顺序和分值,可能会导致查找效率低。

心得:使用Map来存储题目和分值的对应关系,可以提高查找效率。在设计数据结构时,应根据使用场景选择合适的结构。


3. 重复数据处理

问题:在处理重复的题目编号、试卷编号或学生编号时,可能会导致数据覆盖或逻辑错误。

心得:在添加数据之前,先检查是否已经存在相同的编号,并在发现重复时输出相应的提示信息。


4. 异常处理

问题:处理输入时可能出现格式错误或数据不一致的问题。

心得:为每种可能的异常情况添加异常处理逻辑,并输出有意义的错误信息。这样可以帮助快速定位问题。


5. 删除题目逻辑

问题:在处理删除题目时,可能会忽略对试卷中引用该题目的处理,导致评分错误。

心得:在删除题目时,确保在评估答案时正确处理已删除的题目,并输出相应的提示信息。

6. 边界条件

问题:在处理答卷信息时,可能会出现缺失答案或多余答案的情况。

心得:在解析答案时,确保处理所有可能的边界情况,例如缺失答案时给出默认值,并在输出中标记答案缺失的情况。


7. 输出格式

问题:输出格式不符合要求,可能导致结果不正确或不易读。

心得:在输出结果时,严格按照要求的格式生成输出,并在开发过程中多次验证输出格式的正确性。改进建议

8.优化

针对目前的实现,可进行如下改进:

代码重构:通过重构复杂的函数,减少代码重复,提高可读性和可维护性。在重构过程中,我们可以使用设计模式来优化代码结构,提高代码的可读性和可维护性。

增强测试覆盖:增加更多的测试用例,特别是针对异常和边界情况的测试,以提高系统的鲁棒性。通过增加测试覆盖,我们可以更好地确保系统的正确性和稳定性。

优化数据结构:考虑使用更高效的数据结构,以提高系统的性能。在优化数据结构的过程中,我们可以使用更高效的算法和数据结构来提高系统的性能。


四.总结

通过这三个项目的开发,不仅提高了编程能力,还学会了如何设计和实现复杂的系统。以下是在这个过程中学到的关键知识:

面向对象设计原则:通过合理的类设计和职责分配,提高了系统的可扩展性和可维护性。学会了如何使用面向对象的原则来设计复杂的系统,并提高了对面向对象编程的理解。

异常处理:通过完善的异常处理机制,增强了系统的鲁棒性。学会了如何设计和实现健壮的异常处理机制,并提高了对异常处理的理解和应用能力。

测试驱动开发:通过编写全面的测试用例,确保了系统的正确性和稳定性。学会了如何使用测试驱动开发的方法来提高系统的质量,并提高了对测试驱动开发的理解和应用能力。

通过本次学习,我们对Java编程和软件设计有了更深入的理解,也期待在未来的学习中能够继续提高自己的技能。我们意识到,编写高质量的软件需要的不仅仅是编程技巧,还需要良好的设计和规划能力,以及对软件工程原则的深刻理解。在未来的学习和工作中,我们将继续探索和应用这些原则,以开发出更高效、更可靠的软件系统。

在这三个项目中,还学会了如何在团队中协作。通过与团队成员的沟通和合作,我们能够更好地理解和解决问题。这种协作能力不仅在项目开发中至关重要,也将在我们未来的职业生涯中发挥重要作用。

此外,还认识到持续学习和改进的重要性。在软件开发领域,技术和工具不断更新,我们需要不断学习和适应,以保持竞争力。在未来的学习中,将继续关注行业的发展趋势,学习新的技术和方法,以提高我们的专业水平。

总之,通过这三个项目的开发,不仅提高了技术能力,也增强了对软件开发过程的理解。这些经验和技能将为未来的学习和职业发展打下坚实的基础。期待在未来的学习和工作中,能够继续应用和发展这些技能,以实现职业目标。

五.附录源码

点击查看代码
import java.util.*;

class Question {
    int id;
    String content;
    String answer;

    public Question(int id, String content, String answer) {
        this.id = id;
        this.content = content;
        this.answer = answer;
    }
}

class TestPaper {
    int id;
    Map<Integer, Integer> questions; // 题目编号到分值的映射

    public TestPaper(int id) {
        this.id = id;
        this.questions = new LinkedHashMap<>();
    }

    public void addQuestion(int questionId, int score) {
        questions.put(questionId, score);
    }

    public int getTotalScore() {
        return questions.values().stream().mapToInt(Integer::intValue).sum();
    }
}

class AnswerSheet {
    int testPaperId;
    List<String> answers;

    public AnswerSheet(int testPaperId, List<String> answers) {
        this.testPaperId = testPaperId;
        this.answers = answers;
    }
}

public class Main {
    Map<Integer, Question> questionBank = new HashMap<>();
    Map<Integer, TestPaper> testPapers = new HashMap<>();
    List<AnswerSheet> answerSheets = new ArrayList<>();

    public void addQuestion(String input) {
        String[] parts = input.split(" #");
        int id = Integer.parseInt(parts[0].split(":")[1].trim());
        String content = parts[1].split(":")[1].trim();
        String answer = parts[2].split(":")[1].trim();
        questionBank.put(id, new Question(id, content, answer));
    }

    public void addTestPaper(String input) {
        String[] parts = input.split(" ");
        int id = Integer.parseInt(parts[0].split(":")[1].trim());
        TestPaper paper = new TestPaper(id);
        for (int i = 1; i < parts.length; i++) {
            String[] qAndScore = parts[i].split("-");
            int questionId = Integer.parseInt(qAndScore[0]);
            int score = Integer.parseInt(qAndScore[1]);
            paper.addQuestion(questionId, score);
        }
        testPapers.put(id, paper);
    }

    public void addAnswerSheet(String input) {
        String[] parts = input.split(" #");
        int testPaperId = Integer.parseInt(parts[0].split(":")[1].trim());
        List<String> answerList = new ArrayList<>();
        for (int i = 1; i < parts.length; i++) {
            answerList.add(parts[i].split(":")[1].trim());
        }
        answerSheets.add(new AnswerSheet(testPaperId, answerList));
    }

    public void process() {
        for (TestPaper paper : testPapers.values()) {
            if (paper.getTotalScore() != 100) {
                System.out.println("alert: full score of test paper" + paper.id + " is not 100 points");
            }
        }

        for (AnswerSheet sheet : answerSheets) {
            TestPaper paper = testPapers.get(sheet.testPaperId);
            if (paper == null) {
                System.out.println("The test paper number does not exist");
                continue;
            }

            int totalScore = 0;
            int answerIndex = 0;
            StringBuilder scoreOutput = new StringBuilder();

            for (Map.Entry<Integer, Integer> entry : paper.questions.entrySet()) {
                int questionId = entry.getKey();
                int score = entry.getValue();
                Question question = questionBank.get(questionId);

                if (answerIndex < sheet.answers.size()) {
                    String givenAnswer = sheet.answers.get(answerIndex);
                    boolean isCorrect = givenAnswer.equals(question.answer);
                    System.out.println(question.content + "~" + givenAnswer + "~" + (isCorrect ? "true" : "false"));
                    if (isCorrect) {
                        totalScore += score;
                        scoreOutput.append(score).append(" ");
                    } else {
                        scoreOutput.append("0 ");
                    }
                } else {
                    System.out.println("answer is null");
                    scoreOutput.append("0 ");
                }
                answerIndex++;
            }
            System.out.println(scoreOutput.toString().trim() + "~" + totalScore);
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Main examSystem = new Main();

        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (line.equals("end")) {
                break;
            }

            if (line.startsWith("#N:")) {
                examSystem.addQuestion(line);
            } else if (line.startsWith("#T:")) {
                examSystem.addTestPaper(line);
            } else if (line.startsWith("#S:")) {
                examSystem.addAnswerSheet(line);
            }
        }

        examSystem.process();
    }
}

posted @   晚风随钰琳  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示