feat: 添加文档说明

main
peterpan 4 days ago
parent 1bb4fc2e9d
commit 05fb0e0521

@ -1,2 +0,0 @@
# math-paper-cli

@ -0,0 +1,303 @@
# 数学题目生成器
这是潘俊晖在《软件工程导论》课程中的个人项目。
该项目是一个基于 Java 的命令行应用程序,支持用户登录并生成小学、初中、高中的数学题目。
项目采用**策略模式**设计,便于扩展新的题目生成器。
---
## 环境要求
- **JDK 版本**JDK 17+(兼容 JDK 11
- **依赖库**:纯 Java 项目,无需额外依赖
- **推荐 IDE**IntelliJ IDEA也可通过命令行运行
---
## 运行
### 1. 通过 JRE 运行 jar 包
执行:
```aiignore
java -jar new-math-cli.jar
```
### 2. 克隆仓库并通过 IDEA 运行
## 代码说明
### 登陆检查
```java
private static void handleLogin(Scanner scanner) {
System.out.println("**********欢迎使用数学题目生成 Client **********");
System.out.println("请输入用户名和密码,用空格隔开 (输入 'exit' 退出程序):");
String line = scanner.nextLine();
if ("exit".equalsIgnoreCase(line)) {
System.out.println("感谢使用,程序已退出。");
System.exit(0);
}
String[] input = line.split(" ");
if (input.length == 2) {
authService.login(input[0], input[1]).ifPresentOrElse(
user -> {
currentUser = user;
currentLevel = user.getLevel();
System.out.printf("当前选择为%s出题%n", currentLevel.getName());},
() -> System.out.println("请输入正确的用户名、密码")
);
} else {
System.out.println("输入格式不正确,请重新输入。");
}
}
```
### 生成题目时检查输入
```java
private static void handleQuestionGeneration(Scanner scanner) {
System.out.printf("准备生成%s数学题目, 请输入生成题目数量(输入-1将退出当前用户, 重新登录):%n", currentLevel.getName()); // 生成提示
System.out.println("可输入“切换为(小学/初中/高中)”");
String input = scanner.nextLine();
if (input.startsWith("切换为")) {
handleLevelSwitch(input);
return;
}
try {
int count = Integer.parseInt(input);
if (count == -1) {
currentUser = null;
currentLevel = null;
System.out.println("已退出,请重新登录。");
} else if (count >= 10 && count <= 30) {
testPaperService.generateAndSave(currentUser, currentLevel, count);
} else {
System.out.println("输入无效请输入10-30之间的数字或-1。");
}
} catch (NumberFormatException e) {
System.out.println("输入无效,请输入一个数字。");
}
}
```
### 题目查重和生成部分
```java
public void generateAndSave(User user, Level level, int count) {
Set<String> existingQuestions = loadExistingQuestions(user.getUsername());
System.out.println("检测到历史题目 " + existingQuestions.size() + " 道。");
IQuestionGenerator generator = createGenerator(level);
Set<String> newQuestions = new HashSet<>();
// 生成新的、与历史和本次不重复的题目
for (int i = 0; i < count; i++) {
Set<String> used = new HashSet<>(existingQuestions);
used.addAll(newQuestions);
String question = generator.generate(used);
newQuestions.add(question);
}
saveToFile(user.getUsername(), newQuestions);
}
private Set<String> loadExistingQuestions(String username) {
Set<String> existingQuestions = new HashSet<>();
File userDir = new File(username);
if (!userDir.exists() || !userDir.isDirectory()) {
return existingQuestions;
}
File[] files = userDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
if (files == null) {
return existingQuestions;
}
for (File file : files) {
try {
Files.lines(file.toPath()).forEach(line -> {
if (line.matches("^\\d+\\.\\s.*")) {
String question = line.substring(line.indexOf(' ') + 1).trim();
existingQuestions.add(question);
}
});
} catch (IOException e) {
System.err.println("错误:读取历史文件失败: " + file.getName());
}
}
return existingQuestions;
}
```
### 题目生成接口和抽象类
```java
// generator/IQuestionGenerator.java
package generator;
import java.util.Set;
public interface IQuestionGenerator {
String generate(Set<String> existingQuestions);
}
```
```java
// generator/BaseGenerator.java
package generator;
import java.util.Random;
import java.util.Set;
public abstract class BaseGenerator implements IQuestionGenerator {
protected final Random random = new Random();
protected int getRandomOperand() {
return random.nextInt(100) + 1;
}
protected int getNumberOfOperands() {
return random.nextInt(5) + 1;
}
@Override
public String generate(Set<String> existingQuestions) {
String question;
do {
question = createUniqueQuestion();
} while (existingQuestions.contains(question));
return question;
}
protected abstract String createUniqueQuestion();
}
```
### 小学题目生成器
```java
public class ElementarySchoolGenerator extends BaseGenerator {
private final String[] OPERATORS = {"+", "-", "*", "/"};
@Override
protected String createUniqueQuestion() {
int numOperands = random.nextInt(4) + 2;
StringBuilder sb = new StringBuilder();
int runningTotal = getRandomOperand();
sb.append(runningTotal);
for (int i = 0; i < numOperands - 1; i++) {
String operator = pickOperator();
int operand = getRandomOperand();
operator = adjustOperator(operator, operand, runningTotal);
runningTotal = applyOperation(runningTotal, operator, operand);
sb.append(" ").append(operator).append(" ").append(operand);
}
return sb.append(" = ?").toString();
}
private String pickOperator() {
return OPERATORS[random.nextInt(OPERATORS.length)];
}
private String adjustOperator(String op, int operand, int current) {
if (op.equals("-") && operand > current) return "+";
if (op.equals("/") && (operand == 0 || current % operand != 0)) return "*";
return op;
}
private int applyOperation(int current, String op, int operand) {
switch (op) {
case "+": return current + operand;
case "-": return current - operand;
case "*": return current * operand;
case "/": return current / operand;
default: throw new IllegalArgumentException("Unknown operator: " + op);
}
}
}
```
### 初中题目生成器
```java
public class JuniorHighGenerator extends BaseGenerator {
@Override
protected String createUniqueQuestion() {
int numOperands = random.nextInt(4) + 2;
List<String> operands = new ArrayList<>();
for (int i = 0; i < numOperands; i++) {
operands.add(String.valueOf(getRandomOperand()));
}
int specialIndex = random.nextInt(numOperands);
int originalValue = Integer.parseInt(operands.get(specialIndex));
if (random.nextBoolean()) {
operands.set(specialIndex, "sqrt(" + (originalValue * originalValue) + ")");
} else {
operands.set(specialIndex, originalValue + "^2");
}
StringBuilder questionBuilder = new StringBuilder();
String[] basicOperators = {"+", "-", "*"};
questionBuilder.append(operands.get(0));
for (int i = 1; i < numOperands; i++) {
String operator = basicOperators[random.nextInt(basicOperators.length)];
questionBuilder.append(" ").append(operator).append(" ").append(operands.get(i));
}
questionBuilder.append(" = ?");
return questionBuilder.toString();
}
}
```
### 高中题目生成器
```java
public class SeniorHighGenerator extends BaseGenerator {
@Override
protected String createUniqueQuestion() {
int numOperands = random.nextInt(4) + 2;
List<String> operands = new ArrayList<>();
for (int i = 0; i < numOperands; i++) {
operands.add(String.valueOf(getRandomOperand()));
}
int specialIndex = random.nextInt(numOperands);
String[] trigFunctions = {"sin", "cos", "tan"};
String func = trigFunctions[random.nextInt(trigFunctions.length)];
int angle = random.nextInt(91);
operands.set(specialIndex, String.format("%s(%d)", func, angle));
StringBuilder questionBuilder = new StringBuilder();
String[] basicOperators = {"+", "-", "*"};
questionBuilder.append(operands.get(0));
for (int i = 1; i < numOperands; i++) {
String operator = basicOperators[random.nextInt(basicOperators.length)];
questionBuilder.append(" ").append(operator).append(" ").append(operands.get(i));
}
questionBuilder.append(" = ?");
return questionBuilder.toString();
}
}
```
---
## 后续改进方向
- 增加题目难度参数(如:数字范围、运算符种类)。
- 增加 GUI 界面,提升交互体验。
- 增加单元测试和持续集成,确保题目生成正确性。
- 题目结果可导出为 PDF/Word 试卷格式。
---

@ -14,8 +14,8 @@ public class SeniorHighGenerator extends BaseGenerator {
} }
int specialIndex = random.nextInt(numOperands); int specialIndex = random.nextInt(numOperands);
String[] trigFuncs = {"sin", "cos", "tan"}; String[] trigFunctions = {"sin", "cos", "tan"};
String func = trigFuncs[random.nextInt(trigFuncs.length)]; String func = trigFunctions[random.nextInt(trigFunctions.length)];
int angle = random.nextInt(91); int angle = random.nextInt(91);
operands.set(specialIndex, String.format("%s(%d)", func, angle)); operands.set(specialIndex, String.format("%s(%d)", func, angle));

Loading…
Cancel
Save