Second #2

Merged
hnu202326010307 merged 6 commits from develop into main 4 months ago

@ -1,2 +1,189 @@
# math-test
# 中小学数学卷子自动生成程序
## 项目简介
这是一个基于Java开发的智能数学试卷自动生成系统专为中小学数学教师设计。系统能够根据不同学段小学、初中、高中自动生成符合教学大纲要求的数学题目支持用户管理、题目查重、类型切换等功能。
## 功能特点
### 🔐 用户认证系统
- **多用户支持**:预设小学、初中、高中各三个测试账户
- **安全验证**:用户名密码双重验证机制
- **权限管理**:不同学段用户只能生成对应难度的题目
### 📝 智能题目生成
- **小学题目**:加减乘除四则运算,支持括号优先级
- **初中题目**:包含平方、开根号等进阶运算
- **高中题目**:支持三角函数等高等数学运算
- **难度控制**操作数范围1-100操作符数量1-5个
- **随机性保证**基于Java Random类的真随机数生成
### 🔍 智能查重系统
- **历史查重**:自动检查用户历史生成的题目
- **实时去重**:避免在同一份试卷中出现重复题目
- **文件级查重**:基于用户文件夹下的所有历史文件
### 🔄 灵活类型切换
- **动态切换**:登录状态下可随时切换出题类型
- **命令格式**:输入"切换为 XX"XX为小学、初中、高中
- **即时生效**:切换后立即应用新的题目生成规则
### 💾 智能文件管理
- **用户隔离**:按用户名创建独立的文件夹
- **时间戳命名**:文件名格式:年-月-日-时-分-秒.txt
- **规范格式**:题目有序号,每题之间空一行,便于阅读
## 预设账户
| 学段 | 用户名 | 密码 | 权限说明 |
|------|--------|------|----------|
| 小学 | 张三1 | 123 | 生成小学难度题目 |
| 小学 | 张三2 | 123 | 生成小学难度题目 |
| 小学 | 张三3 | 123 | 生成小学难度题目 |
| 初中 | 李四1 | 123 | 生成初中难度题目 |
| 初中 | 李四2 | 123 | 生成初中难度题目 |
| 初中 | 李四3 | 123 | 生成初中难度题目 |
| 高中 | 王五1 | 123 | 生成高中难度题目 |
| 高中 | 王五2 | 123 | 生成高中难度题目 |
| 高中 | 王五3 | 123 | 生成高中难度题目 |
## 技术架构
### 项目结构
```
src/
├── App.java # 主程序入口,控制程序流程
├── User.java # 用户实体类,管理用户信息和认证
├── QuestionGenerator.java # 题目生成器抽象类,定义公共接口
├── PrimarySchoolGenerator.java # 小学题目生成器实现
├── MiddleSchoolGenerator.java # 初中题目生成器实现
├── HighSchoolGenerator.java # 高中题目生成器实现
└── FileManager.java # 文件操作工具类
```
### 核心类说明
- **App类**:程序主控制器,负责用户交互和流程调度
- **User类**:用户数据模型,包含用户名、密码和权限信息
- **QuestionGenerator**:抽象工厂模式,定义题目生成规范
- **各学段生成器**:策略模式实现,不同难度采用不同生成策略
- **FileManager**:单例模式,统一管理文件读写操作
## 快速开始
### 环境要求
- Java 8 或更高版本
- 至少100MB可用磁盘空间
- 支持命令行操作的操作系统
### 编译项目
```bash
# 进入项目目录
cd 1
# 编译所有Java源文件
javac -d bin src/*.java
# 或者使用批处理方式Windows
javac -d bin src\*.java
```
### 运行程序
```bash
# 运行主程序
java -cp bin App
# 或者指定类路径
java -classpath bin App
```
## 使用指南
### 基本操作流程
1. **启动程序**:运行`java -cp bin App`命令
2. **用户登录**:输入用户名和密码(用空格分隔)
```
请输入用户名和密码用空格隔开张三1 123
```
3. **查看权限**:登录成功后显示当前出题类型
```
登录成功!当前出题类型:小学
```
4. **生成题目**输入要生成的题目数量10-30
```
请输入题目数量10-3015
```
5. **切换类型**:或输入"切换为 XX"来改变出题类型
```
请输入题目数量或切换类型:切换为初中
```
6. **退出登录**:输入"-1"退出当前用户
### 文件输出示例
生成的试卷文件示例:
```
1. (3 + 5) × 2 - 4 ÷ 2 =
2. 7 × (9 - 3) + 6 ÷ 2 =
3. 12 + 8 ÷ 4 × 3 - 5 =
...
```
## 开发规范
### 代码质量
- **面向对象设计**:采用清晰的类结构和职责分离
- **方法简洁性**单个方法代码行数控制在40行以内
- **命名规范**遵循Java驼峰命名法见名知意
- **注释完整**:关键方法和复杂逻辑有详细注释
### 错误处理
- **输入验证**:对用户输入进行严格的格式和范围检查
- **异常捕获**使用try-catch处理可能的运行时异常
- **友好提示**:提供清晰易懂的错误信息
## 扩展建议
### 功能扩展
1. **题目难度分级**:在每个学段内设置不同难度级别
2. **题目类型扩展**:增加几何、代数等更多题目类型
3. **批量生成**:支持一次性生成多套试卷
4. **模板定制**:允许教师自定义试卷模板格式
### 技术优化
1. **数据库支持**:使用数据库存储用户和题目数据
2. **Web界面**开发Web版界面提升用户体验
3. **算法优化**:改进题目生成算法,提高题目质量
4. **国际化**:支持多语言界面
## 注意事项
### 系统要求
- 确保Java环境正确安装并配置PATH
- 程序运行目录需要有写权限
- 建议在SSD硬盘上运行以获得更好的文件读写性能
### 数据安全
- 用户密码以明文存储,生产环境建议加密
- 定期备份papers文件夹中的重要数据
- 避免在公共计算机上保存敏感的用户数据
### 性能考虑
- 题目数量较多时,生成时间会相应增加
- 历史文件较多时,查重操作可能影响性能
- 建议定期清理不再需要的历史试卷文件
## 技术支持
如遇到问题,请检查:
1. Java环境是否安装正确
2. 文件路径权限是否足够
3. 输入格式是否符合要求
4. 磁盘空间是否充足
---
*最后更新2025年9月27日*

