Java题目集1~3
前言
本阶段的Java课程作业中,我们完成了从题目集1到题目集3的任务。每个题目集围绕一个或多个编程主题,难度逐步增加,从基本语法操作到较为复杂的面向对象设计,循序渐进地帮助我构建和巩固编程知识。以下是每个题目集的概述:
题目集1:基础语法训练,涵盖了基本的循环、条件判断、输入输出等操作。适合初学者打基础。
题目集2:引入简单的数据结构如数组,以及简单的类和方法的使用,重点在数据处理和条件分支控制。
题目集3:完成一个题目、试卷、答卷管理的模拟系统。重点考察面向对象设计,包括如何在多个类之间协同操作,并进行输入验证、数据解析、异常处理等。
题目集3相对复杂,要求我们设计出能够管理题目、试卷、答题信息等多种数据的结构化系统,因此是对前两次题目集知识点的综合应用和提升。本文将重点针对题目集3的代码设计与实现进行深入分析,并结合开发过程中遇到的问题和经验,总结改进思路。
1.设计与分析
题目集1的设计分析
题目集1的程序设计我主要设计了三个类:Question(题目类)、Shijuan(试卷类)、Dajuan(答卷类)。通过面向对象的设计,简洁地实现了题目的添加、答题判定、和结果输出的功能。
Question类:用于表示单个题目,包含题目编号、内容、标准答案等属性,并提供方法来验证用户答案是否正确。
Shijuan类:作为试卷类,使用List集合存储多个Question对象,提供了添加题目和按编号获取题目的功能。
Dajuan类:表示用户的答卷,包含一个Shijuan对象、用户的答案和判题结果。该类实现了保存用户答案、判题、输出答题信息及判题结果等功能。
Main类负责交互式数据输入,并调用各个类的方法以输出用户的答题情况及判题结果。
类图
顺序图
题目集2的设计分析
我主要设计四个类组成:TiMu、ShiJuan、DaJuan 和 Main。TiMu 类表示单个题目,包含题目编号、题目内容和标准答案,并提供判定答案的功能。ShiJuan 类代表试卷,包含多个题目 ID 及其分值,并计算总分和判卷。DaJuan 类表示答卷,存储用户答案并提供获取功能。Main 类负责输入处理、创建试题、试卷和答卷对象,并执行答卷判定。
相比题目1,本程序的设计在 TiMu、ShiJuan 和 DaJuan 类之间使用了解析方法,适合处理特定格式的输入。ShiJuan 类内实现了总分校验功能,用以确保总分为 100 分。这些类结构和功能更适合面向文本解析的题库系统。
类图
顺序图
题目集3的设计分析
题目集3的核心是设计一个包含题目、试卷和答卷的模拟系统。以下是题目集3的设计与类图分析,并结合SourceMonitor报表的数据进行代码复杂度的详细分析。
类结构与代码示例
题目集3涉及多个类,包括Student、Question、TestPaper、Answer以及主类Main。以下是Question类的简化代码,用于存储每道题目及其答案:
public class Question {
private String questionText;
private String correctAnswer;
private boolean isDeleted;
public Question(String questionText, String correctAnswer) {
this.questionText = questionText;
this.correctAnswer = correctAnswer;
this.isDeleted = false;
}
}
- 项目设计概览
题目集3的设计目标是创建一个能够管理题目、试卷、答卷的模拟系统。整个系统的输入包括题目信息、试卷信息、学生信息和答题记录,输出包括每位学生的答题情况、正确与否的判定以及总分等。这一题目集考察了如何利用面向对象编程实现复杂的数据管理和操作。
主要的输入数据类型:
题目信息:包含题号、题目描述、正确答案。
试卷信息:包含试卷编号和每道题的分值。
学生信息:包括学生学号和姓名。
答题信息:包括学生的答题记录和对答案正确性的验证。
删除题目信息:模拟题目被删除的情况,并根据此类信息在判分时做出“无效题”的处理。
为完成这一题目,我设计了多个类,每个类负责一种特定的数据管理任务。主要的类包括Question
(题目信息)、TestPaper
(试卷信息)、Student
(学生信息)等,且由Main
类负责解析输入,调用相应方法处理逻辑。
- 类设计与结构
2.1 Question类
Question类用于存储每道题目的文本信息、正确答案,并提供一个isDeleted
属性,用于标识题目是否被删除,以便后续判分时排除无效题。以下是该类的核心代码:
class Question {
String questionText;
String correctAnswer;
boolean isDeleted = false;
Question(String questionText, String correctAnswer) {
this.questionText = questionText;
this.correctAnswer = correctAnswer;
}
}
设计Question类时,我们注重保持数据的封装性,使题目、答案及删除状态等信息都存储在一个独立对象中,便于后续的操作和维护。删除状态通过isDeleted
字段实现,可以在判分时用简单的条件判断来跳过已删除的题目。
2.2 TestPaper类
TestPape类用于存储每张试卷的基本信息,包括试卷编号和题目分值的映射。此处使用了LinkedHashMap来保持题目的顺序,确保试卷题目输出时的顺序一致:
class TestPaper {
int paperNumber;
Map<Integer, Integer> questionScores = new LinkedHashMap<>();
TestPaper(int paperNumber) {
this.paperNumber = paperNumber;
}
public int getTotalScore() {
return questionScores.values().stream().mapToInt(Integer::intValue).sum();
}
}
TestPaper类的关键在于分数的管理和总分的计算。getTotalScore
方法通过累加所有题目的分值来得出总分。此外,在测试和调试中,我们通过一个简单的检查代码,确保每张试卷的总分是否为100分,并在出现异常时发出提示。这种封装分值信息的方式在大型试卷中尤为实用,可以避免复杂的逻辑干扰主流程。
2.3 Student类
Studen类主要用于存储学生的学号和姓名,便于后续在答卷数据中进行关联和查询。以下是该类的代码:
static class Student {
String id;
String name;
Student(String id, String name) {
this.id = id;
this.name = name;
}
}
简单的Student类使我能够轻松存储并查找学生的基本信息,并在判分时方便地与答题数据关联。对于实际使用场景,学号与姓名的匹配确保了每一份答卷都可以准确无误地分配到对应的学生信息。
类图
顺序图
- 数据解析与处理
在Main类中,我们设计了多个解析方法,来处理题目、试卷、学生和答题等信息。每个解析方法都根据不同的输入格式进行解析,必要时进行错误提示与异常捕获。这种设计保证了系统能够灵活应对不同的数据输入需求。
以下是题目解析方法的示例:
private static void parseQuestionInfo(String input) {
String[] parts = input.split(" ");
if (parts.length != 3 || !parts[0].startsWith("#N:") || !parts[1].startsWith("#Q:") || !parts[2].startsWith("#A:")) {
throw new IllegalArgumentException();
}
int questionNumber = Integer.parseInt(parts[0].substring(3));
String questionText = parts[1].substring(3);
String correctAnswer = parts[2].substring(3);
questions.put(questionNumber, new Question(questionText, correctAnswer));
}
每次解析时,我都做了严格的输入格式检查,例如对字符串的前缀(如#N:
、#Q:
、#A:
)进行验证,确保输入符合标准格式。否则系统会抛出IllegalArgumentException
异常。这种结构清晰、易于调试,同时能够有效降低格式错误对系统的影响。
- 判分与反馈
题目集3的判分过程在parseAnswerInfo方法中实现,系统会逐个检查题目、和正确答案是否匹配,并根据题目分值给出相应分数。同时,如果某题目被删除,系统会将其标记为“无效题”,不计入总分:
if (question.isDeleted) {
outputs.add("the question " + questionNumber + " invalid~0");
totalScore += 0;
} else if (studentAnswer.equals(question.correctAnswer)) {
outputs.add(question.questionText + "~" + studentAnswer + "~true");
totalScore += questionScore;
} else {
outputs.add(question.questionText + "~" + studentAnswer + "~false");
totalScore += 0;
}
此处逻辑设计简洁明了,对于已删除的题目,通过isDeleted判断可以有效跳过。由于题目和答案的多样性,我们在实际判分中增加了异常处理,以便在答案格式不符时输出“answer is null”而非终止程序。
踩坑心得
- 输入格式与异常处理
开发过程中遇到的一个主要问题是输入格式不一致或不完整,导致程序解析失败。为解决此问题,我们在解析过程中添加了详细的输入格式验证。通过try-catch
机制捕获异常,并在遇到异常时输出提示信息,而非直接中断程序:
try {
// 解析输入
} catch (Exception e) {
outputs.add("wrong format:" + input);
}
这种方式大大提高了系统的健壮性,使其能够灵活应对输入格式错误。
- 判分时题目缺失处理
在判分过程中,常常会出现学生的**缺失某些题目的情况。为应对这一问题,我们在判分逻辑中增加了判断逻辑,确保在无对应答案时输出“answer is null”。
- 数据结构优化
在试卷解析和判分过程中,我发现HashMap并不能保证题目顺序。后续我改用LinkedHashMap,确保试卷的题目顺序与输入一致。这样可以更高效地完成题目和答案的对应判断,避免了无序引发的逻辑错误。
改进建议
-
代码结构优化:可以将解析和判分的逻辑拆分成单独的类或模块,提高代码的可读性和模块化。
-
增强输入处理:未来可以使用正则表达式或设计特定输入解析类,对输入格式进行更严谨的验证。
-
引入设计模式:可以使用工厂模式创建解析器,减少主类中的复杂判断逻辑,使代码结构更加清晰和灵活。
-
简化判分逻辑:引入表驱动法(如分数映射表)来简化条件判断,使得判分过程更高效。
针对题目3的几个类可以进行以下改进:
Question 类:引入多态支持,创建不同题型的子类来处理选择题、填空题等。使用状态枚举(如 ACTIVE、DELETED)替代布尔变量,以简化状态管理,并将验证逻辑拆分为独立的验证类,从而保持 Question 类的简洁性。
TestPaper 类:为试卷添加题目分组功能,通过 Map 结构按题型或难度管理题目,支持动态题型组合。引入构建器模式(Builder Pattern)让试卷生成更灵活,同时支持动态分数配置,使分数的调整无需更改代码。分数统计可以细分到各个题型或题组,帮助老师更清晰地了解学生的各方面成绩。
Student 类:增加学生答题记录功能,记录每道题的得分和正确性,以便于后期分析。添加错题库功能,将答错题目保存,便于反馈和复习。此外,可根据得分为学生评定等级,激励学生提升。
总结
在这三次题目集的开发过程中,通过编写和优化题库系统,我加深了对面向对象编程(OOP)设计原则的理解,特别是在如何设计和组织类结构方面。每个题目集都带来了新的挑战和学习机会,让我在编码、数据解析、判分逻辑等方面得到了显著提升。
主要学到的内容如下:
面向对象设计与封装:
在系统的设计中,每个类都承担了明确的职责,例如Question类负责存储题目信息,TestPaper类管理试卷,Student类保存学生信息。这种职责分离的设计思想,提高了代码的可维护性和扩展性。
数据的封装性得到加强,通过适当的字段设置和方法划分,保证了数据的安全性和模块化,避免了数据直接被外部修改的问题。
数据解析与处理:
编写解析方法时,重点关注了数据格式的标准化和异常处理机制。这一过程培养了我处理多种格式数据的思维,使代码具备较高的通用性和鲁棒性,能够应对不同的数据输入格式。
代码调试与优化:
在实现判分功能时,增加了对无效题目的过滤,使系统更加人性化且灵活。这也让我认识到代码调试的重要性,尤其是在涉及复杂逻辑时,借助单元测试逐步验证功能的正确性。
在这个项目中,虽然完成了基本的功能,但也暴露出一些技术盲点和学习需求,具体如下:
异常处理与日志系统:
要进一步学习如何使用日志系统进行高效的错误跟踪,以更好地调试复杂系统。此外,对于异常处理的深度掌握也尤为重要,未来可以探索更多关于异常处理最佳实践的内容。
设计模式应用:
在大型系统设计中,设计模式往往能帮助我们简化复杂代码结构。比如,这里可以考虑应用工厂模式或构建者模式来构建题目和试卷对象。了解更多设计模式的实际应用将有助于在未来构建更为灵活、可维护的系统。
标签:题目,String,判分,试卷,Question,BLOG,解析 From: https://www.cnblogs.com/pppt/p/18504602