You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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核心类结构

alt text

3.2基本模块

3.2.1 Teacher类

alt text Teacher.java 定义了系统中最基本的用户实体模型它作为一个数据载体使用标准的JavaBean格式封装了用户的核心属性用户名、密码和所属学校类型并通过公共的get和set方法提供对这些属性的安全访问其他所有业务类都围绕此模型进行操作,同时作为一个抽象基类,衍生出小学、初中、高中老师。

3.2.2 Question类

alt text Question.java 作为所有题目生成器的抽象基类,它定义了一个题目从生成到验证的完整算法框架;它声明了获取运算符、生成基础表达式、添加括号和特殊运算符等抽象方法,交由子类实现,同时提供了验证表达式括号是否匹配、运算符位置是否合法等公共方法,并规定了生成随机操作数的范围,是策略模式的一个典型应用。

3.2.3 Write类

alt text Write.java 承担数据持久化的最终写入任务,它提供了一个静态方法 write该方法以追加模式打开指定的文件并将传入的题目序号和内容格式化为“序号. 题目”的标准形式然后写入文件每条记录后还写入两个换行符以确保题目间的分隔整个过程封装在try-with-resources语句中以保证资源能被正确释放。

3.2.4 Equal类

alt text Equal.java 是系统的认证中心,专门负责验证用户登录凭证;其 checkLogin方法会同时遍历传入的小学、初中和高中教师数组将用户输入的信息与系统中预存的所有教师信息进行比对它内部调用的 isTeacherMatch方法会严格比较用户名和密码这两个关键字段只有完全匹配时才认为身份验证通过。

3.2.5 Check类

当前目录查重 alt text 单个文件内容查重 alt text Check.java 提供了系统核心的题目查重服务,它的主要方法 check会获取目标文件所在目录遍历该目录下除自身外的所有历史文件并调用内部方法 checkFileForDuplicate逐行解析这些文件该方法会跳过空行并按“序号. 题目”的格式解析内容,将历史题目与待检查题目进行精确比对,以此判断是否重复,从而保证了题库内容的唯一性。

3.2.6 ProduceFile类

alt text ProduceFile.java 是系统的文件管理工厂,专门负责为每位用户创建有序的存储空间;它的核心方法 produceFile会根据登录教师的用户名创建相对路径在“Record”目录下创建对应的专属文件夹然后使用精确到秒的当前时间戳生成一个唯一的文件名最终创建并返回这个文件对象确保了每次生成的试卷文件不会相互覆盖。。

3.2.7 Login类

alt text Login.java 作为系统的主入口和总控制器,它包含了程序的 main方法负责初始化预置的用户数据、呈现欢迎界面、并管理整个用户交互流程包括处理用户输入、调用认证模块验证身份、在登录成功后提供切换用户类型和生成题目等选项是整个应用程序运行的核心调度中心。

4.使用流程

4.1启动系统运行Login类的main方法启动应用程序

alt text

4.2 ​用户登录​​:输入用户名和密码进行认证

小学教师张三1/123, 张三2/123, 张三3/123
初中教师李四1/123, 李四2/123, 李四3/123
高中教师王五1/123, 王五2/123, 王五3/123

alt text

4.3 选择操作并生成题目

4.3.1 如果选择不需要切换类型,对应的是原来的类型

alt text 这里以王五1为例出高中试卷题15道出题之后可以继续选择返回主菜单切换还是继续出高中试题或者退出。

4.3.2如果选择切换类型

alt text 那么可以切换为小学、初中、高中任意一中类型其他和4.3.1操作类似。

4.4文件查看

alt text 发现生成的题目保存在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指令说明书学习。