@ -5,248 +5,251 @@ import java.util.Scanner;
import java.util.Set;
public class App {
private static final Scanner scanner = new Scanner(System.in);
private static final Map<String, User> users = User.getPresetUsers();
private static final FileManager fileManager = new FileManager();
private static QuestionGenerator currentGenerator;
private static String currentUsername;
public static void main(String[] args) {
System.out.println("=== 中小学数学卷子自动生成程序 ===");
while (true) {
// 登录
User loggedInUser = login();
currentUsername = loggedInUser.getUsername();
String userType = loggedInUser.getUserType();
// 根据用户类型初始化题目生成器
switch (userType) {
case "小学":
currentGenerator = new PrimarySchoolGenerator();
break;
case "初中":
currentGenerator = new MiddleSchoolGenerator();
break;
case "高中":
currentGenerator = new HighSchoolGenerator();
break;
}
System.out.println("当前选择为 " + userType + " 出题");
// 加载已存在的题目用于查重
Set<String> existingQuestions = fileManager.loadExistingQuestions(currentUsername);
for (String question : existingQuestions) {
currentGenerator.addToGenerated(question);
}
// 主循环
boolean stayLoggedIn = true;
while (stayLoggedIn) {
System.out.println("\n准备生成 " + currentGenerator.getCurrentType() + " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
String input = scanner.nextLine().trim();
if (input.equals("-1")) {
stayLoggedIn = false;
System.out.println("退出当前用户...");
break;
}
// 处理切换类型命令
if (input.startsWith("切换为")) {
handleTypeSwitch(input);
continue;
}
// 生成题目
try {
int count = Integer.parseInt(input);
if (count >= 10 && count <= 30) {
generateAndSaveQuestions(count);
} else {
System.out.println("题目数量必须在10-30之间请重新输入。");
}
} catch (NumberFormatException e) {
System.out.println("请输入有效的数字10-30或'切换为XX'命令。");
}
}
}
}
private static User login() {
while (true) {
System.out.println("\n请输入用户名和密码用空格隔开");
System.out.println("如果需要注册新用户,请输入'register'");
System.out.println("如果需要退出程序,请输入'-1'");
String input = scanner.nextLine();
String[] credentials = input.split("\\s+");
if (credentials[0].equals("-1")) {
System.out.println("退出程序...");
System.exit(0);
}
// 处理注册请求
if (credentials[0].equalsIgnoreCase("register")) {
handleRegistration();
continue;
}
if (credentials.length != 2) {
System.out.println("请输入正确的用户名、密码格式(用户名 密码)");
continue;
}
String username = credentials[0];
String password = credentials[1];
User user = User.authenticate(username, password);
if (user != null) {
return user;
} else {
System.out.println("请输入正确的用户名、密码");
}
}
}
/**
*
*/
private static void handleRegistration() {
System.out.println("\n=== 用户注册 ===");
// 输入用户名
String username;
while (true) {
System.out.print("请输入用户名: ");
username = scanner.nextLine().trim();
if (username.isEmpty()) {
System.out.println("用户名不能为空,请重新输入。");
continue;
}
if (User.userExists(username)) {
System.out.println("用户名已存在,请选择其他用户名。");
continue;
}
break;
}
// 输入密码
String password;
while (true) {
System.out.print("请输入密码: ");
password = scanner.nextLine().trim();
if (password.isEmpty()) {
System.out.println("密码不能为空,请重新输入。");
continue;
}
break;
private static final Scanner scanner = new Scanner(System.in);
private static final Map<String, User> users = User.getPresetUsers();
private static final FileManager fileManager = new FileManager();
private static QuestionGenerator currentGenerator;
private static String currentUsername;
public static void main(String[] args) {
System.out.println("=== 中小学数学卷子自动生成程序 ===");
while (true) {
// 登录
User loggedInUser = login();
currentUsername = loggedInUser.getUsername();
String userType = loggedInUser.getUserType();
// 根据用户类型初始化题目生成器
switch (userType) {
case "小学":
currentGenerator = new PrimarySchoolGenerator();
break;
case "初中":
currentGenerator = new MiddleSchoolGenerator();
break;
case "高中":
currentGenerator = new HighSchoolGenerator();
break;
}
System.out.println("当前选择为 " + userType + " 出题");
// 加载已存在的题目用于查重
Set<String> existingQuestions = fileManager.loadExistingQuestions(currentUsername);
for (String question : existingQuestions) {
currentGenerator.addToGenerated(question);
}
// 主循环
boolean stayLoggedIn = true;
while (stayLoggedIn) {
System.out.println("\n准备生成 " + currentGenerator.getCurrentType()
+ " 数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
String input = scanner.nextLine().trim();
if (input.equals("-1")) {
stayLoggedIn = false;
System.out.println("退出当前用户...");
break;
}
// 选择用户类型
String userType;
while (true) {
System.out.println("请选择用户类型:");
System.out.println("1. 小学");
System.out.println("2. 初中");
System.out.println("3. 高中");
System.out.print("请输入选项(1-3): ");
String choice = scanner.nextLine().trim();
switch (choice) {
case "1":
userType = "小学";
break;
case "2":
userType = "初中";
break;
case "3":
userType = "高中";
break;
default:
System.out.println("无效选项,请重新选择。");
continue;
}
break;
// 处理切换类型命令
if (input.startsWith("切换为")) {
handleTypeSwitch(input);
continue;
}
// 添加用户
if (User.addUser(username, password, userType)) {
System.out.println("用户注册成功!");
System.out.println("用户名: " + username);
System.out.println("用户类型: " + userType);
System.out.println("请使用新用户登录。");
} else {
System.out.println("用户注册失败,请重试。");
// 生成题目
try {
int count = Integer.parseInt(input);
if (count >= 10 && count <= 30) {
generateAndSaveQuestions(count);
} else {
System.out.println("题目数量必须在10-30之间请重新输入。");
}
} catch (NumberFormatException e) {
System.out.println("请输入有效的数字10-30或'切换为XX'命令。");
}
}
}
private static void handleTypeSwitch(String input) {
// 提取目标类型,支持"切换为小学"和"切换为 小学"两种格式
String targetType;
if (input.contains(" ")) {
// 格式:"切换为 小学"(有空格)
String[] parts = input.split("\\s+");
if (parts.length != 2) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return;
}
targetType = parts[1];
} else {
// 格式:"切换为小学"(无空格)
targetType = input.substring(3); // 去掉"切换为"三个字
}
if (!targetType.equals("小学") && !targetType.equals("初中") && !targetType.equals("高中")) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return;
}
// 切换题目生成器
switch (targetType) {
case "小学":
currentGenerator = new PrimarySchoolGenerator();
break;
case "初中":
currentGenerator = new MiddleSchoolGenerator();
break;
case "高中":
currentGenerator = new HighSchoolGenerator();
break;
}
// 重新加载已存在的题目用于查重
Set<String> existingQuestions = fileManager.loadExistingQuestions(currentUsername);
for (String question : existingQuestions) {
currentGenerator.addToGenerated(question);
}
System.out.println("已切换为 " + targetType + " 出题模式");
}
private static User login() {
while (true) {
System.out.println("\n请输入用户名和密码用空格隔开");
System.out.println("如果需要注册新用户,请输入'register'");
System.out.println("如果需要退出程序,请输入'-1'");
String input = scanner.nextLine();
String[] credentials = input.split("\\s+");
if (credentials[0].equals("-1")) {
System.out.println("退出程序...");
System.exit(0);
}
// 处理注册请求
if (credentials[0].equalsIgnoreCase("register")) {
handleRegistration();
continue;
}
if (credentials.length != 2) {
System.out.println("请输入正确的用户名、密码格式(用户名 密码)");
continue;
}
String username = credentials[0];
String password = credentials[1];
User user = User.authenticate(username, password);
if (user != null) {
return user;
} else {
System.out.println("请输入正确的用户名、密码");
}
}
private static void generateAndSaveQuestions(int count) {
String[] questions = new String[count];
System.out.println("正在生成 " + count + " 道 " + currentGenerator.getCurrentType() + " 题目...");
for (int i = 0; i < count; i++) {
questions[i] = currentGenerator.generateQuestion();
System.out.println((i + 1) + ". " + questions[i]);
}
try {
fileManager.saveQuestions(currentUsername, questions);
System.out.println("题目生成完成!");
} catch (Exception e) {
System.out.println("保存文件时出错: " + e.getMessage());
}
}
/**
*
*/
private static void handleRegistration() {
System.out.println("\n=== 用户注册 ===");
// 输入用户名
String username;
while (true) {
System.out.print("请输入用户名: ");
username = scanner.nextLine().trim();
if (username.isEmpty()) {
System.out.println("用户名不能为空,请重新输入。");
continue;
}
if (User.userExists(username)) {
System.out.println("用户名已存在,请选择其他用户名。");
continue;
}
break;
}
// 输入密码
String password;
while (true) {
System.out.print("请输入密码: ");
password = scanner.nextLine().trim();
if (password.isEmpty()) {
System.out.println("密码不能为空,请重新输入。");
continue;
}
break;
}
// 选择用户类型
String userType;
while (true) {
System.out.println("请选择用户类型:");
System.out.println("1. 小学");
System.out.println("2. 初中");
System.out.println("3. 高中");
System.out.print("请输入选项(1-3): ");
String choice = scanner.nextLine().trim();
switch (choice) {
case "1":
userType = "小学";
break;
case "2":
userType = "初中";
break;
case "3":
userType = "高中";
break;
default:
System.out.println("无效选项,请重新选择。");
continue;
}
break;
}
// 添加用户
if (User.addUser(username, password, userType)) {
System.out.println("用户注册成功!");
System.out.println("用户名: " + username);
System.out.println("用户类型: " + userType);
System.out.println("请使用新用户登录。");
} else {
System.out.println("用户注册失败,请重试。");
}
}
private static void handleTypeSwitch(String input) {
// 提取目标类型,支持"切换为小学"和"切换为 小学"两种格式
String targetType;
if (input.contains(" ")) {
// 格式:"切换为 小学"(有空格)
String[] parts = input.split("\\s+");
if (parts.length != 2) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return;
}
targetType = parts[1];
} else {
// 格式:"切换为小学"(无空格)
targetType = input.substring(3); // 去掉"切换为"三个字
}
if (!targetType.equals("小学") && !targetType.equals("初中") && !targetType.equals("高中")) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return;
}
// 切换题目生成器
switch (targetType) {
case "小学":
currentGenerator = new PrimarySchoolGenerator();
break;
case "初中":
currentGenerator = new MiddleSchoolGenerator();
break;
case "高中":
currentGenerator = new HighSchoolGenerator();
break;
}
// 重新加载已存在的题目用于查重
Set<String> existingQuestions = fileManager.loadExistingQuestions(currentUsername);
for (String question : existingQuestions) {
currentGenerator.addToGenerated(question);
}
System.out.println("已切换为 " + targetType + " 出题模式");
}
private static void generateAndSaveQuestions(int count) {
String[] questions = new String[count];
System.out.println(
"正在生成 " + count + " 道 " + currentGenerator.getCurrentType() + " 题目...");
for (int i = 0; i < count; i++) {
questions[i] = currentGenerator.generateQuestion();
System.out.println((i + 1) + ". " + questions[i]);
}
try {
fileManager.saveQuestions(currentUsername, questions);
System.out.println("题目生成完成!");
} catch (Exception e) {
System.out.println("保存文件时出错: " + e.getMessage());
}
}
}

@ -1,98 +1,104 @@
package src;
import java.io.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
public class FileManager {
private String baseDir;
public FileManager() {
this.baseDir = System.getProperty("user.dir") + File.separator + "papers";
createBaseDirectory();
private String baseDir;
public FileManager() {
this.baseDir = System.getProperty("user.dir") + File.separator + "papers";
createBaseDirectory();
}
// 创建基础目录
private void createBaseDirectory() {
File dir = new File(baseDir);
if (!dir.exists()) {
dir.mkdirs();
}
// 创建基础目录
private void createBaseDirectory() {
File dir = new File(baseDir);
if (!dir.exists()) {
dir.mkdirs();
}
}
// 为用户创建目录
private String createUserDirectory(String username) {
String userDir = baseDir + File.separator + username;
File dir = new File(userDir);
if (!dir.exists()) {
dir.mkdirs();
}
// 为用户创建目录
private String createUserDirectory(String username) {
String userDir = baseDir + File.separator + username;
File dir = new File(userDir);
if (!dir.exists()) {
dir.mkdirs();
return userDir;
}
// 生成文件名
private String generateFileName() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
return sdf.format(new Date()) + ".txt";
}
// 保存题目到文件
public void saveQuestions(String username, String[] questions) throws IOException {
String userDir = createUserDirectory(username);
String fileName = generateFileName();
String filePath = userDir + File.separator + fileName;
try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) {
for (int i = 0; i < questions.length; i++) {
writer.println((i + 1) + ". " + questions[i]);
if (i < questions.length - 1) {
writer.println(); // 题目之间空一行
}
return userDir;
}
}
// 生成文件名
private String generateFileName() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
return sdf.format(new Date()) + ".txt";
}
// 保存题目到文件
public void saveQuestions(String username, String[] questions) throws IOException {
String userDir = createUserDirectory(username);
String fileName = generateFileName();
String filePath = userDir + File.separator + fileName;
try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) {
for (int i = 0; i < questions.length; i++) {
writer.println((i + 1) + ". " + questions[i]);
if (i < questions.length - 1) {
writer.println(); // 题目之间空一行
System.out.println("题目已保存到: " + filePath);
}
// 检查题目是否重复(读取用户目录下所有文件)
public Set<String> loadExistingQuestions(String username) {
Set<String> existingQuestions = new HashSet<>();
String userDir = baseDir + File.separator + username;
File dir = new File(userDir);
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles((d, name) -> name.endsWith(".txt"));
if (files != null) {
for (File file : files) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
StringBuilder questionBuilder = new StringBuilder();
while ((line = reader.readLine()) != null) {
if (line.trim().isEmpty()) {
if (questionBuilder.length() > 0) {
// 移除题号
String question = questionBuilder.toString().replaceAll("^\\d+\\.\\s*", "");
existingQuestions.add(question.trim());
questionBuilder.setLength(0);
}
} else {
questionBuilder.append(line).append(" ");
}
}
}
System.out.println("题目已保存到: " + filePath);
}
// 检查题目是否重复(读取用户目录下所有文件)
public Set<String> loadExistingQuestions(String username) {
Set<String> existingQuestions = new HashSet<>();
String userDir = baseDir + File.separator + username;
File dir = new File(userDir);
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles((d, name) -> name.endsWith(".txt"));
if (files != null) {
for (File file : files) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
StringBuilder questionBuilder = new StringBuilder();
while ((line = reader.readLine()) != null) {
if (line.trim().isEmpty()) {
if (questionBuilder.length() > 0) {
// 移除题号
String question = questionBuilder.toString().replaceAll("^\\d+\\.\\s*", "");
existingQuestions.add(question.trim());
questionBuilder.setLength(0);
}
} else {
questionBuilder.append(line).append(" ");
}
}
// 处理最后一个题目
if (questionBuilder.length() > 0) {
String question = questionBuilder.toString().replaceAll("^\\d+\\.\\s*", "");
existingQuestions.add(question.trim());
}
} catch (IOException e) {
System.out.println("读取文件失败: " + file.getName());
}
}
// 处理最后一个题目
if (questionBuilder.length() > 0) {
String question = questionBuilder.toString().replaceAll("^\\d+\\.\\s*", "");
existingQuestions.add(question.trim());
}
} catch (IOException e) {
System.out.println("读取文件失败: " + file.getName());
}
}
return existingQuestions;
}
}
return existingQuestions;
}
}

@ -1,85 +1,88 @@
package src;
public class HighSchoolGenerator extends QuestionGenerator {
private static final String[] BASIC_OPERATORS = {"+", "-", "*", "/"};
private static final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"};
public HighSchoolGenerator() {
super("高中");
}
@Override
public String generateQuestion() {
String question;
do {
question = generateSingleQuestion();
} while (isDuplicate(question) || !question.matches(".*(sin|cos|tan)\\(.*\\).*")); // 确保包含三角函数
addToGenerated(question);
return question;
}
private String generateSingleQuestion() {
int operatorCount = generateOperatorCount();
StringBuilder questionBuilder = new StringBuilder();
boolean hasTrigFunction = false;
// 生成第一个操作数或三角函数
hasTrigFunction = processFirstOperandOrTrig(questionBuilder);
// 生成操作符和操作数
processOperatorsAndOperands(questionBuilder, operatorCount, hasTrigFunction);
return questionBuilder.toString();
}
private boolean processFirstOperandOrTrig(StringBuilder builder) {
if (random.nextBoolean()) {
// 使用三角函数
String trigFunction = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)];
int angle = random.nextInt(360) + 1; // 1-360度
builder.append(trigFunction).append("(").append(angle).append("°)");
return true;
} else {
// 使用普通数字
builder.append(generateOperand());
return false;
}
}
private void processOperatorsAndOperands(StringBuilder builder, int operatorCount, boolean hasTrigFunction) {
for (int i = 0; i < operatorCount; i++) {
String operator = BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)];
// 决定下一个操作数是普通数字还是三角函数
if (!hasTrigFunction && i == operatorCount - 1) {
// 确保至少有一个三角函数
appendTrigFunction(builder, operator);
hasTrigFunction = true;
} else if (random.nextBoolean()) {
// 使用三角函数
appendTrigFunction(builder, operator);
hasTrigFunction = true;
} else {
// 使用普通数字
appendBasicOperand(builder, operator, operatorCount);
}
}
private static final String[] BASIC_OPERATORS = {"+", "-", "*", "/"};
private static final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"};
public HighSchoolGenerator() {
super("高中");
}
@Override
public String generateQuestion() {
String question;
do {
question = generateSingleQuestion();
} while (isDuplicate(question) || !question.matches(".*(sin|cos|tan)\\(.*\\).*")); // 确保包含三角函数
addToGenerated(question);
return question;
}
private String generateSingleQuestion() {
int operatorCount = generateOperatorCount();
StringBuilder questionBuilder = new StringBuilder();
boolean hasTrigFunction = false;
// 生成第一个操作数或三角函数
hasTrigFunction = processFirstOperandOrTrig(questionBuilder);
// 生成操作符和操作数
processOperatorsAndOperands(questionBuilder, operatorCount, hasTrigFunction);
return questionBuilder.toString();
}
private boolean processFirstOperandOrTrig(StringBuilder builder) {
if (random.nextBoolean()) {
// 使用三角函数
String trigFunction = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)];
int angle = random.nextInt(360) + 1; // 1-360度
builder.append(trigFunction).append("(").append(angle).append("°)");
return true;
} else {
// 使用普通数字
builder.append(generateOperand());
return false;
}
private void appendTrigFunction(StringBuilder builder, String operator) {
String trigFunction = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)];
int angle = random.nextInt(360) + 1;
builder.append(" ").append(operator).append(" ").append(trigFunction).append("(").append(angle).append("°)");
}
private void processOperatorsAndOperands(StringBuilder builder, int operatorCount,
boolean hasTrigFunction) {
for (int i = 0; i < operatorCount; i++) {
String operator = BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)];
// 决定下一个操作数是普通数字还是三角函数
if (!hasTrigFunction && i == operatorCount - 1) {
// 确保至少有一个三角函数
appendTrigFunction(builder, operator);
hasTrigFunction = true;
} else if (random.nextBoolean()) {
// 使用三角函数
appendTrigFunction(builder, operator);
hasTrigFunction = true;
} else {
// 使用普通数字
appendBasicOperand(builder, operator, operatorCount);
}
}
private void appendBasicOperand(StringBuilder builder, String operator, int operatorCount) {
int operand = generateOperand();
// 随机决定是否加括号
if (random.nextBoolean() && operatorCount > 1) {
builder.insert(0, "(").append(" ").append(operator).append(" ").append(operand).append(")");
} else {
builder.append(" ").append(operator).append(" ").append(operand);
}
}
private void appendTrigFunction(StringBuilder builder, String operator) {
String trigFunction = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)];
int angle = random.nextInt(360) + 1;
builder.append(" ").append(operator).append(" ").append(trigFunction).append("(").append(angle)
.append("°)");
}
private void appendBasicOperand(StringBuilder builder, String operator, int operatorCount) {
int operand = generateOperand();
// 随机决定是否加括号
if (random.nextBoolean() && operatorCount > 1) {
builder.insert(0, "(").append(" ").append(operator).append(" ").append(operand).append(")");
} else {
builder.append(" ").append(operator).append(" ").append(operand);
}
}
}

