Compare commits

...

5 Commits

@ -1,2 +0,0 @@
# wanglei

@ -0,0 +1,156 @@
# 中小学数学卷子自动生成程序
## 项目简介
这是一个为中小学数学老师设计的命令行卷子自动生成程序,支持小学、初中、高中三个难度级别。程序能够根据教师账户类型自动生成相应难度的数学题目,并确保题目不重复。
## 功能特性
- **用户认证系统** - 支持小学、初中、高中各三个预设账户
- **多难度题目生成** - 根据不同学段生成相应难度的数学题目
- **智能查重** - 确保同一教师的题目不重复
- **灵活切换** - 支持在登录状态下切换出题难度
- **自动保存** - 按用户分文件夹保存,文件命名规范
## 预设账户
| 账户类型 | 用户名 | 密码 |
|---------|--------|------|
| 小学 | 张三1, 张三2, 张三3 | 123 |
| 初中 | 李四1, 李四2, 李四3 | 123 |
| 高中 | 王五1, 王五2, 王五3 | 123 |
## 题目难度要求
### 小学题目
- **运算符**: `+`, `-`, `*`, `/`, `()`
- **要求**: 只能包含基本四则运算和括号
- **示例**: `15 + (23 - 8) * 3 = `
### 初中题目
- **运算符**: `+`, `-`, `*`, `/`, `()`, `²`, `√`
- **要求**: 至少包含一个平方或开根号运算符
- **示例**: `5² + √16 * 3 = `
### 高中题目
- **运算符**: `+`, `-`, `*`, `/`, `()`, `sin`, `cos`, `tan`
- **要求**: 至少包含一个三角函数运算符
- **示例**: `sin(45°) + cos(30°) * 2 = `
## 技术架构
### 项目结构
src/
├── Main.java # 程序入口
├── User.java # 用户模型
├── UserType.java # 用户类型枚举
├── AuthManager.java # 认证管理器
├── QuestionGenerator.java # 题目生成器接口
├── PrimaryQuestionGenerator.java # 小学题目生成器
├── JuniorQuestionGenerator.java # 初中题目生成器
├── SeniorQuestionGenerator.java # 高中题目生成器
├── QuestionGeneratorFactory.java # 工厂类
├── QuestionService.java # 题目服务
├── DuplicateChecker.java # 查重服务
├── FileService.java # 文件服务
└── Question.java # 题目模型
text
### 设计模式
- **工厂模式** - 题目生成器工厂
- **策略模式** - 不同难度的题目生成策略
- **面向对象设计** - 类职责分离
## 安装与运行
### 环境要求
- Java 8 或更高版本
- 支持命令行操作的系统
### 编译项目
```bash
# 进入项目src目录
cd src
# 编译所有Java文件
javac *.java
# 运行程序
java Main
使用说明
1. 登录系统
text
=== 中小学数学卷子自动生成程序 ===
请输入用户名和密码(用空格隔开):
张三1 123
当前选择为小学出题
2. 生成题目
text
准备生成小学数学题目请输入生成题目数量10-30输入-1将退出当前用户重新登录
15
题目生成完成!题目已保存到: questions/张三1/2025-01-20-14-30-25.txt
3. 切换难度
text
切换为初中
已切换为初中出题
4. 退出登录
text
-1
已退出当前用户
文件保存规范
目录结构
text
questions/
├── 张三1/
│ ├── 2025-01-20-14-30-25.txt
│ └── 2025-01-20-15-45-10.txt
├── 李四1/
│ └── 2025-01-20-16-20-35.txt
└── 王五1/
└── 2025-01-20-17-15-40.txt
文件格式
text
1. 25 + 13 * (45 - 12) =
2. 15 / 3 + 28 =
3. (67 + 34) * 2 - 15 =
故障排除
常见问题
编译错误
确保所有Java文件在同一目录下
检查Java环境变量配置
运行错误
确认所有.class文件已生成
检查文件读写权限
题目生成失败
确认输入题目数量在10-30范围内
检查磁盘空间是否充足
项目规范
代码符合面向对象设计原则
类职责单一,方法简洁
包含完整的异常处理
支持题目查重功能
版本信息
作者: 王磊
班级: 软件2301
学号202326010106
项目名称: 中小学数学卷子自动生成程序

@ -0,0 +1,25 @@
import java.util.Arrays;
import java.util.List;
public class AuthManager {
private static final List<User> USERS = Arrays.asList(
new User("张三1", "123", UserType.PRIMARY),
new User("张三2", "123", UserType.PRIMARY),
new User("张三3", "123", UserType.PRIMARY),
new User("李四1", "123", UserType.JUNIOR),
new User("李四2", "123", UserType.JUNIOR),
new User("李四3", "123", UserType.JUNIOR),
new User("王五1", "123", UserType.SENIOR),
new User("王五2", "123", UserType.SENIOR),
new User("王五3", "123", UserType.SENIOR)
);
public User authenticate(String username, String password) {
for (User user : USERS) {
if (user.getUsername().equals(username) && user.getPassword().equals(password)) {
return user;
}
}
return null;
}
}

@ -0,0 +1,71 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class DuplicateChecker {
public boolean isDuplicate(String username, String questionContent) {
String userDir = "questions/" + username + "/";
File dir = new File(userDir);
if (!dir.exists()) {
return false;
}
File[] files = dir.listFiles((d, name) -> name.endsWith(".txt"));
if (files == null) {
return false;
}
for (File file : files) {
try {
List<String> lines = Files.readAllLines(Paths.get(file.getAbsolutePath()));
for (String line : lines) {
if (line.trim().isEmpty()) continue;
// 提取题目内容(去掉题号)
String content = line.substring(line.indexOf('.') + 1).trim();
if (content.equals(questionContent)) {
return true;
}
}
} catch (IOException e) {
System.err.println("读取文件失败: " + file.getName());
}
}
return false;
}
public List<String> getUserQuestions(String username) {
List<String> questions = new ArrayList<>();
String userDir = "questions/" + username + "/";
File dir = new File(userDir);
if (!dir.exists()) {
return questions;
}
File[] files = dir.listFiles((d, name) -> name.endsWith(".txt"));
if (files == null) {
return questions;
}
for (File file : files) {
try {
List<String> lines = Files.readAllLines(Paths.get(file.getAbsolutePath()));
for (String line : lines) {
if (line.trim().isEmpty()) continue;
String content = line.substring(line.indexOf('.') + 1).trim();
questions.add(content);
}
} catch (IOException e) {
System.err.println("读取文件失败: " + file.getName());
}
}
return questions;
}
}

@ -0,0 +1,32 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class FileService {
public String saveQuestions(String username, List<Question> questions) throws IOException {
// 创建用户目录
String userDir = "questions/" + username + "/";
File dir = new File(userDir);
if (!dir.exists()) {
dir.mkdirs();
}
// 生成文件名
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
String filename = userDir + timestamp + ".txt";
// 写入文件
try (FileWriter writer = new FileWriter(filename)) {
for (int i = 0; i < questions.size(); i++) {
writer.write(questions.get(i).toString());
writer.write("\n\n"); // 题目之间空一行
}
}
return filename;
}
}

@ -0,0 +1,47 @@
import java.util.Random;
public class JuniorQuestionGenerator implements QuestionGenerator {
private Random random = new Random();
private final String[] OPERATORS = {"+", "-", "*", "/"};
@Override
public String generateQuestion() {
int operandCount = random.nextInt(3) + 2; // 2-4个操作数
StringBuilder question = new StringBuilder();
// 确保至少有一个平方或开根号
boolean hasSpecialOperator = false;
int specialOperatorPosition = random.nextInt(operandCount);
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
question.append(" ").append(OPERATORS[random.nextInt(OPERATORS.length)]).append(" ");
}
// 在特定位置添加平方或开根号
if (i == specialOperatorPosition || !hasSpecialOperator) {
if (random.nextBoolean()) {
// 平方
int num = random.nextInt(20) + 1; // 1-20的平方
question.append(num).append("²");
hasSpecialOperator = true;
} else {
// 开根号
int num = random.nextInt(100) + 1; // 1-100开根号
question.append("√").append(num);
hasSpecialOperator = true;
}
} else {
question.append(random.nextInt(100) + 1);
}
}
return question.toString() + " = ";
}
@Override
public boolean isValidQuestion(String question) {
return (question.contains("²") || question.contains("√")) &&
question.contains("=");
}
}

@ -0,0 +1,41 @@
import java.util.Random;
public class PrimaryQuestionGenerator implements QuestionGenerator {
private Random random = new Random();
private final String[] OPERATORS = {"+", "-", "*", "/"};
@Override
public String generateQuestion() {
int operandCount = random.nextInt(3) + 2; // 2-4个操作数
StringBuilder question = new StringBuilder();
// 随机决定是否添加括号
boolean hasParentheses = operandCount >= 3 && random.nextBoolean();
int parenthesesPosition = hasParentheses ? random.nextInt(operandCount - 1) : -1;
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
question.append(" ").append(OPERATORS[random.nextInt(OPERATORS.length)]).append(" ");
}
if (hasParentheses && i == parenthesesPosition) {
question.append("(");
}
question.append(random.nextInt(100) + 1); // 1-100
if (hasParentheses && i == parenthesesPosition + 1) {
question.append(")");
}
}
return question.toString() + " = ";
}
@Override
public boolean isValidQuestion(String question) {
return question.matches(".*[+\\-*/].*") &&
!question.matches(".*[√²sincostan].*") &&
question.contains("=");
}
}

@ -0,0 +1,20 @@
public class Question {
private int number;
private String content;
private String userType;
public Question(int number, String content, String userType) {
this.number = number;
this.content = content;
this.userType = userType;
}
public int getNumber() { return number; }
public String getContent() { return content; }
public String getUserType() { return userType; }
@Override
public String toString() {
return number + ". " + content;
}
}

@ -0,0 +1,4 @@
public interface QuestionGenerator {
String generateQuestion();
boolean isValidQuestion(String question);
}

@ -0,0 +1,14 @@
public class QuestionGeneratorFactory {
public static QuestionGenerator createGenerator(UserType userType) {
switch (userType) {
case PRIMARY:
return new PrimaryQuestionGenerator();
case JUNIOR:
return new JuniorQuestionGenerator();
case SENIOR:
return new SeniorQuestionGenerator();
default:
throw new IllegalArgumentException("不支持的题目类型: " + userType);
}
}
}

@ -0,0 +1,41 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class QuestionService {
private DuplicateChecker duplicateChecker = new DuplicateChecker();
private FileService fileService = new FileService();
public void generateAndSaveQuestions(User user, int count) {
QuestionGenerator generator = QuestionGeneratorFactory.createGenerator(user.getUserType());
List<Question> questions = new ArrayList<>();
int generated = 0;
int attempts = 0;
int maxAttempts = count * 10; // 防止无限循环
while (generated < count && attempts < maxAttempts) {
String questionContent = generator.generateQuestion();
// 检查题目是否有效且不重复
if (generator.isValidQuestion(questionContent) &&
!duplicateChecker.isDuplicate(user.getUsername(), questionContent)) {
questions.add(new Question(generated + 1, questionContent,
user.getUserType().getDisplayName()));
generated++;
}
attempts++;
}
if (generated < count) {
System.out.println("警告:只生成了 " + generated + " 个不重复的题目(请求数量:" + count + "");
}
try {
String filename = fileService.saveQuestions(user.getUsername(), questions);
System.out.println("题目已保存到: " + filename);
} catch (IOException e) {
System.out.println("保存文件失败: " + e.getMessage());
}
}
}

@ -0,0 +1,41 @@
import java.util.Random;
public class SeniorQuestionGenerator implements QuestionGenerator {
private Random random = new Random();
private final String[] OPERATORS = {"+", "-", "*", "/"};
private final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"};
@Override
public String generateQuestion() {
int operandCount = random.nextInt(3) + 2; // 2-4个操作数
StringBuilder question = new StringBuilder();
// 确保至少有一个三角函数
boolean hasTrigFunction = false;
int trigFunctionPosition = random.nextInt(operandCount);
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
question.append(" ").append(OPERATORS[random.nextInt(OPERATORS.length)]).append(" ");
}
// 在特定位置添加三角函数
if (i == trigFunctionPosition || !hasTrigFunction) {
String trigFunction = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)];
int angle = random.nextInt(360); // 0-359度
question.append(trigFunction).append("(").append(angle).append("°)");
hasTrigFunction = true;
} else {
question.append(random.nextInt(100) + 1);
}
}
return question.toString() + " = ";
}
@Override
public boolean isValidQuestion(String question) {
return (question.contains("sin") || question.contains("cos") || question.contains("tan")) &&
question.contains("=");
}
}

@ -0,0 +1,25 @@
public class User {
private String username;
private String password;
private UserType userType;
public User(String username, String password, UserType userType) {
this.username = username;
this.password = password;
this.userType = userType;
}
// Getters
public String getUsername() { return username; }
public String getPassword() { return password; }
public UserType getUserType() { return userType; }
public void setUserType(UserType userType) {
this.userType = userType;
}
@Override
public String toString() {
return username + " (" + userType.getDisplayName() + ")";
}
}

@ -0,0 +1,24 @@
public enum UserType {
PRIMARY("小学"),
JUNIOR("初中"),
SENIOR("高中");
private final String displayName;
UserType(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
public static UserType fromDisplayName(String displayName) {
for (UserType type : values()) {
if (type.displayName.equals(displayName)) {
return type;
}
}
return null;
}
}

@ -0,0 +1,95 @@
import java.util.Scanner;
public class Main {
private static final AuthManager authManager = new AuthManager();
private static final QuestionService questionService = new QuestionService();
private static final Scanner scanner = new Scanner(System.in);
private static User currentUser = null;
public static void main(String[] args) {
System.out.println("=== 中小学数学卷子自动生成程序 ===");
while (true) {
if (currentUser == null) {
login();
} else {
generateQuestions();
}
}
}
private static void login() {
System.out.println("请输入用户名和密码(用空格隔开):");
try {
String input = scanner.nextLine().trim();
if (input.isEmpty()) {
return;
}
String[] credentials = input.split("\\s+");
if (credentials.length != 2) {
System.out.println("请输入正确的用户名、密码");
return;
}
currentUser = authManager.authenticate(credentials[0], credentials[1]);
if (currentUser == null) {
System.out.println("请输入正确的用户名、密码");
} else {
System.out.println("当前选择为" + currentUser.getUserType().getDisplayName() + "出题");
}
} catch (Exception e) {
System.out.println("输入格式错误,请重新输入");
}
}
private static void generateQuestions() {
System.out.println("准备生成" + currentUser.getUserType().getDisplayName() +
"数学题目请输入生成题目数量10-30输入-1将退出当前用户重新登录");
try {
String input = scanner.nextLine().trim();
if (input.startsWith("切换为")) {
handleSwitchCommand(input);
return;
}
int count = Integer.parseInt(input);
if (count == -1) {
currentUser = null;
System.out.println("已退出当前用户");
return;
}
if (count < 10 || count > 30) {
System.out.println("题目数量范围应为10-30");
return;
}
questionService.generateAndSaveQuestions(currentUser, count);
System.out.println("题目生成完成!可继续生成题目或输入-1退出登录");
} catch (NumberFormatException e) {
System.out.println("请输入有效的数字");
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
}
}
private static void handleSwitchCommand(String command) {
String targetType = command.substring(3).trim();
UserType newType = UserType.fromDisplayName(targetType);
if (newType == null) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return;
}
currentUser.setUserType(newType);
System.out.println("已切换为" + currentUser.getUserType().getDisplayName() + "出题");
}
}
Loading…
Cancel
Save