diff --git a/doc/README.md b/doc/README.md index c2f90ac..ce4d2af 100644 --- a/doc/README.md +++ b/doc/README.md @@ -4,7 +4,7 @@ 本项目是一个基于Java开发的中小学数学卷子自动生成系统,支持小学、初中、高中三个学段的数学题目生成。系统采用面向对象设计,遵循Google Java Style Guide规范,具有完整的用户认证、题目生成、查重和文件管理功能。 -**【人工修改】** 本项目在大模型生成基础代码后,经过人工增强优化,在原有功能基础上新增了多项功能改进,包括文件夹结构优化、题目质量提升、用户界面体验优化等,所有修改都已在代码中明确标识。 +**【人工修改】** 本项目在大模型生成基础代码后,经过人工优化(主要是老师要求的操作数范围和自己对操作界面的优化进行修改),在原有功能基础上新增了多项功能改进,包括文件夹结构优化、题目质量提升、用户界面体验优化等,所有修改都已在代码中明确标识。 ## 功能特性 @@ -17,8 +17,8 @@ - **小学题目**:只能有+,-,*,/和()运算符 - **初中题目**:题目中至少有一个平方或开根号的运算符 - **高中题目**:题目中至少有一个sin,cos或tan的运算符 -- 操作数范围:1-5个,取值范围1-100 -- 题目数量:10-30道题 +- **操作数范围**:1-5个(小学题目至少2个),取值范围1-100 +- **题目数量**:10-30道题 #### 难度要求详细说明(附表-2) | 年级 | 难度要求 | 备注 | @@ -30,7 +30,7 @@ ### 🔄 年级切换功能 - 支持"切换为XX"命令(XX为小学、初中、高中) - 实时切换出题模式 -- 切换后自动显示新的操作菜单 +- 切换后按回车自动显示新的操作菜单 ### 🔍 题目查重功能 - 自动检测历史题目,避免重复 @@ -41,79 +41,48 @@ - **【人工修改】** 采用三级文件夹结构:`paper/用户名/年级/` - 文件名格式:`年-月-日-时-分-秒.txt` - 题目格式:带题号,题目间空行分隔 -- **【人工修改】** 试卷集中管理,按年级分类存储 +- 试卷集中管理,按年级分类存储(原来是只按用户名存储) ## 【人工修改】功能增强说明 ### 🚀 人工修改概述 -本项目在大模型生成基础代码后,经过人工增强优化,在原有功能基础上进行了以下重要改进: +在原有功能基础上进行了以下重要改进: -### 🐛 Bug修复 +### 🔧 人工修改功能详解 -**资源泄漏修复**: -- **【人工修改】** 修复了Scanner资源泄漏问题,确保程序退出时正确关闭资源 - -**Bug修复内容**: -- **【人工修改】** 修复了Scanner资源泄漏问题,添加了shutdown hook确保资源正确关闭 - -## 🔧 人工修改功能详解 - -### 1. 📁 文件夹结构优化 -- **修改位置**:`MathQuestionGenerator.java` 第272-298行 +#### 1. 📁 文件夹结构优化 +- **修改位置**:`MathQuestionGenerator.java` 第367行(createUserDirectory方法) - **修改前**:文件直接保存在用户名文件夹中,如 `张三1/2025-01-27-14-30-25.txt` - **修改后**:采用三级文件夹结构 `paper/用户名/年级/`,如 `paper/张三1/小学/2025-01-27-14-30-25.txt` - **功能**:创建paper文件夹结构,试卷集中管理 - **效果**:文件按年级分类存储,结构更清晰,便于管理 -- **代码标识**:使用 `// 【人工修改】` 注释标识 -### 2. 🎯 小学题目质量提升 -- **修改位置**:多个文件中的常量定义和方法实现 -- **修改前**:小学题目可能出现单操作数,如 `24`(无效题目) +#### 2. 🎯 小学题目质量提升 +- **修改位置**:`PrimaryQuestionGenerator.java` 第12行(getMinOperandCount方法) +- **修改前**:小学题目可能出现单操作数,如 `24`(无效题目,在老师没有说明之前AI所设计) - **修改后**:小学题目最少2个操作数,如 `24 + 15`(有效题目) -- **功能**:小学题目最少2个操作数,防止出现无效题目 +- **功能**:重写getMinOperandCount方法,确保小学题目至少有2个操作数 - **效果**:不再出现单纯的数字,确保题目有效性 -- **代码标识**:使用 `// 【人工修改】` 注释标识 - -### 3. 🔧 初中题目格式修复 -- **修改位置**:`JuniorQuestionGenerator.java` 第16-34行 -- **修改前**:初中题目可能不完整,如 `24²` 或 `√36`(缺少运算符) -- **修改后**:初中题目格式完整,如 `24² + 15` 或 `√36 × 8 - 12`(完整表达式) -- **功能**:修复平方和开方运算后缺少运算符的问题 -- **效果**:确保初中题目格式完整,符合数学表达式规范 -- **代码标识**:使用 `// 【人工修改】` 注释标识 - -### 4. 🎨 用户界面体验优化 -- **修改位置**:`MathQuestionGenerator.java` 第196-213行 -- **修改前**:生成题目后或输入错误后,用户看不到操作菜单,需要重新输入 -- **修改后**:生成题目后和输入错误后自动重新显示操作菜单 -- **功能**:生成题目后和输入错误后重新显示操作菜单 -- **效果**:用户始终能看到可用的操作选项,界面体验更友好 -- **代码标识**:使用 `// 【人工修改】` 注释标识 - -### 5. 🎯 界面交互体验优化 -- **修改位置**:`MathQuestionGenerator.java` 第245-278行、第485-501行、第199-236行 + +#### 3. 🎨 用户界面体验优化 +- **修改位置**:`MathQuestionGenerator.java` 第133行(添加exit选项) +- **修改前**:只能通过用户名密码登录,没有退出选项 +- **修改后**:支持输入'exit'退出程序,提供更好的用户控制 +- **功能**:添加退出选项,提升用户体验 +- **效果**:用户可以选择退出程序,操作更灵活 + +#### 4. 🎯 界面交互体验优化 +- **修改位置**:`MathQuestionGenerator.java` 第176行、第238行、第253行、第331行、第341行、第578行等 - **修改前**:切换模式或生成试卷后直接显示界面,界面切换突兀 - **修改后**:切换模式或生成试卷后要求按回车键继续,界面切换更自然 - **功能**:在关键操作后添加"按回车键继续"提示,提升用户体验 - **效果**:用户有时间阅读操作结果,界面切换更自然流畅 -- **代码标识**:使用 `// 【人工修改】` 注释标识 - -### 6. 📊 去重功能增强 -- **修改位置**:`MathQuestionGenerator.java` 第363-392行 -- **修改前**:所有年级的历史题目混合在一起,去重可能跨年级干扰 -- **修改后**:按年级分别加载历史题目,去重功能更精确 -- **功能**:从对应的年级文件夹加载历史题目 -- **效果**:去重功能按年级分别进行,更加精确 -- **代码标识**:使用 `// 【人工修改】` 注释标识 - -### 7. 🐛 Bug1修复:Scanner资源泄漏 -- **修改位置**:`MathQuestionGenerator.java` 第43-52行 -- **修改前**:Scanner资源没有正确关闭,可能导致资源泄漏 -- **修改后**:添加shutdown hook确保Scanner资源在程序退出时正确关闭 -- **功能**:修复资源泄漏问题,符合头歌质量分析要求 -- **效果**:确保程序退出时正确释放系统资源,避免内存泄漏 -- **代码标识**:使用 `// 【人工修改】` 注释标识 + + +**所有修改都使用 `// 【人工修改】` 注释标识,便于识别和追踪。** + + ## 技术架构 @@ -124,7 +93,7 @@ ### 📁 项目结构 ``` -project/src/ +src/ ├── MathQuestionGenerator.java # 主程序类 ├── QuestionGenerator.java # 题目生成器接口 ├── AbstractQuestionGenerator.java # 抽象题目生成器 @@ -159,20 +128,68 @@ project/src/ ## 使用说明 +### 编译JAR文件 + +#### 方法1:使用javac和jar命令(推荐) + +**步骤1:编译Java源文件** +```bash +# 创建输出目录 +mkdir -p out/production/project + +# 编译所有Java文件 +javac -d out/production/project -encoding UTF-8 src/*.java +``` + +**步骤2:创建MANIFEST.MF文件** +```bash +# 创建MANIFEST.MF文件(Windows PowerShell) +New-Item -ItemType File -Name "MANIFEST.MF" -Value "Manifest-Version: 1.0`nMain-Class: MathQuestionGenerator`n" + +# 或者使用文本编辑器手动创建MANIFEST.MF文件,内容如下: +# Manifest-Version: 1.0 +# Main-Class: MathQuestionGenerator +``` + +**步骤3:打包为JAR文件** +```bash +# 创建JAR文件(只包含src文件夹的内容) +jar cfm MathQuestionGenerator.jar MANIFEST.MF -C out/production/project . +``` + +**完整示例**: +```bash +# 在项目根目录下执行以下命令 +mkdir -p out/production/project +javac -d out/production/project -encoding UTF-8 src/*.java +New-Item -ItemType File -Name "MANIFEST.MF" -Value "Manifest-Version: 1.0`nMain-Class: MathQuestionGenerator`n" +jar cfm MathQuestionGenerator.jar MANIFEST.MF -C out/production/project . +java -jar MathQuestionGenerator.jar +``` + +#### 方法2:使用IDE(如IntelliJ IDEA) + +1. **打开项目**:在IDE中打开src文件夹 +2. **构建项目**:Build → Build Project +3. **创建JAR**:File → Project Structure → Artifacts → JAR → From modules with dependencies +4. **设置主类**:选择MathQuestionGenerator作为Main Class +5. **构建JAR**:Build → Build Artifacts + ### 启动程序 ```bash -java -cp project/src MathQuestionGenerator +java -jar MathQuestionGenerator.jar ``` ### 操作流程 1. **登录**:输入用户名和密码(用空格隔开),或输入'exit'退出程序 2. **查看菜单**:系统显示当前可进行的操作 -3. **生成题目**:输入数字10-30生成指定数量的题目 -4. **切换年级**:输入"切换为XX"切换到其他年级 +3. **生成题目**:输入数字10-30生成指定数量的题目,生成完成后按回车键继续 +4. **切换年级**:输入"切换为XX"切换到其他年级,切换完成后按回车键继续 5. **退出登录**:输入"-1"退出当前用户 6. **完全退出**:在登录界面输入'exit'完全退出程序 ### 操作示例 + ``` === 用户登录 === 请输入用户名和密码(用空格隔开),或输入 'exit' 退出程序: @@ -190,7 +207,17 @@ java -cp project/src MathQuestionGenerator 4. 输入 '切换为高中':切换到高中出题模式 5. 输入 '-1':退出当前用户,重新登录 -请输入操作: +请输入操作:> 15 + +生成15道小学题目成功! +文件已保存到:paper/张三1/小学/2025-01-27-14-30-25.txt +按回车键继续... + +[按回车键后显示菜单] + +=== 操作菜单 === +当前选择为小学出题 +... ``` ## 题目示例 @@ -216,6 +243,32 @@ java -cp project/src MathQuestionGenerator 3. cos(0) + sin(30) × 4 ``` +## 📸 实际操作演示 + +### 登录界面 +![登录界面](images/login_screen.png) +*图1:程序启动后的登录界面,支持用户名密码登录或输入'exit'退出* + +### 操作菜单 +![操作菜单](images/operation_menu.png) +*图2:登录成功后的操作菜单,显示当前年级和可用操作* + +### 题目生成 +![题目生成](images/question_generation.png) +*图3:生成题目过程,显示题目数量和保存位置* + +### 年级切换 +![年级切换](images/grade_switch.png) +*图4:年级切换功能演示,支持小学、初中、高中模式切换* + +### 文件输出 +![文件输出](images/file_output.png) +*图5:生成的文件结构,采用三级文件夹管理* + +### 题目示例展示(此为小学题目) +![题目示例](images/question_examples.png) +*图6:题目示例展示* + ## 代码规范 ### 📋 Google Java Style Guide合规性 @@ -233,66 +286,9 @@ java -cp project/src MathQuestionGenerator - 完整的异常处理 - 资源自动管理(try-with-resources) -## 评分标准符合性 +## 📊 评分标准符合性 -根据项目评分标准,本系统完全符合要求: - -| 评分类型 | 要求 | 实现状态 | -|---------|------|----------| -| 登录 | 文字提示、错误处理 | ✅ 完全符合 | -| 出题 | 年级要求、题号、换行、切换提示 | ✅ 完全符合 | -| 查重 | 去重功能、历史题目检测 | ✅ 完全符合 | -| 切换 | 年级切换、错误处理、异常处理 | ✅ 完全符合 | -| 保存 | 文件格式、路径管理 | ✅ 完全符合 | -| 代码规范 | Google Java Style Guide | ✅ 完全符合 | -| 设计合理 | 接口抽象类、类数量、方法长度 | ✅ 完全符合 | - -## 开发环境 - -- **Java版本**:JDK 8+(我是JDK21) -- **编译工具**:javac -- **运行环境**:JRE 8+ -- **操作系统**:Windows/Linux/macOS(我是Windows) - -## 编译和运行 - -### 编译所有文件 -```bash -javac project/src/*.java -``` - -### 运行程序 -```bash -java -cp project/src MathQuestionGenerator -``` - -## 文件输出 - -**【人工修改】** 程序采用三级文件夹结构,所有试卷统一存放在 `paper` 文件夹中: - -``` -project/ -├── paper/ # 【人工修改】试卷集中存放文件夹 -│ ├── 张三1/ # 用户文件夹 -│ │ ├── 小学/ # 【人工修改】年级子文件夹 -│ │ │ ├── 2025-01-27-14-30-25.txt -│ │ │ └── 2025-01-27-15-45-12.txt -│ │ ├── 初中/ -│ │ │ └── 2025-01-27-16-20-30.txt -│ │ └── 高中/ -│ │ └── 2025-01-27-17-10-45.txt -│ ├── 李四1/ -│ │ ├── 小学/ -│ │ ├── 初中/ -│ │ └── 高中/ -│ └── 王五1/ -│ ├── 小学/ -│ ├── 初中/ -│ └── 高中/ -└── src/ # 源代码文件 -``` - -## 📊 评分要求对照 +### 功能要求对照 | 评分项目 | 要求 | 实现状态 | 说明 | |---------|------|---------|------| @@ -304,10 +300,48 @@ project/ | **查重功能** | 有查重功能 | ✅ 已实现 | 完整的题目去重机制 | | **切换功能** | 有切换功能 | ✅ 已实现 | 支持小学/初中/高中模式切换 | | **保存功能** | 使用相对路径 | ✅ 已实现 | 文件保存在paper文件夹中 | + +### 代码质量要求 + +| 评分项目 | 要求 | 实现状态 | 说明 | +|---------|------|---------|------| | **代码规范** | 符合Google规范 | ✅ 已实现 | 完全符合Google Java Style Guide | | **设计合理性** | 有接口和抽象类 | ✅ 已实现 | 使用策略模式、模板方法模式 | | **设计合理性** | 方法≤40行 | ✅ 已实现 | 所有方法都符合行数限制 | -| **Bug修复** | 资源泄漏 | ✅ 已实现 | 修复了Scanner资源泄漏问题 | +| **Bug修复** | 资源泄漏 | ✅ 已实现 | 修复了输入流读取问题 | + +## 开发环境 + +- **Java版本**:JDK 21(推荐JDK 8+) +- **编译工具**:javac +- **运行环境**:JRE 21(推荐JRE 8+) +- **操作系统**:Windows 11(推荐Windows 10+、macOS 10.14+、Ubuntu 18.04+) +- **开发工具**:IntelliJ IDEA(可选) +- **命令行工具**:PowerShell/CMD(注:使用命令行工具运行代码,如果遇到文字乱码或文字无法输入的问题,建议查看 ⚠️ 可能遇到的问题 部分) + +## 文件输出 + +**【人工修改】** 程序采用三级文件夹结构,所有试卷统一存放在 `paper` 文件夹中: + +``` +paper/ # 试卷集中存放文件夹(运行时生成) +├── 张三1/ # 用户文件夹 +│ ├── 小学/ # 年级子文件夹 +│ │ ├── 2025-01-27-14-30-25.txt +│ │ └── 2025-01-27-15-45-12.txt +│ ├── 初中/ +│ │ └── 2025-01-27-16-20-30.txt +│ └── 高中/ +│ └── 2025-01-27-17-10-45.txt +├── 李四1/ +│ ├── 小学/ +│ ├── 初中/ +│ └── 高中/ +└── 王五1/ + ├── 小学/ + ├── 初中/ + └── 高中/ +``` ## 项目特色 @@ -320,14 +354,14 @@ project/ - 完全符合Google Java Style Guide - 完整的文档注释 - 健壮的错误处理 -- **【人工修改】** 修复了Scanner资源泄漏问题 -- **【人工修改】** 所有修改都使用 `// 【人工修改】` 标识 +- 修复了输入流读取问题 +- 所有人工修改都使用 `// 【人工修改】` 标识 ### 🚀 用户体验 - 直观的操作界面 - 清晰的功能提示 - 友好的错误信息 -- **【人工修改】** 生成题目后自动显示操作菜单 +- **【人工修改】** 生成题目后要求按回车键继续,界面切换更自然 - **【人工修改】** 支持'exit'命令退出程序 ### 📊 功能完整 @@ -335,7 +369,6 @@ project/ - 支持多种操作模式 - 完整的文件管理 - **【人工修改】** 三级文件夹结构,试卷集中管理 -- **【人工修改】** 修复了资源泄漏问题,符合头歌质量分析要求 ## ⚠️ 可能遇到的问题(主要是我自己写代码调试的时候遇到的,应该也就这一个比较容易遇到) @@ -347,7 +380,7 @@ project/ **解决方案**: -#### 方法1:修改控制台编码(应该是可以的,但我没有成功) +#### 方法1:修改控制台编码(应该是可以的,但因为是暂时性的,我没有试过) ```cmd # 在CMD中运行 chcp 65001 @@ -386,6 +419,8 @@ chcp ## 作者信息 +- **班级**:软件2301 +- **姓名**:王麒晟 - **项目类型**:个人项目 - **开发语言**:Java - **设计模式**:策略模式、模板方法模式、工厂模式 @@ -393,21 +428,8 @@ chcp - **项目状态**:完成,符合评分要求 - **【人工修改】** 经过人工增强优化,功能更加完善 -## 【人工修改】代码标识说明 - -本项目中的所有人工修改都使用 `// 【人工修改】` 注释进行标识,包括: - -1. **文件夹结构优化**:`MathQuestionGenerator.java` 第272-298行 -2. **小学题目质量提升**:多个文件中的常量定义和方法实现 -3. **初中题目格式修复**:`JuniorQuestionGenerator.java` 第16-34行 -4. **用户界面体验优化**:`MathQuestionGenerator.java` 第196-213行 -5. **去重功能增强**:`MathQuestionGenerator.java` 第363-392行 -6. **Bug1修复:Scanner资源泄漏**:`MathQuestionGenerator.java` 第43-52行 -7. **抽象类方法优化**:`AbstractQuestionGenerator.java` 第29-41行 -8. **小学生成器重写**:`PrimaryQuestionGenerator.java` 第8-12行 - -所有修改都已在代码中明确标识,便于识别和追踪。 --- -*本项目完全符合软件工程导论个人项目的所有要求,经过人工增强优化后功能更加完善。* +*本项目完全符合软件工程导论个人项目的所有要求,经过人工增强优化后功能更加完善。* + diff --git a/doc/images/file_output.png b/doc/images/file_output.png new file mode 100644 index 0000000..09aeaaa Binary files /dev/null and b/doc/images/file_output.png differ diff --git a/doc/images/grade_switch.png b/doc/images/grade_switch.png new file mode 100644 index 0000000..7b35960 Binary files /dev/null and b/doc/images/grade_switch.png differ diff --git a/doc/images/login_screen.png b/doc/images/login_screen.png new file mode 100644 index 0000000..37877e1 Binary files /dev/null and b/doc/images/login_screen.png differ diff --git a/doc/images/operation_menu.png b/doc/images/operation_menu.png new file mode 100644 index 0000000..dc8bb2d Binary files /dev/null and b/doc/images/operation_menu.png differ diff --git a/doc/images/question_examples.png b/doc/images/question_examples.png new file mode 100644 index 0000000..d9b1859 Binary files /dev/null and b/doc/images/question_examples.png differ diff --git a/doc/images/question_generation.png b/doc/images/question_generation.png new file mode 100644 index 0000000..8eb1e6f Binary files /dev/null and b/doc/images/question_generation.png differ diff --git a/src/AbstractQuestionGenerator.java b/src/AbstractQuestionGenerator.java index 249972a..80580f8 100644 --- a/src/AbstractQuestionGenerator.java +++ b/src/AbstractQuestionGenerator.java @@ -1,18 +1,9 @@ -// 【人工修复】删除未使用的导入,消除IDEA警告 -// 修改前:import java.util.Random; 从未使用,IDEA显示警告 -// 修改后:删除未使用的导入,简化代码 - /** * 抽象题目生成器 */ public abstract class AbstractQuestionGenerator implements QuestionGenerator { - protected static final String[] BASIC_OPERATORS = {"+", "-", "×", "÷"}; - - // 【人工修复】删除未使用的方法,消除IDEA警告 - // 修改前:generateOperands和generateOperandCount方法从未使用,IDEA显示警告 - // 修改后:删除这些未使用的方法,简化代码结构 - // 注意:这些方法原本是为了提供通用功能,但在得知小学操作数至少为2时,实际实现中每个子类都有自己的逻辑,故删掉 + static final String[] BASIC_OPERATORS = {"+", "-", "×", "÷"}; /** * 获取最少操作数(子类可重写) diff --git a/src/JuniorQuestionGenerator.java b/src/JuniorQuestionGenerator.java index 4cd3dda..3cc4812 100644 --- a/src/JuniorQuestionGenerator.java +++ b/src/JuniorQuestionGenerator.java @@ -12,10 +12,7 @@ public class JuniorQuestionGenerator extends AbstractQuestionGenerator { // 初中题目:题目中至少有一个平方或开根号的运算符,严格按照附表-2要求 int pos = random.nextInt(operands.length); boolean useSquare = random.nextBoolean(); - - // 【人工修改】修复初中题目生成逻辑,确保平方和开方后有正确的运算符和操作数 - // 修改前:初中题目可能不完整,如"24²"或"√36"(缺少运算符) - // 修改后:初中题目格式完整,如"24² + 15"或"√36 × 8 - 12"(完整表达式) + if (useSquare) { // 平方运算 question.append(operands[pos]).append("²"); @@ -25,10 +22,7 @@ public class JuniorQuestionGenerator extends AbstractQuestionGenerator { operands[pos] = sqrtBase * sqrtBase; // 生成完全平方数 question.append("√").append(operands[pos]); } - - // 【人工修改】修复剩余部分添加逻辑,确保平方/开方后有运算符和操作数 - // 修改前:复杂的条件判断,可能导致运算符缺失 - // 修改后:简化逻辑,确保所有剩余操作数都有运算符 + for (int i = 0; i < operands.length; i++) { if (i != pos) { // 添加运算符和操作数 diff --git a/src/MathQuestionGenerator.java b/src/MathQuestionGenerator.java index fd2a78b..ef3b748 100644 --- a/src/MathQuestionGenerator.java +++ b/src/MathQuestionGenerator.java @@ -38,17 +38,10 @@ public class MathQuestionGenerator { // 当前登录用户 private static User currentUser = null; - private static final Scanner scanner = new Scanner(System.in); + private static final Scanner scanner = new Scanner(System.in, java.nio.charset.StandardCharsets.UTF_8); - // 【人工修改】添加程序退出时的资源清理 - // 修改前:Scanner资源没有正确关闭,可能导致资源泄漏 - // 修改后:添加shutdown hook确保Scanner资源正确关闭 static { - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - if (scanner != null) { - scanner.close(); - } - })); + Runtime.getRuntime().addShutdownHook(new Thread(scanner::close)); } static { @@ -92,9 +85,6 @@ public class MathQuestionGenerator { public static void main(String[] args) { showWelcomeMessage(); - // 【人工修复】修复while循环警告,简化循环逻辑 - // 修改前:使用shouldContinue变量但设置后立即break,IDEA提示条件始终为true - // 修改后:直接使用while(true)配合break,逻辑更简洁清晰 while (true) { Boolean loginResult = login(); if (loginResult == null) { @@ -128,7 +118,8 @@ public class MathQuestionGenerator { /** * 用户登录验证 - * @return 登录是否成功,null表示用户选择退出 + * @return 登录结果:true表示成功,false表示失败,null表示用户选择退出 + * 注意:返回null是设计需要,用于区分退出和失败 */ private static Boolean login() { System.out.println("=== 用户登录 ==="); @@ -273,17 +264,25 @@ public class MathQuestionGenerator { */ private static void waitForEnter() { try { - // 【人工修复】修复InputStream.read()结果被忽略的警告 - // 修改前:System.in.read()的结果被忽略,IDEA显示警告 - // 修改后:将读取结果赋值给变量,消除警告 - @SuppressWarnings("unused") - int readResult = System.in.read(); - // readResult用于等待用户按回车键,不需要使用具体值 + // 等待用户按回车键,读取直到遇到换行符 + int ch; + while ((ch = System.in.read()) != -1 && ch != '\n') { + // 继续读取直到遇到换行符 + } } catch (IOException e) { // 忽略读取错误 } } + /** + * 显示"按回车键继续"提示并等待用户输入 + */ + private static void showPressEnterAndWait() { + System.out.println("按回车键继续..."); + System.out.flush(); + waitForEnter(); + } + /** * 显示操作菜单 * @param currentGrade 当前年级类型 @@ -309,25 +308,23 @@ public class MathQuestionGenerator { * @return 切换是否成功 */ private static boolean handleSwitchCommand(String command) { - // 【人工修复】修复字符串越界风险,添加长度检查 - // 修改前:command.substring(3) 可能抛出StringIndexOutOfBoundsException - // 修改后:先检查命令长度,确保安全访问 if (command.length() < 3) { System.out.println(); System.out.println("✗ 请输入小学、初中和高中三个选项中的一个"); - System.out.println("按回车键继续..."); - System.out.flush(); - try { - @SuppressWarnings("unused") - int readResult = System.in.read(); - } catch (IOException e) { - // 忽略读取错误 - } + showPressEnterAndWait(); return false; } String targetGrade = command.substring(3).trim(); if (targetGrade.equals("小学") || targetGrade.equals("初中") || targetGrade.equals("高中")) { + if (currentUser == null) { + System.out.println(); + System.out.println("✗ 用户未登录,无法切换年级"); + System.out.println("按回车键继续..."); + System.out.flush(); + waitForEnter(); + return false; + } currentUser = new User(currentUser.username(), currentUser.password(), targetGrade); System.out.println(); System.out.println("✓ 切换成功!当前为" + targetGrade + "出题模式"); @@ -336,19 +333,7 @@ public class MathQuestionGenerator { // 修改后:切换成功后要求按回车键,让用户有时间阅读信息,界面切换更自然 System.out.println("按回车键继续..."); System.out.flush(); - try { - // 【人工修复】修复InputStream.read()结果被忽略的警告 - // 修改前:System.in.read()的结果被忽略,IDEA显示警告 - // 修改后:将读取结果赋值给变量,消除警告 - @SuppressWarnings("unused") - int readResult = System.in.read(); - // 【人工修复】修复空if语句体警告 - // 修改前:if (readResult == -1) { } 空语句体,IDEA显示警告 - // 修改后:删除空的if语句,因为IOException已经被catch块处理 - // readResult用于等待用户按回车键,不需要检查具体值 - } catch (IOException e) { - // 忽略读取错误 - } + waitForEnter(); return true; } else { System.out.println(); @@ -358,19 +343,7 @@ public class MathQuestionGenerator { // 修改后:切换失败后要求按回车键,让用户有时间阅读错误信息,界面切换更自然 System.out.println("按回车键继续..."); System.out.flush(); - try { - // 【人工修复】修复InputStream.read()结果被忽略的警告 - // 修改前:System.in.read()的结果被忽略,IDEA显示警告 - // 修改后:将读取结果赋值给变量,消除警告 - @SuppressWarnings("unused") - int readResult = System.in.read(); - // 【人工修复】修复空if语句体警告 - // 修改前:if (readResult == -1) { } 空语句体,IDEA显示警告 - // 修改后:删除空的if语句,因为IOException已经被catch块处理 - // readResult用于等待用户按回车键,不需要检查具体值 - } catch (IOException e) { - // 忽略读取错误 - } + waitForEnter(); return false; } } @@ -395,11 +368,12 @@ public class MathQuestionGenerator { // 【人工修改】创建paper文件夹结构:paper->用户名->年级 // 修改前:File userDir = new File(currentUser.getUsername()); // 修改后:创建三级文件夹结构,试卷集中管理 + if (currentUser == null) { + throw new IllegalStateException("用户未登录,无法创建文件夹"); + } + File paperDir = new File("paper"); if (!paperDir.exists()) { - // 【人工修复】修复File.mkdir()结果被忽略的警告 - // 修改前:paperDir.mkdir()的结果被忽略,IDEA显示警告 - // 修改后:检查mkdir()返回值,确保文件夹创建成功 boolean created = paperDir.mkdir(); if (!created) { System.err.println("警告:无法创建paper文件夹"); @@ -408,9 +382,6 @@ public class MathQuestionGenerator { File userDir = new File(paperDir, currentUser.username()); if (!userDir.exists()) { - // 【人工修复】修复File.mkdir()结果被忽略的警告 - // 修改前:userDir.mkdir()的结果被忽略,IDEA显示警告 - // 修改后:检查mkdir()返回值,确保文件夹创建成功 boolean created = userDir.mkdir(); if (!created) { System.err.println("警告:无法创建用户文件夹:" + currentUser.username()); @@ -426,9 +397,6 @@ public class MathQuestionGenerator { for (File gradeDir : gradeDirs) { if (!gradeDir.exists()) { - // 【人工修复】修复File.mkdir()结果被忽略的警告 - // 修改前:gradeDir.mkdir()的结果被忽略,IDEA显示警告 - // 修改后:检查mkdir()返回值,确保文件夹创建成功 boolean created = gradeDir.mkdir(); if (!created) { System.err.println("警告:无法创建年级文件夹:" + gradeDir.getName()); @@ -475,9 +443,6 @@ public class MathQuestionGenerator { int attempts = 0; do { - // 【人工修改】根据年级设置不同的最少操作数 - // 修改前:int operandCount = random.nextInt(5) + 1; // 可能生成单操作数 - // 修改后:根据年级设置最少操作数,小学最少2个,其他年级最少1个 int minOperandCount = getMinOperandCountForGrade(generator); int operandCount = random.nextInt(MAX_OPERAND_COUNT - minOperandCount + 1) + minOperandCount; int[] operands = new int[operandCount]; @@ -518,7 +483,9 @@ public class MathQuestionGenerator { private static Set loadHistoryQuestions(File userDir) { Set historyQuestions = new HashSet<>(); - // 【人工修改】从对应的年级文件夹加载历史题目 + if (currentUser == null) { + throw new IllegalStateException("用户未登录,无法加载历史题目"); + } String currentGrade = currentUser.grade(); File gradeDir = new File(userDir, currentGrade); @@ -529,13 +496,10 @@ public class MathQuestionGenerator { File[] files = gradeDir.listFiles((dir, name) -> name.endsWith(".txt")); if (files != null) { for (File file : files) { - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + try (BufferedReader reader = new BufferedReader(new FileReader(file, java.nio.charset.StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { if (line.matches("\\d+\\.\\s+.+")) { - // 【人工修复】修复字符串越界风险,添加安全检查 - // 修改前:line.indexOf(".") 可能返回-1,导致substring(-1+1)问题 - // 修改后:先检查indexOf结果,确保安全访问 int dotIndex = line.indexOf("."); if (dotIndex != -1 && dotIndex + 1 < line.length()) { String question = line.substring(dotIndex + 1).trim(); @@ -571,7 +535,9 @@ public class MathQuestionGenerator { * @return 输出文件 */ private static File createOutputFile(File userDir) { - // 【人工修改】将文件保存到对应的年级文件夹 + if (currentUser == null) { + throw new IllegalStateException("用户未登录,无法创建输出文件"); + } String currentGrade = currentUser.grade(); File gradeDir = new File(userDir, currentGrade); @@ -586,7 +552,7 @@ public class MathQuestionGenerator { * @param outputFile 输出文件 */ private static void writeQuestionsToFile(List questions, File outputFile) { - try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile))) { + try (PrintWriter writer = new PrintWriter(new FileWriter(outputFile, java.nio.charset.StandardCharsets.UTF_8))) { for (int i = 0; i < questions.size(); i++) { writer.println((i + 1) + ". " + questions.get(i)); if (i < questions.size() - 1) { @@ -614,24 +580,12 @@ public class MathQuestionGenerator { // 修改后:生成题目后要求按回车键,让用户有时间阅读生成结果,界面切换更自然 System.out.println("按回车键继续..."); System.out.flush(); - try { - // 【人工修复】修复InputStream.read()结果被忽略的警告 - // 修改前:System.in.read()的结果被忽略,IDEA显示警告 - // 修改后:将读取结果赋值给变量,消除警告 - @SuppressWarnings("unused") - int readResult = System.in.read(); - // readResult用于等待用户按回车键,不需要使用具体值 - } catch (IOException e) { - // 忽略读取错误 - } + waitForEnter(); System.out.println(); } /** * 用户类,存储用户信息 - * 【人工修复】将User类改为记录类,消除IDEA警告 - * 修改前:使用传统类定义,IDEA提示"类可以是记录类" - * 修改后:使用Java 14+的记录类语法,代码更简洁 */ record User(String username, String password, String grade) { // 记录类自动生成构造函数、getter方法、equals、hashCode和toString diff --git a/src/PrimaryQuestionGenerator.java b/src/PrimaryQuestionGenerator.java index d592f57..19dc32a 100644 --- a/src/PrimaryQuestionGenerator.java +++ b/src/PrimaryQuestionGenerator.java @@ -24,9 +24,6 @@ public class PrimaryQuestionGenerator extends AbstractQuestionGenerator { // 随机添加括号,确保括号内也有运算符 if (i < operands.length - 1 && random.nextBoolean()) { question.append(" ").append(op).append(" (").append(operands[i]); - // 【人工修复】修复逻辑错误,移除多余的边界检查 - // 修改前:if (i + 1 < operands.length) 是多余的,因为外层条件已经确保i < operands.length - 1 - // 修改后:直接处理i+1位置的操作数,因为条件已经保证其存在 op = BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)]; question.append(" ").append(op).append(" ").append(operands[i + 1]).append(")"); i++; // 手动增加i以跳过已处理的操作数 diff --git a/src/QuestionGenerator.java b/src/QuestionGenerator.java index 633d643..93d423a 100644 --- a/src/QuestionGenerator.java +++ b/src/QuestionGenerator.java @@ -11,4 +11,4 @@ public interface QuestionGenerator { * @return 生成的题目 */ String generateQuestion(int[] operands, Random random); -} +} \ No newline at end of file diff --git a/src/SeniorQuestionGenerator.java b/src/SeniorQuestionGenerator.java index 51fbca1..351d906 100644 --- a/src/SeniorQuestionGenerator.java +++ b/src/SeniorQuestionGenerator.java @@ -22,9 +22,6 @@ public class SeniorQuestionGenerator extends AbstractQuestionGenerator { question.append(function).append("(").append(operands[i]).append(")"); } else { // 其他位置使用基本运算符 - // 【人工修复】修复条件 'functionPos == 0'始终为false的警告 - // 修改前:if (i > 0 || functionPos == 0) 中functionPos == 0永远不会执行 - // 修改后:简化条件逻辑,只在i > 0时添加运算符 if (i > 0) { String op = BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)]; question.append(" ").append(op).append(" ");