@ -1,95 +1,99 @@
package src;
public class MiddleSchoolGenerator extends QuestionGenerator {
private static final String[] BASIC_OPERATORS = {"+", "-", "*", "/"};
private static final String[] ADVANCED_OPERATORS = {"²", "√"};
public MiddleSchoolGenerator() {
super("初中");
}
@Override
public String generateQuestion() {
String question;
do {
question = generateSingleQuestion();
} while (isDuplicate(question) || !question.matches(".*[²√].*")); // 确保包含高级运算符
addToGenerated(question);
return question;
}
private String generateSingleQuestion() {
int operatorCount = generateOperatorCount();
StringBuilder questionBuilder = new StringBuilder();
boolean hasAdvancedOperator = false;
// 生成第一个操作数
int firstOperand = generateOperand();
// 处理第一个操作数(可能使用高级运算符)
hasAdvancedOperator = processFirstOperand(questionBuilder, firstOperand);
// 生成操作符和操作数
processOperatorsAndOperands(questionBuilder, operatorCount, hasAdvancedOperator);
return questionBuilder.toString();
}
private boolean processFirstOperand(StringBuilder builder, int operand) {
// 随机决定第一个操作数是否使用高级运算符
if (random.nextBoolean()) {
String advancedOp = ADVANCED_OPERATORS[random.nextInt(ADVANCED_OPERATORS.length)];
if (advancedOp.equals("²")) {
builder.append(operand).append("²");
} else {
builder.append("√").append(operand);
}
return true;
} else {
builder.append(operand);
return false;
}
private static final String[] BASIC_OPERATORS = {"+", "-", "*", "/"};
private static final String[] ADVANCED_OPERATORS = {"²", "√"};
public MiddleSchoolGenerator() {
super("初中");
}
@Override
public String generateQuestion() {
String question;
do {
question = generateSingleQuestion();
} while (isDuplicate(question) || !question.matches(".*[²√].*")); // 确保包含高级运算符
addToGenerated(question);
return question;
}
private String generateSingleQuestion() {
int operatorCount = generateOperatorCount();
StringBuilder questionBuilder = new StringBuilder();
boolean hasAdvancedOperator = false;
// 生成第一个操作数
int firstOperand = generateOperand();
// 处理第一个操作数(可能使用高级运算符)
hasAdvancedOperator = processFirstOperand(questionBuilder, firstOperand);
// 生成操作符和操作数
processOperatorsAndOperands(questionBuilder, operatorCount, hasAdvancedOperator);
return questionBuilder.toString();
}
private boolean processFirstOperand(StringBuilder builder, int operand) {
// 随机决定第一个操作数是否使用高级运算符
if (random.nextBoolean()) {
String advancedOp = ADVANCED_OPERATORS[random.nextInt(ADVANCED_OPERATORS.length)];
if (advancedOp.equals("²")) {
builder.append(operand).append("²");
} else {
builder.append("√").append(operand);
}
return true;
} else {
builder.append(operand);
return false;
}
private void processOperatorsAndOperands(StringBuilder builder, int operatorCount, boolean hasAdvancedOperator) {
for (int i = 0; i < operatorCount; i++) {
String operator = determineOperator(i, operatorCount, hasAdvancedOperator);
int operand = generateOperand();
if (operator.equals("²") || operator.equals("√")) {
processAdvancedOperator(builder, operator, operand);
hasAdvancedOperator = true;
} else {
processBasicOperator(builder, operator, operand, operatorCount);
}
}
}
private void processOperatorsAndOperands(StringBuilder builder, int operatorCount,
boolean hasAdvancedOperator) {
for (int i = 0; i < operatorCount; i++) {
String operator = determineOperator(i, operatorCount, hasAdvancedOperator);
int operand = generateOperand();
if (operator.equals("²") || operator.equals("√")) {
processAdvancedOperator(builder, operator, operand);
hasAdvancedOperator = true;
} else {
processBasicOperator(builder, operator, operand, operatorCount);
}
}
private String determineOperator(int currentIndex, int totalOperators, boolean hasAdvancedOperator) {
if (!hasAdvancedOperator && currentIndex == totalOperators - 1) {
// 确保至少有一个高级运算符
return ADVANCED_OPERATORS[random.nextInt(ADVANCED_OPERATORS.length)];
} else {
return BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)];
}
}
private String determineOperator(int currentIndex, int totalOperators,
boolean hasAdvancedOperator) {
if (!hasAdvancedOperator && currentIndex == totalOperators - 1) {
// 确保至少有一个高级运算符
return ADVANCED_OPERATORS[random.nextInt(ADVANCED_OPERATORS.length)];
} else {
return BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)];
}
private void processAdvancedOperator(StringBuilder builder, String operator, int operand) {
String basicOp = BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)];
if (operator.equals("²")) {
builder.append(" ").append(basicOp).append(" ").append(operand).append("²");
} else {
builder.append(" ").append(basicOp).append(" √").append(operand);
}
}
private void processAdvancedOperator(StringBuilder builder, String operator, int operand) {
String basicOp = BASIC_OPERATORS[random.nextInt(BASIC_OPERATORS.length)];
if (operator.equals("²")) {
builder.append(" ").append(basicOp).append(" ").append(operand).append("²");
} else {
builder.append(" ").append(basicOp).append(" √").append(operand);
}
private void processBasicOperator(StringBuilder builder, String operator, int operand, int operatorCount) {
// 随机决定是否加括号
if (random.nextBoolean() && operatorCount > 1) {
builder.insert(0, "(").append(" ").append(operator).append(" ").append(operand).append(")");
} else {
builder.append(" ").append(operator).append(" ").append(operand);
}
}
private void processBasicOperator(StringBuilder builder, String operator, int operand,
int operatorCount) {
// 随机决定是否加括号
if (random.nextBoolean() && operatorCount > 1) {
builder.insert(0, "(").append(" ").append(operator).append(" ").append(operand).append(")");
} else {
builder.append(" ").append(operator).append(" ").append(operand);
}
}
}

