diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f68d109
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..779255b
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..dca0e52
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..e0086d8
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {}
+ {
+ "isMigrated": true
+}
+
+
+
+ {
+ "associatedIndex": 1
+}
+
+
+
+
+
+
+
+
+ {
+ "keyToString": {
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "SHARE_PROJECT_CONFIGURATION_FILES": "true",
+ "git-widget-placeholder": "develop",
+ "kotlin-language-version-configured": "true",
+ "last_opened_file_path": "C:/Users/ASUS/OneDrive/Desktop/paper_generator/src",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "project.structure.last.edited": "工件",
+ "project.structure.proportion": "0.15",
+ "project.structure.side.proportion": "0.2",
+ "settings.editor.selected.configurable": "configurable.group.tools",
+ "vue.rearranger.settings.migration": "true",
+ "应用程序.MathExamGenerator.executor": "Run"
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1758627387353
+
+
+ 1758627387353
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1758718169046
+
+
+
+ 1758718169046
+
+
+
+ 1758721030985
+
+
+
+ 1758721030986
+
+
+
+ 1758976924192
+
+
+
+ 1758976924192
+
+
+
+ 1758979600757
+
+
+
+ 1758979600757
+
+
+
+ 1759046417724
+
+
+
+ 1759046417724
+
+
+
+ 1759046442793
+
+
+
+ 1759046442793
+
+
+
+ 1759055214485
+
+
+
+ 1759055214485
+
+
+
+ 1759055292192
+
+
+
+ 1759055292192
+
+
+
+ 1759055353424
+
+
+
+ 1759055353424
+
+
+
+ 1759055878739
+
+
+
+ 1759055878739
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PaperGenerator.iml b/PaperGenerator.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/PaperGenerator.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index fb79287..0000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# paper_generator
-
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 0000000..a82cd63
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,170 @@
+# 中小学数学试卷生成系统
+
+一个基于Java的命令行应用程序,能够根据不同年级自动生成相应难度的数学试卷。
+
+## 项目简介
+
+这是一个专为中小学教师、学生和家长设计的数学试卷自动生成工具。系统支持小学、初中、高中三个教育阶段,能够生成符合各阶段教学要求的数学题目,并自动保存为试卷文件。
+
+## 功能特性
+
+### 🎯 用户管理
+- 支持9个预置用户账号(张三1-3、李四1-3、王五1-3)
+- 自动识别用户对应的教育级别(小学/初中/高中)
+- 安全的用户名密码验证机制
+
+### 📚 题目生成
+- **小学阶段**:四则运算、混合运算、带括号运算
+- **初中阶段**:混合运算、分数运算、方程求解、幂运算和开方
+- **高中阶段**:二次方程、函数计算、三角函数、概率、数列、导数、复数运算
+
+### 📄 试卷管理
+- 支持生成10-30道题目
+- 智能题目去重机制,确保题目不重复
+- 按用户分类自动保存试卷文件
+- 时间戳命名,便于管理
+
+### 💻 交互体验
+- 友好的命令行交互界面
+- 支持切换年级级别
+- 用户登出和重新登录功能
+
+## 技术架构
+
+### 开发环境
+- **编程语言**:Java 21
+- **开发工具**:IntelliJ IDEA
+- **项目类型**:纯Java控制台应用程序
+
+### 项目结构
+```
+src/com/bx/
+├── generator_main/ # 主程序入口
+├── manager/ # 业务管理层
+├── question/ # 题目相关
+│ └── generator/ # 题目生成器
+```
+
+### 设计模式
+- **工厂模式**:`QuestionFactory`根据难度级别分发题目生成
+- **策略模式**:不同年级采用不同的题目生成策略
+- **分层架构**:清晰的职责分离,便于维护和扩展
+
+## 快速开始
+
+### 环境要求
+- Java 21或更高版本
+- 支持UTF-8编码
+
+### 运行步骤
+1. 克隆项目到本地
+2. 使用IntelliJ IDEA打开项目
+3. 运行 `src/com/bx/generator_main/MathExamGenerator.java`
+4. 或者使用 `java -jar PaperGenerator.jar` 指令运行提供的jar包
+4. 使用预置账号登录:
+ - 小学用户:张三1/123、李四1/123、王五1/123
+ - 初中用户:张三2/123、李四2/123、王五2/123
+ - 高中用户:张三3/123、李四3/123、王五3/123
+
+### 使用流程
+1. 输入用户名和密码登录系统
+2. 选择要生成的题目数量(10-30道)
+3. 系统自动生成相应难度的数学试卷
+4. 试卷自动保存到 `user_papers/{用户名}/` 目录下
+
+## 核心功能详解
+
+### 题目类型
+
+#### 小学题目
+- 基础四则运算:`1 + 2 =`、`5 × 3 =`
+- 混合运算:`2 + 3 × 4 =`、`(1 + 2) × 3 =`
+- 带括号运算:`(4 + 5) × 2 =`、`8 ÷ (2 + 2) =`
+
+#### 初中题目
+- 分数运算:`1/2 + 1/3 =`、`2/3 × 3/4 =`
+- 方程求解:`2x + 5 = 13`、`x² - 4 = 0`
+- 幂运算:`2³ =`、`√16 =`
+
+#### 高中题目
+- 二次方程:`x² + 5x + 6 = 0`
+- 三角函数:`sin(30°) =`、`cos(45°) =`
+- 函数计算:`f(x) = x² + 2x + 1, f(2) =`
+- 概率统计:基础概率计算题
+- 数列计算:等差数列、等比数列
+- 导数计算:基础函数求导
+- 复数运算:`(2 + 3i) + (1 - 2i) =`
+
+### 特点功能
+
+#### 题目去重机制
+系统采用哈希算法确保生成的题目不重复,每份试卷都是独一无二的。
+
+#### 难度自适应
+根据用户级别自动调整题目复杂度,确保题目符合相应年级的教学要求。
+
+#### 文件管理
+- 按用户分类存储试卷
+- 时间戳命名便于查找
+- 支持查看历史生成的试卷
+
+## 扩展开发
+
+### 添加新题目类型
+1. 在相应的生成器类中添加新的题目生成方法
+2. 遵循现有的命名规范和代码风格
+3. 确保题目符合对应年级的难度要求
+
+### 添加新用户
+1. 修改 `UserManager.java` 中的用户列表
+2. 遵循用户名密码的格式规范
+3. 指定用户的教育级别
+
+### 自定义题目数量
+系统支持10-30道题目生成,可通过修改 `ExamManager.java` 中的参数进行调整。
+
+## 项目优势
+
+### 教育价值
+- 减轻教师出题负担
+- 提供个性化练习题目
+- 支持不同学习阶段的需求
+
+### 技术特点
+- **零依赖**:纯Java实现,无需额外库
+- **跨平台**:支持所有Java运行环境
+- **易扩展**:清晰的架构便于功能扩展
+- **高可靠**:完善的错误处理机制
+
+### 用户体验
+- 简洁的命令行界面
+- 直观的操作流程
+- 即时的反馈提示
+
+## 注意事项
+
+1. **编码要求**:确保系统使用UTF-8编码,避免中文乱码
+2. **文件权限**:确保程序有权限在 `user_papers` 目录下创建文件
+ - 文件夹会在程序首次运行时自动创建
+ - 生成的题目文件保存在此文件夹中
+3. **用户安全**:预置密码为演示用途,实际使用请修改
+
+## 更新日志
+
+### 第四版 (当前版本)
+- 优化题目生成算法
+- 修复终端执行jar包显示乱码问题
+
+### 第三版
+- 添加高中题目类型
+- 改进文件管理系统
+
+### 第二版
+- 扩展初中题目类型
+- 优化用户界面
+
+### 第一版
+- 基础功能实现
+- 小学题目生成
+
+
diff --git a/doc/终端运行说明.md b/doc/终端运行说明.md
new file mode 100644
index 0000000..85d9456
--- /dev/null
+++ b/doc/终端运行说明.md
@@ -0,0 +1,107 @@
+# 数学试卷生成器 - 终端运行说明
+
+## 项目简介
+这是一个中小学数学试卷自动生成程序,支持小学、初中、高中三个级别的数学题目生成。
+
+## 编码说明
+程序已智能适配不同操作系统的编码:
+- **Windows系统**:自动使用GBK编码,避免CMD/PowerShell中文乱码
+- **Linux/Mac系统**:自动使用UTF-8编码
+
+## 运行前准备
+
+### 1. 编译项目
+```bash
+# 在项目根目录执行
+javac -encoding UTF-8 -d out/production/PaperGenerator -cp src src/com/bx/generator_main/MathExamGenerator.java src/com/bx/manager/*.java src/com/bx/question/generator/*.java src/com/bx/question/QuestionFactory.java
+```
+
+### 2. 运行程序
+```bash
+# 在项目根目录执行
+java -cp out/production/PaperGenerator com.bx.generator_main.MathExamGenerator
+```
+
+## 各终端运行方法
+
+### Windows CMD
+```cmd
+# 直接运行(程序会自动检测为Windows系统,使用GBK编码)
+java -cp out/production/PaperGenerator com.bx.generator_main.MathExamGenerator
+```
+
+### Windows PowerShell
+```powershell
+# 直接运行(程序会自动检测为Windows系统,使用GBK编码)
+java -cp out/production/PaperGenerator com.bx.generator_main.MathExamGenerator
+```
+
+### Linux/Mac 终端
+```bash
+# 直接运行(程序会自动检测为非Windows系统,使用UTF-8编码)
+java -cp out/production/PaperGenerator com.bx.generator_main.MathExamGenerator
+```
+
+## 使用方法
+
+### 登录流程
+1. 程序启动后会显示:
+ ```
+ 系统默认编码: GBK
+ === 中小学数学卷子自动生成程序 ===
+ 请输入用户名和密码(空格分隔):
+ ```
+
+2. 输入用户名和密码(空格分隔),例如:
+ ```
+ admin 123456
+ ```
+
+3. 登录成功后会显示当前选择的年级级别
+
+### 功能操作
+- **生成题目**:输入题目数量(10-30道)
+- **切换年级**:输入`切换为小学`、`切换为初中`或`切换为高中`
+- **重新登录**:输入`-1`
+
+### 示例操作流程
+```
+系统默认编码: GBK
+=== 中小学数学卷子自动生成程序 ===
+请输入用户名和密码(空格分隔):admin 123456
+当前选择为小学出题
+准备生成 小学 数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录)(若要切换则输入切换为xx):10
+成功生成小学数学试卷到当前文件夹!
+```
+
+## 注意事项
+
+1. **编码兼容性**:程序已自动适配不同操作系统,无需手动设置编码
+2. **中文输入**:确保终端支持中文输入
+3. **文件保存**:生成的试卷文件会保存在程序运行的当前目录
+4. **用户管理**:用户账号信息存储在程序内置的数据结构中
+
+## 常见问题
+
+### Q: 运行后中文显示乱码?
+A: 程序会自动检测操作系统并选择合适的编码,一般不会出现乱码。如果仍有乱码问题,请检查:
+- 终端是否支持中文显示
+- Java版本是否过旧(建议Java 8及以上)
+
+### Q: 无法输入中文?
+A: 确保你的终端输入法正常工作,程序已正确处理中文输入流。
+
+### Q: 登录失败?
+A: 请检查:
+- 用户名和密码是否正确
+- 用户名和密码之间是否有空格分隔
+- 是否有多余的空格或特殊字符
+
+## 技术实现
+
+程序通过以下方式实现编码兼容:
+1. 检测操作系统类型(`System.getProperty("os.name")`)
+2. Windows系统使用GBK编码,其他系统使用UTF-8
+3. 设置控制台输出流和错误流的编码
+4. 使用对应编码创建Scanner对象处理输入
+5. 设置相关系统属性确保Java运行时编码一致
\ No newline at end of file
diff --git a/out/artifacts/PaperGenerator_jar/PaperGenerator.jar b/out/artifacts/PaperGenerator_jar/PaperGenerator.jar
new file mode 100644
index 0000000..4eb72d1
Binary files /dev/null and b/out/artifacts/PaperGenerator_jar/PaperGenerator.jar differ
diff --git a/out/production/PaperGenerator/META-INF/MANIFEST.MF b/out/production/PaperGenerator/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a2b4134
--- /dev/null
+++ b/out/production/PaperGenerator/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.bx.generator_main.MathExamGenerator
+
diff --git a/out/production/PaperGenerator/com/bx/generator_main/MathExamGenerator.class b/out/production/PaperGenerator/com/bx/generator_main/MathExamGenerator.class
new file mode 100644
index 0000000..5927969
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/generator_main/MathExamGenerator.class differ
diff --git a/out/production/PaperGenerator/com/bx/manager/ExamManager.class b/out/production/PaperGenerator/com/bx/manager/ExamManager.class
new file mode 100644
index 0000000..cc40712
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/manager/ExamManager.class differ
diff --git a/out/production/PaperGenerator/com/bx/manager/UserManager.class b/out/production/PaperGenerator/com/bx/manager/UserManager.class
new file mode 100644
index 0000000..5a6d6cb
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/manager/UserManager.class differ
diff --git a/out/production/PaperGenerator/com/bx/question/QuestionFactory.class b/out/production/PaperGenerator/com/bx/question/QuestionFactory.class
new file mode 100644
index 0000000..86e3a1f
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/question/QuestionFactory.class differ
diff --git a/out/production/PaperGenerator/com/bx/question/generator/HighQuestionGenerator.class b/out/production/PaperGenerator/com/bx/question/generator/HighQuestionGenerator.class
new file mode 100644
index 0000000..57165ce
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/question/generator/HighQuestionGenerator.class differ
diff --git a/out/production/PaperGenerator/com/bx/question/generator/MiddleQuestionGenerator.class b/out/production/PaperGenerator/com/bx/question/generator/MiddleQuestionGenerator.class
new file mode 100644
index 0000000..b1ad796
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/question/generator/MiddleQuestionGenerator.class differ
diff --git a/out/production/PaperGenerator/com/bx/question/generator/PrimaryQuestionGenerator.class b/out/production/PaperGenerator/com/bx/question/generator/PrimaryQuestionGenerator.class
new file mode 100644
index 0000000..a2f6208
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/question/generator/PrimaryQuestionGenerator.class differ
diff --git a/out/production/PaperGenerator/com/bx/question/generator/QuestionGenerator.class b/out/production/PaperGenerator/com/bx/question/generator/QuestionGenerator.class
new file mode 100644
index 0000000..9bf220d
Binary files /dev/null and b/out/production/PaperGenerator/com/bx/question/generator/QuestionGenerator.class differ
diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..a2b4134
--- /dev/null
+++ b/src/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: com.bx.generator_main.MathExamGenerator
+
diff --git a/src/com/bx/generator_main/MathExamGenerator.java b/src/com/bx/generator_main/MathExamGenerator.java
new file mode 100644
index 0000000..8308ea4
--- /dev/null
+++ b/src/com/bx/generator_main/MathExamGenerator.java
@@ -0,0 +1,143 @@
+package com.bx.generator_main;
+
+import com.bx.manager.ExamManager;
+import com.bx.manager.UserManager;
+
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Scanner;
+
+
+// 数学试卷生成器主程序
+public class MathExamGenerator {
+ protected static UserManager userManager = new UserManager();
+ protected static Scanner scanner;
+
+ static {
+ try {
+ // 检测系统默认编码
+ String defaultEncoding = System.getProperty("file.encoding");
+ System.out.println("系统默认编码: " + defaultEncoding);
+
+ // 检测操作系统
+ String osName = System.getProperty("os.name").toLowerCase();
+ String encoding = "UTF-8";
+
+ // Windows系统使用GBK编码以避免乱码
+ if (osName.contains("windows")) {
+ encoding = "GBK";
+ System.out.println("检测到Windows系统,使用GBK编码");
+ } else {
+ System.out.println("检测到非Windows系统,使用UTF-8编码");
+ }
+
+ // 设置控制台编码
+ System.setOut(new PrintStream(System.out, true, encoding));
+ System.setErr(new PrintStream(System.err, true, encoding));
+
+ // 设置系统属性
+ System.setProperty("file.encoding", encoding);
+ System.setProperty("sun.stdout.encoding", encoding);
+ System.setProperty("sun.stderr.encoding", encoding);
+
+ // 使用对应编码创建Scanner
+ scanner = new Scanner(System.in, encoding);
+
+ } catch (UnsupportedEncodingException e) {
+ // 如果指定编码不支持,回退到默认编码
+ System.err.println("指定编码不支持,使用默认编码");
+ scanner = new Scanner(System.in);
+ } catch (Exception e) {
+ // 其他异常也回退到默认
+ System.err.println("编码设置失败,使用默认编码: " + e.getMessage());
+ scanner = new Scanner(System.in);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println("=== 中小学数学卷子自动生成程序 ===");
+
+ // 登录验证
+ while (!performLogin()) {
+ // 继续尝试登录
+ }
+
+ // 登录成功后进入主菜单循环
+ runMainMenu();
+ }
+
+ //执行用户登录
+ public static boolean performLogin() {
+ System.out.print("请输入用户名和密码(空格分隔):");
+ String input = scanner.nextLine().trim();
+ String[] parts = input.split("\\s+");
+
+ if (parts.length == 2) {
+ String username = parts[0];
+ String password = parts[1];
+
+ //和存储在map容器中的账号密码比对验证
+ if (userManager.login(username, password)) {
+ System.out.println("当前选择为" + userManager.getCurrentLevel()+"出题");
+ return true;
+ }
+ }
+
+ System.out.println("请输入正确的用户名、密码,重新输入用户名、密码:");
+ return false;
+ }
+
+ //主菜单
+ private static void runMainMenu() {
+ while (true) {
+ System.out.print("准备生成 " + userManager.getCurrentLevel() + " 数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录)(若要切换则输入切换为xx):");
+ String input = scanner.nextLine().trim();
+
+ if ("-1".equals(input)) {
+ userManager.logout();
+ main(new String[0]);
+ return;
+ }
+
+ // 检查切换命令
+ if (handleSwitchCommand(input)) {
+ continue;
+ }
+
+ // 处理题目数量输入
+ handleQuestionCountInput(input);
+ }
+ }
+
+
+ //切换命令
+ private static boolean handleSwitchCommand(String input) {
+ if (input.startsWith("切换为")) {
+ String newLevel = input.substring(3).trim();
+ if ("小学".equals(newLevel) || "初中".equals(newLevel) || "高中".equals(newLevel)) {
+ userManager.setCurrentLevel(newLevel);
+ System.out.println("系统提示:准备生成 " + userManager.getCurrentLevel() + " 数学题目,请输入生成题目数量");
+ return true;
+ } else {
+ System.out.println("请输入小学、初中和高中三个选项中的一个");
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ //处理题目数量输入
+ private static void handleQuestionCountInput(String input) {
+ try {
+ int count = Integer.parseInt(input);
+ if (count >= 10 && count <= 30) {
+ ExamManager.generateExam(count, userManager.getCurrentLevel(), userManager.getCurrentUser());
+ } else {
+ System.out.println("题目数量必须在10-30之间");
+ }
+ } catch (NumberFormatException e) {
+ System.out.println("请输入有效的数字");
+ }
+ }
+}
diff --git a/src/com/bx/manager/ExamManager.java b/src/com/bx/manager/ExamManager.java
new file mode 100644
index 0000000..ad0855f
--- /dev/null
+++ b/src/com/bx/manager/ExamManager.java
@@ -0,0 +1,62 @@
+package com.bx.manager;
+
+import com.bx.question.QuestionFactory;
+import java.io.*;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+ //考试管理类 - 负责生成试卷和文件保存
+public class ExamManager {
+ private static final Set generatedQuestions = new HashSet<>();
+
+ //生成试卷 count为数量、level为难度、username为用户名
+ public static void generateExam(int count, String level, String username) {
+ List questions = new ArrayList<>();
+ Set currentExamQuestions = new HashSet<>();
+
+ for (int i = 1; i <= count; i++) {
+ String question = QuestionFactory.generateQuestion(level);
+
+ // 确保题目不重复
+ while (currentExamQuestions.contains(question) || generatedQuestions.contains(question)) {
+ question = QuestionFactory.generateQuestion(level);
+ }
+
+ currentExamQuestions.add(question);
+ generatedQuestions.add(question);
+ questions.add(i + ". " + question);
+ }
+
+ saveToFile(questions, username);
+ }
+
+ //将题目保存到用户专属文件夹
+ private static void saveToFile(List questions, String username) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ String fileName = sdf.format(new Date()) + ".txt";
+
+ // 构建文件路径
+ String filePath;
+ if (username != null && !username.trim().isEmpty()) {
+ // 使用相对路径,创建用户专属文件夹
+ File userDir = new File("user_papers/" + username);
+ if (!userDir.exists()) {
+ userDir.mkdirs(); // 如果文件夹不存在则创建
+ }
+ filePath = "user_papers/" + username + "/" + fileName;
+ } else {
+ // 如果没有用户名,保存在当前目录
+ filePath = fileName;
+ }
+
+ try (PrintWriter writer = new PrintWriter(new FileWriter(filePath), true)) {
+ for (String question : questions) {
+ writer.println(question);
+ writer.println(); // 空一行
+ }
+ System.out.println("题目已生成并保存到文件:" + filePath);
+ } catch (IOException e) {
+ System.err.println("保存文件时出错:" + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/bx/manager/UserManager.java b/src/com/bx/manager/UserManager.java
new file mode 100644
index 0000000..6f780bc
--- /dev/null
+++ b/src/com/bx/manager/UserManager.java
@@ -0,0 +1,71 @@
+package com.bx.manager;
+
+import java.util.*;
+
+
+ // 用户管理类 - 存储好了用户的账号密码,在登录时调用login和getUserLevel方法验证登录是否成功以及查看等级
+public class UserManager {
+ private static final Map USERS = new HashMap<>();
+ private String currentUser = "";
+ private String currentLevel = "";
+
+ // 初始化用户数据
+ static {
+ USERS.put("张三1", "123");
+ USERS.put("张三2", "123");
+ USERS.put("张三3", "123");
+ USERS.put("李四1", "123");
+ USERS.put("李四2", "123");
+ USERS.put("李四3", "123");
+ USERS.put("王五1", "123");
+ USERS.put("王五2", "123");
+ USERS.put("王五3", "123");
+ }
+
+
+ // 用户登录验证
+ public boolean login(String username, String password) {
+ if (USERS.containsKey(username) && USERS.get(username).equals(password)) {
+ currentUser = username;
+ currentLevel = getUserLevel(username);
+ return true;
+ }
+ return false;
+ }
+
+
+
+ //根据用户名获取对应的教育级别
+ private String getUserLevel(String username) {
+ switch (username) {
+ case "张三1": return "小学";
+ case "张三2": return "小学";
+ case "张三3": return "小学";
+ case "李四1": return "初中";
+ case "李四2": return "初中";
+ case "李四3": return "初中";
+ case "王五1": return "高中";
+ case "王五2": return "高中";
+ case "王五3": return "高中";
+ default: return "小学";
+ }
+ }
+
+ public String getCurrentUser() {
+ return currentUser;
+ }
+
+ public String getCurrentLevel() {
+ return currentLevel;
+ }
+
+ public void setCurrentLevel(String level) {
+ this.currentLevel = level;
+ }
+
+ //登出
+ public void logout()
+ { currentUser = "";
+ currentLevel = "";
+ }
+}
\ No newline at end of file
diff --git a/src/com/bx/question/QuestionFactory.java b/src/com/bx/question/QuestionFactory.java
new file mode 100644
index 0000000..88f912a
--- /dev/null
+++ b/src/com/bx/question/QuestionFactory.java
@@ -0,0 +1,34 @@
+package com.bx.question;
+
+import com.bx.question.generator.HighQuestionGenerator;
+import com.bx.question.generator.MiddleQuestionGenerator;
+import com.bx.question.generator.PrimaryQuestionGenerator;
+import com.bx.question.generator.QuestionGenerator;
+
+
+//题目工厂类 - 根据难度级别生成对应的题目
+
+public class QuestionFactory {
+
+
+ //根据难度级别获取对应的题目生成器
+ private static QuestionGenerator getGenerator(String level) {
+ switch (level) {
+ case "小学":
+ return new PrimaryQuestionGenerator();
+ case "初中":
+ return new MiddleQuestionGenerator();
+ case "高中":
+ return new HighQuestionGenerator();
+ default:
+ return new PrimaryQuestionGenerator();
+ }
+ }
+
+
+ //根据难度级别生成题目
+ public static String generateQuestion(String level) {
+ QuestionGenerator generator = getGenerator(level);
+ return generator.generateQuestion();
+ }
+}
diff --git a/src/com/bx/question/generator/HighQuestionGenerator.java b/src/com/bx/question/generator/HighQuestionGenerator.java
new file mode 100644
index 0000000..8da10b0
--- /dev/null
+++ b/src/com/bx/question/generator/HighQuestionGenerator.java
@@ -0,0 +1,73 @@
+package com.bx.question.generator;
+import java.util.Random;
+
+
+ // 高中题目生成器 - 生成高等数学题目
+public class HighQuestionGenerator implements QuestionGenerator{
+ private static final Random random = new Random();
+
+ @Override
+ public String generateQuestion() {
+ int type = random.nextInt(12);
+ return switch (type) {
+ case 0 -> generateQuadraticEquation();
+ case 1 -> generateFunctionQuestion();
+ case 2 -> generateTrigonometryQuestion();
+ case 3 -> generateProbabilityQuestion();
+ case 4 -> generateSequenceQuestion();
+ case 5 -> generateDerivativeQuestion();
+ case 6 -> generateComplexNumberQuestion();
+ default -> generateTrigonometryQuestion();
+ };
+ }
+
+
+ //解一元二次方程
+ private static String generateQuadraticEquation() {
+ int a = random.nextInt(5) + 1, b = random.nextInt(10) - 5, c = random.nextInt(10) - 5;
+ String bStr = b >= 0 ? "+" + b : String.valueOf(b);
+ String cStr = c >= 0 ? "+" + c : String.valueOf(c);
+ return "解方程:" + a + "x² " + bStr + "x " + cStr + " = 0";
+ }
+
+ //函数计算
+ private static String generateFunctionQuestion() {
+ int a = random.nextInt(9) + 1, b = random.nextInt(10) - 5, x = random.nextInt(10) + 1;
+ String bStr = b >= 0 ? "+" + b : String.valueOf(b);
+ return "已知f(x) = " + a + "x " + bStr + ",求f(" + x + ")";
+ }
+
+ //三角函数
+ private static String generateTrigonometryQuestion() {
+ String[] functions = {"sin", "cos", "tan"};
+ String func = functions[random.nextInt(functions.length)];
+ int angle = random.nextInt(4) * 30; // 0, 30, 60, 90度
+ return "计算:" + func + "(" + angle + "°)";
+ }
+
+ //概率问题
+ private static String generateProbabilityQuestion() {
+ int total = random.nextInt(20) + 10, favorable = random.nextInt(total / 2) + 1;
+ return "从" + total + "个球中任取1个,其中有" + favorable + "个红球,求取到红球的概率";
+ }
+
+ //数列
+ private static String generateSequenceQuestion() {
+ int first = random.nextInt(10) + 1, diff = random.nextInt(5) + 1, n = random.nextInt(10) + 5;
+ return "等差数列首项a₁=" + first + ",公差d=" + diff + ",求第" + n + "项";
+ }
+
+ //导数
+ private static String generateDerivativeQuestion() {
+ int a = random.nextInt(9) + 1, n = random.nextInt(4) + 2;
+ return "求函数f(x) = " + a + "x^" + n + "的导数";
+ }
+
+ //复数运算
+ private static String generateComplexNumberQuestion() {
+ int a = random.nextInt(9) + 1, b = random.nextInt(9) + 1;
+ int c = random.nextInt(9) + 1, d = random.nextInt(9) + 1;
+ return "计算:(" + a + "+" + b + "i) + (" + c + "+" + d + "i)";
+ }
+}
+
diff --git a/src/com/bx/question/generator/MiddleQuestionGenerator.java b/src/com/bx/question/generator/MiddleQuestionGenerator.java
new file mode 100644
index 0000000..d3f1481
--- /dev/null
+++ b/src/com/bx/question/generator/MiddleQuestionGenerator.java
@@ -0,0 +1,114 @@
+package com.bx.question.generator;
+import java.util.Random;
+
+//初中题目生成器(混合运算、分数运算、方程、开方、开根号)
+
+public class MiddleQuestionGenerator implements QuestionGenerator {
+ private static final Random random = new Random();
+
+ @Override
+ public String generateQuestion() {
+ int type = random.nextInt(7);
+ int operandCount = random.nextInt(4) + 2; // 2-5个操作数
+
+ return switch (type) {
+ case 0 -> generateMixedArithmetic(operandCount);
+ case 1 -> generateFractionQuestion();
+ case 2 -> generateEquationQuestion();
+ case 3 -> generatePowerAndRootQuestion();
+ default -> generatePowerAndRootQuestion();
+ };
+ }
+
+ //生成混合运算题目
+ private static String generateMixedArithmetic(int count) {
+ StringBuilder question = new StringBuilder();
+ String[] operators = {"+", "-", "×", "÷"};
+ int num = random.nextInt(100) + 1;
+ question.append(num);
+
+ for (int i = 1; i < count; i++) {
+ String op = operators[random.nextInt(operators.length)];
+ int nextNum = random.nextInt(20) + 1; //第二个数1-20
+ question.append(" ").append(op).append(" ").append(nextNum);
+ }
+ question.append(" = ?");
+ return question.toString();
+ }
+
+ //生成分数运算题目
+ private static String generateFractionQuestion() {
+ int num1 = random.nextInt(9) + 1, den1 = random.nextInt(9) + 2;
+ int num2 = random.nextInt(9) + 1, den2 = random.nextInt(9) + 2;
+ String[] ops = {"+", "-", "×", "÷"};
+ String op = ops[random.nextInt(ops.length)];
+ return num1 + "/" + den1 + " " + op + " " + num2 + "/" + den2 + " = ?";
+ }
+
+ //方程
+ private static String generateEquationQuestion() {
+ int type = random.nextInt(4);
+
+ switch (type) {
+ case 0: {
+ // 一元一次方程:ax + b = c
+ int a = random.nextInt(9) + 1;
+ int b = random.nextInt(20) + 1;
+ int c = random.nextInt(30) + 1;
+ return "解方程:" + a + "x + " + b + " = " + c;
+ }
+ case 1: {
+ // 含分母的方程:(x + a)/b = c
+ int a = random.nextInt(10) + 1;
+ int b = random.nextInt(5) + 2;
+ int c = random.nextInt(8) + 1;
+ return "解方程:(x + " + a + ")/" + b + " = " + c;
+ }
+ case 2: {
+ // 两边都含x:ax + b = cx + d
+ int a = random.nextInt(9) + 2;
+ int b = random.nextInt(20) + 1;
+ int c = random.nextInt(5) + 1;
+ int d = random.nextInt(15) + 1;
+ return "解方程:" + a + "x + " + b + " = " + c + "x + " + d;
+ }
+ default: {
+ // 含括号的方程:a(x + b) = c
+ int a = random.nextInt(5) + 2;
+ int b = random.nextInt(10) + 1;
+ int c = random.nextInt(30) + 10;
+ return "解方程:" + a + "(x + " + b + ") = " + c;
+ }
+ }
+ }
+
+ //平方、开方、立方、幂运算
+ private static String generatePowerAndRootQuestion() {
+ int type = random.nextInt(4);
+
+ switch (type) {
+ case 0: {
+ // 平方运算:a²
+ int base = random.nextInt(15) + 1;
+ return "计算:" + base + "² = ?";
+ }
+ case 1: {
+ // 开平方运算:√a
+ int[] perfectSquares = {4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225};
+ int square = perfectSquares[random.nextInt(perfectSquares.length)];
+ return "计算:√" + square + " = ?";
+ }
+ case 2: {
+ // 立方运算:a³
+ int base = random.nextInt(8) + 1;
+ return "计算:" + base + "³ = ?";
+ }
+ default: {
+ // 幂运算:a^n
+ int base = random.nextInt(10) + 2;
+ int exponent = random.nextInt(3) + 2; // 指数2-4
+ return "计算:" + base + "^" + exponent + " = ?";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/bx/question/generator/PrimaryQuestionGenerator.java b/src/com/bx/question/generator/PrimaryQuestionGenerator.java
new file mode 100644
index 0000000..2cd3aee
--- /dev/null
+++ b/src/com/bx/question/generator/PrimaryQuestionGenerator.java
@@ -0,0 +1,161 @@
+package com.bx.question.generator;
+
+import java.util.Random;
+
+//小学题目生成器
+public class PrimaryQuestionGenerator implements QuestionGenerator {
+ private static final Random random = new Random();
+
+ // 操作数范围
+ private static final int MIN_NUMBER = 1;
+ private static final int MAX_NUMBER = 100;
+
+ // 运算符数组
+ private static final String[] OPERATORS = {"+", "-", "x", "÷"};
+
+ @Override
+ public String generateQuestion() {
+ // 50%概率生成单一运算符,50%概率生成复合运算符
+ if (random.nextBoolean()) {
+ return generateSingleOperatorQuestion();
+ } else {
+ return generateMixedOperatorQuestion();
+ }
+ }
+
+ //生成符合范围的操作数
+ private int generateRandomNumber() {
+ return random.nextInt(MAX_NUMBER) + MIN_NUMBER;
+ }
+
+ //单一运算符
+ private String generateSingleOperatorQuestion() {
+ String operator = OPERATORS[random.nextInt(4)]; // 随机选择一个运算符
+ int operandCount = random.nextInt(4) + 2; // 2-5个操作数
+
+ StringBuilder question = new StringBuilder();
+
+ // 生成第一个数
+ question.append(generateRandomNumber());
+
+ // 生成后续的数和运算符
+ for (int i = 1; i < operandCount; i++) {
+ question.append(" ").append(operator).append(" ").append(generateRandomNumber());
+ }
+
+ return question.append(" = ?").toString();
+ }
+
+ //复合运算符
+ private String generateMixedOperatorQuestion() {
+ int choice = random.nextInt(3);
+ if (choice == 0) {
+ return generateMixedWithoutBrackets();
+ } else if (choice == 1) {
+ return generateMixedWithBrackets3();
+ } else
+ return generateMixedWithBrackets4();
+ }
+
+ //生成无括号的混合运算
+ private String generateMixedWithoutBrackets() {
+ StringBuilder question = new StringBuilder();
+ int count = random.nextInt(4) + 2;
+ String[] operators = {"+", "-", "×", "÷"};
+ int num = random.nextInt(100) + 1;
+ question.append(num);
+
+ for (int i = 1; i < count; i++) {
+ String op = operators[random.nextInt(operators.length)];
+ int nextNum = random.nextInt(20) + 1; //下一个数1-20
+ question.append(" ").append(op).append(" ").append(nextNum);
+ }
+ question.append(" = ?");
+ return question.toString();
+
+ }
+
+ //生成带括号的混合运算(三个操作数)
+ private String generateMixedWithBrackets3() {
+ StringBuilder question = new StringBuilder();
+
+ // 括号内的运算
+ int innerNum1 = generateRandomNumber();
+ int innerNum2 = generateRandomNumber();
+ String innerOp = OPERATORS[random.nextInt(4)];
+
+ // 括号外的数字和运算符
+ int outerNum = generateRandomNumber();
+ String outerOp = OPERATORS[random.nextInt(4)];
+
+ // 随机决定括号在前还是在后
+ if (random.nextBoolean()) {
+ // 括号在前:(a op b) op c
+ question.append("(").append(innerNum1).append(" ").append(innerOp)
+ .append(" ").append(innerNum2).append(") ").append(outerOp)
+ .append(" ").append(outerNum);
+ } else {
+ // 括号在后:a op (b op c)
+ question.append(outerNum).append(" ").append(outerOp).append(" (")
+ .append(innerNum1).append(" ").append(innerOp).append(" ")
+ .append(innerNum2).append(")");
+ }
+
+ return question.append(" = ?").toString();
+ }
+
+ //生成带括号的混合运算(四个操作数)
+ private String generateMixedWithBrackets4() {
+ StringBuilder question = new StringBuilder();
+
+ int choice = random.nextInt(3);
+
+ if (choice == 0) {
+ // 格式1: (a op b) op (c op d)
+ int num1 = generateRandomNumber();
+ int num2 = generateRandomNumber();
+ int num3 = generateRandomNumber();
+ int num4 = generateRandomNumber();
+
+ String op1 = OPERATORS[random.nextInt(4)];
+ String op2 = OPERATORS[random.nextInt(4)];
+ String op3 = OPERATORS[random.nextInt(4)];
+
+ question.append("(").append(num1).append(" ").append(op1).append(" ")
+ .append(num2).append(") ").append(op2).append(" (")
+ .append(num3).append(" ").append(op3).append(" ").append(num4).append(")");
+
+ } else if (choice == 1) {
+ // 格式2: (a op b op c) op d
+ int num1 = generateRandomNumber();
+ int num2 = generateRandomNumber();
+ int num3 = generateRandomNumber();
+ int num4 = generateRandomNumber();
+
+ String op1 = OPERATORS[random.nextInt(4)];
+ String op2 = OPERATORS[random.nextInt(4)];
+ String op3 = OPERATORS[random.nextInt(4)];
+
+ question.append("(").append(num1).append(" ").append(op1).append(" ")
+ .append(num2).append(" ").append(op2).append(" ").append(num3)
+ .append(") ").append(op3).append(" ").append(num4);
+
+ } else {
+ // 格式3: a op (b op c op d)
+ int num1 = generateRandomNumber();
+ int num2 = generateRandomNumber();
+ int num3 = generateRandomNumber();
+ int num4 = generateRandomNumber();
+
+ String op1 = OPERATORS[random.nextInt(4)];
+ String op2 = OPERATORS[random.nextInt(4)];
+ String op3 = OPERATORS[random.nextInt(4)];
+
+ question.append(num1).append(" ").append(op1).append(" (")
+ .append(num2).append(" ").append(op2).append(" ").append(num3)
+ .append(" ").append(op3).append(" ").append(num4).append(")");
+ }
+
+ return question.append(" = ?").toString();
+ }
+}
\ No newline at end of file
diff --git a/src/com/bx/question/generator/QuestionGenerator.java b/src/com/bx/question/generator/QuestionGenerator.java
new file mode 100644
index 0000000..e985611
--- /dev/null
+++ b/src/com/bx/question/generator/QuestionGenerator.java
@@ -0,0 +1,5 @@
+package com.bx.question.generator;
+
+public interface QuestionGenerator {
+ String generateQuestion();
+}