12 KiB
中小学数学卷子自动生成程序 - 技术文档
1.项目概述
这是一个面向中小学教育的数学题目自动生成系统,支持小学、初中和高中三个学段的数学题目生成。系统提供教师登录验证、题目查重、文件管理等功能,能够根据教师类型生成相应难度和类型的数学题目。
2.运行环境与命令行操作
2.1 运行环境为cmd
如果直接运行java文件,需要执行如下命令行:
chcp 65001
javac -encoding UTF-8 *.java
java Login
如果运行可执行文件,需要执行:
chcp 65001
java -jar 数学卷子生成器.jar
2.2 运行环境为Powershell
如果直接运行java文件,需要执行如下命令行:
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
java Login
这里直接运行可执行文件,需要执行如下命令行:
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
java -jar 数学卷子生成器.jar
3.系统架构
3.1核心类结构
3.2基本模块
3.2.1 Teacher类
Teacher.java 定义了系统中最基本的用户实体模型,它作为一个数据载体,使用标准的JavaBean格式封装了用户的核心属性:用户名、密码和所属学校类型,并通过公共的get和set方法提供对这些属性的安全访问,其他所有业务类都围绕此模型进行操作,同时作为一个抽象基类,衍生出小学、初中、高中老师。
3.2.2 Question类
Question.java 作为所有题目生成器的抽象基类,它定义了一个题目从生成到验证的完整算法框架;它声明了获取运算符、生成基础表达式、添加括号和特殊运算符等抽象方法,交由子类实现,同时提供了验证表达式括号是否匹配、运算符位置是否合法等公共方法,并规定了生成随机操作数的范围,是策略模式的一个典型应用。
3.2.3 Write类
Write.java 承担数据持久化的最终写入任务,它提供了一个静态方法 write,该方法以追加模式打开指定的文件,并将传入的题目序号和内容格式化为“序号. 题目”的标准形式,然后写入文件,每条记录后还写入两个换行符以确保题目间的分隔,整个过程封装在try-with-resources语句中以保证资源能被正确释放。
3.2.4 Equal类
Equal.java 是系统的认证中心,专门负责验证用户登录凭证;其 checkLogin方法会同时遍历传入的小学、初中和高中教师数组,将用户输入的信息与系统中预存的所有教师信息进行比对,它内部调用的 isTeacherMatch方法会严格比较用户名和密码这两个关键字段,只有完全匹配时才认为身份验证通过。
3.2.5 Check类
当前目录查重
单个文件内容查重
Check.java 提供了系统核心的题目查重服务,它的主要方法 check会获取目标文件所在目录,遍历该目录下除自身外的所有历史文件,并调用内部方法 checkFileForDuplicate逐行解析这些文件;该方法会跳过空行,并按“序号. 题目”的格式解析内容,将历史题目与待检查题目进行精确比对,以此判断是否重复,从而保证了题库内容的唯一性。
3.2.6 ProduceFile类
ProduceFile.java 是系统的文件管理工厂,专门负责为每位用户创建有序的存储空间;它的核心方法 produceFile会根据登录教师的用户名,创建相对路径,在“Record”目录下创建对应的专属文件夹,然后使用精确到秒的当前时间戳生成一个唯一的文件名,最终创建并返回这个文件对象,确保了每次生成的试卷文件不会相互覆盖。。
3.2.7 Login类
Login.java 作为系统的主入口和总控制器,它包含了程序的 main方法,负责初始化预置的用户数据、呈现欢迎界面、并管理整个用户交互流程,包括处理用户输入、调用认证模块验证身份、在登录成功后提供切换用户类型和生成题目等选项,是整个应用程序运行的核心调度中心。
4.使用流程
4.1启动系统:运行Login类的main方法启动应用程序
4.2 用户登录:输入用户名和密码进行认证
小学教师:张三1/123, 张三2/123, 张三3/123
初中教师:李四1/123, 李四2/123, 李四3/123
高中教师:王五1/123, 王五2/123, 王五3/123
4.3 选择操作并生成题目
4.3.1 如果选择不需要切换类型,对应的是原来的类型
这里以王五1为例,出高中试卷题15道,出题之后可以继续选择返回主菜单切换还是继续出高中试题或者退出。
4.3.2如果选择切换类型
那么可以切换为小学、初中、高中任意一中类型其他和4.3.1操作类似。
4.4文件查看
发现生成的题目保存在Record/用户名/时间戳.txt文件中。
5.异常处理
5.1 文件操作异常处理
位置: Check.checkFileForDuplicate()方法。
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
// 文件读取操作
} catch (IOException e) {
System.err.println("读取文件失败: " + file.getName() + ", 错误: " + e.getMessage());
// 文件读取失败时不认为重复,避免因IO错误影响正常流程
}
这里使用try-with-resources确保资源自动关闭,捕获IOException并输出错误日志,异常时不中断流程,返回默认值。
5.2 输入验证异常处理
位置: Login类中的输入处理
// 检查输入是否为整数
if (!scanner.hasNextInt()) {
String invalidInput = scanner.next();
System.out.println("请输入有效的整数数字!");
continue;
}
这里主动检查输入类型有效性,提供明确的用户提示信息,并且通过continue语句实现重试机制。
6.扩展性
6.1 面向对象设扩展性
核心扩展点:抽象类与继承体系
public abstract class Question {
protected abstract String getOperator();
protected abstract String generateBaseExpression();
protected abstract String addBrackets(String expression);
protected abstract String addSpecialOperators(String expression);
protected abstract String generateCompoundExpression();
public abstract String generateQuestion();
}
扩展机制:通过继承Question抽象类实现不同学校类型的题目生成,每个子类实现特定的算法逻辑和运算符,支持运行时多态调用。
6.2 学校类型扩展支持
// 小学题目生成
public class PrimaryQuestion extends Question {
// 实现小学特定逻辑
}
// 初中题目生成
public class MiddleQuestion extends Question {
// 实现初中特定逻辑
}
// 高中题目生成
public class HighQuestion extends Question {
// 实现高中特定逻辑
}
扩展特点:新增学校类型只需创建新的Question子类,各学校类型算法独立,互不干扰,同时拥有统一的接口规范,便于管理。
6.3 工厂方法模式应用
位置: 各Teacher类的题目生成方法
// PrimaryTeacher类
public static void PrimaryQuestion(int number, int temps, File paper) {
PrimaryQuestion primaryQuestion = new PrimaryQuestion();
// 使用实例生成题目
}
// MiddleTeacher类
public static void MiddleQuestion(int number, int temps, File paper) {
MiddleQuestion middleQuestion = new MiddleQuestion();
// 使用实例生成题目
}
6.4 策略模式应用
位置: 题目生成算法差异处理
// 各子类实现不同的算法策略
@Override
protected String getOperator() {
// 小学:基础运算符
// 初中:增加平方和开根号
// 高中:增加三角函数
}
7.遇到的困难与解决方式
7.1架构设计不当,类职责划分混乱
在多个Java文件开发过程中,出现了严重的类职责混淆问题。特别是在Teacher类和相关业务类之间,职责边界不清晰。Teacher类本应只负责存储用户基本信息,但实际上却承担了题目生成和文件操作等业务逻辑。这种设计导致了代码耦合度过高,当需要修改用户信息管理或题目生成逻辑时,往往需要同时修改多个类,增加了维护的复杂性。
解决方案:严格遵循单一职责原则进行重构,对Teacher类进行纯数据化改造,移除所有业务逻辑方法,确保其只包含用户基本信息属性和相应的getter/setter方法,同时建立清晰的分层包结构,按照功能模块重新组织代码结构,将业务逻辑、数据模型、工具类等分离到不同的包中。
src/
├── entity/ // 数据实体类:Teacher、Question等
├── service/ // 业务服务类:LoginService、QuestionService
├── util/ // 工具类:Check、Write、ProduceFile
├── question/ // 题目相关类:Question、PrimaryQuestion等
└── main/ // 主程序入口:Login
7.2继承体系困难,抽象类设计复杂
在实现Question抽象类及其子类(PrimaryQuestion、MiddleQuestion、HighQuestion)的过程中,遇到了抽象设计复杂的问题。抽象类中定义了过多必须实现的方法,给子类带来了沉重的实现负担。各学校类型的题目生成算法差异较大,如何在抽象层面统一接口同时保持灵活性成为挑战。多态调用时需要进行类型判断和异常处理,增加了代码的复杂性。
解决方案:优化抽象类方法设计,重新设计Question抽象类,减少必须实现的方法数量,提供更多默认实现,同时采用模板方法模式统一算法骨架,在抽象类中定义题目生成的整体流程,子类只需实现特定步骤,并且实现统一的工厂创建机制,创建专门的工厂类来管理不同学校类型题目的创建,避免在业务代码中直接实例化具体类。
7.3重复代码较多,修改代码复杂
在开发过程中出现了大量的重复代码问题,特别是在各个Teacher类的题目生成方法中。PrimaryTeacher、MiddleTeacher、HighTeacher三个类中的题目生成方法结构几乎完全相同,只有使用的具体Question子类不同。文件操作逻辑在多个地方重复出现,包括文件创建、文件写入、文件读取等操作。输入验证代码也分散在各个地方,没有进行统一管理,导致修改验证逻辑时需要修改多个文件。
解决方案:提取公共工具类消除重复代码,创建专门的工具类来封装重复的业务逻辑,提供统一的方法调用。重构Teacher类消除代码重复,优化各个Teacher类的实现,将重复的逻辑提取到父类或工具类中。统一输入验证和处理流程,创建专门的输入验证类,统一处理所有用户输入验证逻辑。
// 统一的用户登录输入验证
public class LoginInputValidator {}
// 统一的题目数量输入验证
public static int validateQuestionNumber(int number) {}
7.4 仓库使用不熟练,耗费大量时间
在与远程仓库(如GitHub)与头歌交互时遇到诸多困难。对git clone、git pull、git push的使用不够熟练,经常出现权限问题或冲突问题,还会出现文件不见的情况。
解决方案:询问宿舍同学创建以及使用方法,并询问AI怎么把一些发送的指令撤回,比如有一次我的src文件全部丢失了,AI给我指令查询哈希值,可以把之前不见的文件恢复过来,感觉非常有趣又好用,其他的指令通过查看git指令说明书学习。