@ -1,40 +1,41 @@
package src;
public class PrimarySchoolGenerator extends QuestionGenerator {
private static final String[] OPERATORS = {"+", "-", "*", "/"};
public PrimarySchoolGenerator() {
super("小学");
}
@Override
public String generateQuestion() {
String question;
do {
int operatorCount = generateOperatorCount();
StringBuilder questionBuilder = new StringBuilder();
// 生成第一个操作数
questionBuilder.append(generateOperand());
// 生成操作符和操作数
for (int i = 0; i < operatorCount; i++) {
String operator = OPERATORS[random.nextInt(OPERATORS.length)];
int operand = generateOperand();
// 随机决定是否加括号
if (random.nextBoolean() && operatorCount > 1) {
questionBuilder.insert(0, "(").append(" " + operator + " " + operand + ")");
} else {
questionBuilder.append(" " + operator + " " + operand);
}
}
question = questionBuilder.toString();
} while (isDuplicate(question));
addToGenerated(question);
return question;
}
private static final String[] OPERATORS = {"+", "-", "*", "/"};
public PrimarySchoolGenerator() {
super("小学");
}
@Override
public String generateQuestion() {
String question;
do {
int operatorCount = generateOperatorCount_one();
StringBuilder questionBuilder = new StringBuilder();
// 生成第一个操作数
questionBuilder.append(generateOperand());
// 生成操作符和操作数
for (int i = 0; i < operatorCount; i++) {
String operator = OPERATORS[random.nextInt(OPERATORS.length)];
int operand = generateOperand();
// 随机决定是否加括号
if (random.nextBoolean() && operatorCount > 1) {
questionBuilder.insert(0, "(").append(" " + operator + " " + operand + ")");
} else {
questionBuilder.append(" " + operator + " " + operand);
}
}
question = questionBuilder.toString();
} while (isDuplicate(question));
addToGenerated(question);
return question;
}
}

@ -5,45 +5,50 @@ import java.util.Random;
import java.util.Set;
public abstract class QuestionGenerator {
protected Random random = new Random();
protected Set<String> generatedQuestions = new HashSet<>();
protected String currentType;
public QuestionGenerator(String type) {
this.currentType = type;
}
// 生成操作数
protected int generateOperand() {
return random.nextInt(100) + 1; // 1-100
}
// 生成操作符数量
protected int generateOperatorCount() {
return random.nextInt(5) + 1; // 1-5个操作符
}
// 检查题目是否重复
protected boolean isDuplicate(String question) {
return generatedQuestions.contains(question);
}
// 添加题目到已生成集合
protected void addToGenerated(String question) {
generatedQuestions.add(question);
}
// 抽象方法:生成题目
public abstract String generateQuestion();
// 获取当前类型
public String getCurrentType() {
return currentType;
}
// 设置当前类型
public void setCurrentType(String type) {
this.currentType = type;
this.generatedQuestions.clear(); // 切换类型时清空已生成题目
}
protected Random random = new Random();
protected Set<String> generatedQuestions = new HashSet<>();
protected String currentType;
public QuestionGenerator(String type) {
this.currentType = type;
}
// 生成操作数
protected int generateOperand() {
return random.nextInt(100) + 1; // 1-100
}
// 生成操作符数量
protected int generateOperatorCount() {
return random.nextInt(5) + 1; // 1-5个操作符
}
protected int generateOperatorCount_one() {
return random.nextInt(4) + 2; // 1-5个操作符
}
// 检查题目是否重复
protected boolean isDuplicate(String question) {
return generatedQuestions.contains(question);
}
// 添加题目到已生成集合
protected void addToGenerated(String question) {
generatedQuestions.add(question);
}
// 抽象方法:生成题目
public abstract String generateQuestion();
// 获取当前类型
public String getCurrentType() {
return currentType;
}
// 设置当前类型
public void setCurrentType(String type) {
this.currentType = type;
this.generatedQuestions.clear(); // 切换类型时清空已生成题目
}
}

@ -4,135 +4,108 @@ import java.util.HashMap;
import java.util.Map;
public class User {
private String username;
private String password;
private String userType; // 小学、初中、高中
// 静态用户映射,用于存储所有用户
private static Map<String, User> userMap = getPresetUsers();
public User(String username, String password, String userType) {
this.username = username;
this.password = password;
this.userType = userType;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getUserType() {
return userType;
}
// 用户管理接口
/**
*
* @param username
* @param password
* @param userType
* @return truefalse
*/
public static boolean addUser(String username, String password, String userType) {
if (userMap.containsKey(username)) {
return false; // 用户名已存在
}
userMap.put(username, new User(username, password, userType));
return true;
}
/**
*
* @param username
* @return truefalse
*/
public static boolean removeUser(String username) {
if (!userMap.containsKey(username)) {
return false; // 用户不存在
}
userMap.remove(username);
return true;
}
/**
*
* @param username
* @return truefalse
*/
public static boolean userExists(String username) {
return userMap.containsKey(username);
}
/**
*
* @param username
* @param password
* @return Usernull
*/
public static User authenticate(String username, String password) {
User user = userMap.get(username);
if (user != null && user.getPassword().equals(password)) {
return user;
}
return null;
}
/**
*
* @return
*/
public static int getUserCount() {
return userMap.size();
}
/**
*
* @param userType
* @return
*/
public static int getUserCountByType(String userType) {
int count = 0;
for (User user : userMap.values()) {
if (user.getUserType().equals(userType)) {
count++;
}
}
return count;
private String username;
private String password;
private String userType; // 小学、初中、高中
// 静态用户映射,用于存储所有用户
private static Map<String, User> userMap = getPresetUsers();
public User(String username, String password, String userType) {
this.username = username;
this.password = password;
this.userType = userType;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getUserType() {
return userType;
}
// 用户管理接口
/**
*
*
* @param username
* @param password
* @param userType
* @return truefalse
*/
public static boolean addUser(String username, String password, String userType) {
if (userMap.containsKey(username)) {
return false; // 用户名已存在
}
/**
*
* @param username
* @return Usernull
*/
public static User getUser(String username) {
return userMap.get(username);
userMap.put(username, new User(username, password, userType));
return true;
}
/**
*
*
* @param username
* @return truefalse
*/
public static boolean removeUser(String username) {
if (!userMap.containsKey(username)) {
return false; // 用户不存在
}
// 预设用户数据
public static Map<String, User> getPresetUsers() {
Map<String, User> users = new HashMap<>();
// 小学用户
users.put("张三1", new User("张三1", "123", "小学"));
users.put("张三2", new User("张三2", "123", "小学"));
users.put("张三3", new User("张三3", "123", "小学"));
// 初中用户
users.put("李四1", new User("李四1", "123", "初中"));
users.put("李四2", new User("李四2", "123", "初中"));
users.put("李四3", new User("李四3", "123", "初中"));
// 高中用户
users.put("王五1", new User("王五1", "123", "高中"));
users.put("王五2", new User("王五2", "123", "高中"));
users.put("王五3", new User("王五3", "123", "高中"));
return users;
userMap.remove(username);
return true;
}
/**
*
*
* @param username
* @return truefalse
*/
public static boolean userExists(String username) {
return userMap.containsKey(username);
}
/**
*
*
* @param username
* @param password
* @return Usernull
*/
public static User authenticate(String username, String password) {
User user = userMap.get(username);
if (user != null && user.getPassword().equals(password)) {
return user;
}
return null;
}
// 预设用户数据
public static Map<String, User> getPresetUsers() {
Map<String, User> users = new HashMap<>();
// 小学用户
users.put("张三1", new User("张三1", "123", "小学"));
users.put("张三2", new User("张三2", "123", "小学"));
users.put("张三3", new User("张三3", "123", "小学"));
// 初中用户
users.put("李四1", new User("李四1", "123", "初中"));
users.put("李四2", new User("李四2", "123", "初中"));
users.put("李四3", new User("李四3", "123", "初中"));
// 高中用户
users.put("王五1", new User("王五1", "123", "高中"));
users.put("王五2", new User("王五2", "123", "高中"));
users.put("王五3", new User("王五3", "123", "高中"));
return users;
}
}
Loading…
Cancel
Save