项目结构重构:方法不超过40行,修复括号生成问题

develop
imok 4 days ago
parent ec0d58434b
commit 8c9898b20b

@ -1,5 +1,5 @@
<component name="ArtifactManager">
<artifact type="jar" name="mathQuetion:jar">
<artifact type="jar" build-on-make="true" name="mathQuetion:jar">
<output-path>$PROJECT_DIR$/out/artifacts/mathQuetion_jar</output-path>
<root id="archive" name="untitled.jar">
<element id="module-output" name="untitled" />

@ -38,6 +38,16 @@ cmd
cd math_question_release_v1.0 #进入程序目录
java -jar mathQuestion.jar #运行程序
方法三PowerShell运行
PowerShell
cd "C:\path\to\your\project" #进入目录
java -jar math_question.jar #运行
若出现中文乱码问题,需要设置 .NET 控制台输入/输出编码为 UTF-8输入以下代码
[Console]::InputEncoding = [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Linux
方法一使用Shell脚本推荐

@ -0,0 +1,31 @@
1. 69 - 65 - 7 =
2. 72 / 96 =
3. 35 / 75 =
4. 23 - 11 - 99 + 17 * 34 =
5. 8 - 21 =
6. 24 / 61 =
7. (55 + 43 /) 47 / 5 =
8. (26 - 22 *) 30 * 54 * 62 =
9. 90 / 20 + 44 + 32 =
10. 14 / 80 =
11. 55 + 72 + 51 + 16 / 84 =
12. 16 / 61 =
13. (18 + 36 /) 20 / 36 * 31 =
14. (3 + 90 /) 99 =
15. 29 * 65 =
16. 91 - 28 =

@ -0,0 +1,45 @@
1. (92 + 89 *) 83 =
2. 68 - 62 =
3. (57 - 88 /) 8 - 80 * 88 =
4. (65 + 64 +) 51 / 65 * 57 =
5. 41 - 42 =
6. 75 * 97 - 68 =
7. 87 * 78 * 55 * 46 - 1 =
8. (37 / 98 +) 3 =
9. 66 - 4 * 44 * 65 =
10. 93 - 86 + 67 / 20 =
11. 100 / 23 / 86 + 11 =
12. 53 / 52 / 85 + 84 =
13. (51 / 42 +) 9 - 62 - 8 =
14. 92 * 41 - 86 * 57 =
15. 39 - 42 * 26 - 14 =
16. 22 * 91 - 9 * 53 =
17. (55 * 8 -) 76 * 47 =
18. 54 - 98 - 79 * 66 =
19. 9 - 90 - 63 =
20. (18 * 64 /) 97 - 99 =
21. (90 * 88 *) 9 =
22. 70 + 87 * 67 =
23. 83 / 9 - 45 + 15 =

@ -0,0 +1,31 @@
1. √26 =
2. (2)² =
3. √56 =
4. (1)² =
5. (41 / 60 /) 71 =
6. (5)² =
7. √57 =
8. √91 =
9. √71 =
10. (3)² + 17 - 41 * 61 - 99 * 52 =
11. (9 + 52 * 9 +) 51 * 27 =
12. √62 + 1 * 16 - 31 =
13. (6)² =
14. √38 + (7 - 5 -) 57 - 12 =
15. √29 =
16. √73 =

@ -0,0 +1,31 @@
1. sin(26°) =
2. sin(53°) + 34 * 16 / 59 =
3. 48 * 85 - 80 =
4. cos(52°) + (2)² + 54 - 34 / 99 + 69 =
5. tan(44°) + (1)² =
6. cos(6°) + 27 - 34 * 83 =
7. (44 - 79 /) 10 - 62 =
8. 35 / 42 / 21 / 24 + 75 =
9. sin(84°) + √76 =
10. cos(1°) =
11. sin(5°) + √55 =
12. sin(31°) =
13. cos(79°) + (78 * 51 -) 67 - 67 / 32 =
14. cos(7°) + (37 - 6 *) 8 / 89 - 1 =
15. sin(20°) + (19 * 74 +) 83 =
16. tan(53°) + 51 / 76 - 71 + 68 =

@ -0,0 +1,31 @@
1. 32 + 97 / 81 * 72 / 2 =
2. 15 / 83 =
3. 35 + 72 * 65 + 4 * 16 =
4. (51 / 62) - 12 =
5. 58 * 52 =
6. 76 / 2 - 93 =
7. 80 - 12 + 75 / 41 =
8. 46 - 68 =
9. 58 - 48 - 27 - 10 =
10. 65 * 24 =
11. 15 - 78 * 28 - 66 + 72 =
12. 52 * 34 + 35 =
13. (91 / 27) + 49 - 32 =
14. 68 * 51 + 15 * 32 =
15. 39 + 14 * 63 * 3 - 73 =
16. 36 + 30 / 20 * 85 =

@ -0,0 +1,31 @@
1. 13 - 63 - 23 + 34 - 6 =
2. 13 - 17 =
3. √74 + 36 / 23 + 75 =
4. (6)² + 83 * 97 / 75 - 77 / 52 =
5. (4)² =
6. (8)² + 19 - 91 / 67 * 97 =
7. √35 + 47 / 40 =
8. (7)² =
9. √8 =
10. √90 =
11. 44 * 21 - 58 / 80 / 94 =
12. √18 =
13. √70 =
14. (10)² + 78 * 95 - 22 * 72 - 33 =
15. √34 =
16. (8)² + 12 - 50 - 74 =

@ -0,0 +1,31 @@
1. cos(4°) + √40 + 23 / 26 =
2. tan(26°) + √9 =
3. sin(24°) + √90 + 72 + 52 =
4. sin(86°) =
5. cos(62°) + (10)² =
6. 97 / 100 + 38 - 69 =
7. cos(20°) =
8. 19 / 79 + 3 - 85 / 34 =
9. sin(46°) + 52 + 6 =
10. 44 * 69 - 98 + 94 * 75 =
11. sin(48°) + 4 + 58 * 75 =
12. sin(80°) + 32 - 97 + 85 - 86 =
13. sin(72°) + (13 * 68) + 63 =
14. tan(84°) + 66 / 90 * 4 =
15. 38 / 19 =
16. cos(6°) + 41 + 28 * 73 - 44 =

@ -0,0 +1,59 @@
1. 50 + 97 + 6 + 70 =
2. cos(31°) + 21 + (13 / 72) / 76 * 74 =
3. tan(33°) + 41 + 30 - 19 / 29 * 66 =
4. tan(88°) + √68 + 34 - 15 - 5 =
5. tan(59°) =
6. sin(59°) + 20 * 60 / 46 / 71 =
7. sin(36°) + (7)² + 47 * 48 / 23 + 5 - 20 =
8. 87 - 43 =
9. cos(19°) =
10. 42 * (56 - 58) - 6 =
11. sin(41°) + (10 + 75) / 47 / 96 =
12. sin(38°) =
13. cos(35°) + (1)² =
14. 80 / 97 + (18 - 92) / 80 =
15. cos(83°) =
16. cos(85°) + 33 + 69 - 8 - 48 * 6 =
17. sin(61°) + 25 / 33 + 42 =
18. 35 + 75 =
19. sin(51°) + (23 + 18) + 12 * 79 =
20. sin(63°) + 68 - 40 =
21. tan(84°) + 82 - 72 * 31 =
22. sin(50°) =
23. cos(22°) =
24. tan(81°) + √31 =
25. cos(6°) + 3 * 24 =
26. tan(49°) + √28 =
27. tan(27°) + 48 - 16 =
28. cos(40°) =
29. sin(43°) + 5 - 9 + 55 - 90 + 71 =
30. sin(67°) + (1)² =

@ -0,0 +1,51 @@
1. (4)² + 42 =
2. √4 + 1 =
3. √30 + 51 - 84 =
4. √99 + 60 =
5. √22 + 97 =
6. (6)² + ((12) + 10 * 78 + 17 + 9) =
7. (3)² + 5 =
8. √28 + 91 =
9. (2)² + 11 / 57 - 87 =
10. (10)² + 55 * 97 =
11. (8)² + (74) / 18 - 46 + 12 =
12. (9)² + 96 =
13. √46 + 48 =
14. (2)² + 71 * 83 =
15. √42 + (44 / 91 + 51) =
16. √51 + 36 - 57 =
17. (3)² + 88 =
18. (3)² + 80 =
19. √87 + 96 * 45 =
20. (9)² + 40 =
21. (6)² + ((67 * 20) + 91) + 85 =
22. (8)² + ((24 * 46) / 40) / 5 * 100 =
23. √19 + 19 =
24. √95 + 17 + 91 / 27 =
25. (7)² + 31 =
26. √100 + (39) * 72 - 50 =

@ -0,0 +1,29 @@
1. 27 =
2. (61) + 90 / 15 - 25 =
3. (42 / 28 - 92 - 53) - 13 =
4. 79 * 71 / 94 =
5. 66 - 24 + 85 - 52 =
6. 95 =
7. 70 * 18 =
8. (88 * 26 - 7 * 88 - 95) =
9. (60 - 1 - 34) =
10. 86 =
11. 2 - 90 - 21 =
12. 6 =
13. 87 =
14. (40 - 14 + 6 + 78 - 76) =
15. 91 - 4 * 78 + 19 =

@ -0,0 +1,124 @@
import interfaces.LoginSystemInterface;
import interfaces.FileManagerInterface;
import models.User;
import models.DifficultyLevel;
import factories.ServiceFactory;
import services.QuestionGenerator;
import java.util.Scanner;
public class Application {
private Scanner scanner;
private LoginSystemInterface loginSystem;
private QuestionGenerator generator;
private FileManagerInterface fileManager;
public Application() {
this.scanner = new Scanner(System.in);
this.loginSystem = ServiceFactory.createLoginSystem();
this.generator = new QuestionGenerator();
this.fileManager = ServiceFactory.createFileManager();
}
public void start() {
while (true) {
User currentUser = handleLogin();
if (currentUser != null) {
handleUserSession(currentUser);
}
}
}
private User handleLogin() {
while (true) {
System.out.print("请输入用户名和密码(用空格隔开):");
String input = scanner.nextLine().trim();
String[] parts = input.split("\\s+");
if (parts.length != 2) {
System.out.println("请输入正确的用户名、密码");
continue;
}
User user = loginSystem.login(parts[0], parts[1]);
if (user != null) {
System.out.println("当前选择为" + user.getLevel().getDisplayName() + "出题");
return user;
} else {
System.out.println("请输入正确的用户名、密码");
}
}
}
private void handleUserSession(User user) {
while (true) {
showPrompt(user);
String command = scanner.nextLine().trim();
if (processCommand(command, user)) {
break;
}
}
}
private void showPrompt(User user) {
System.out.println("准备生成" + user.getLevel().getDisplayName() +
"数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
}
private boolean processCommand(String command, User user) {
// 检查退出命令
if (command.equals("-1")) {
System.out.println("退出当前用户,重新登录...");
return true;
}
// 检查切换命令
if (command.startsWith("切换为")) {
return handleSwitchLevel(command, user);
}
// 处理生成题目命令
handleGenerateQuestions(command, user);
return false;
}
private boolean handleSwitchLevel(String command, User user) {
String levelName = command.substring(3).trim();
DifficultyLevel newLevel = loginSystem.switchLevel(levelName);
if (newLevel != null) {
user.setLevel(newLevel);
// 这里不再显示提示信息,让主循环重新显示
}
return false; // 继续当前会话
}
private void handleGenerateQuestions(String command, User user) {
try {
int count = Integer.parseInt(command);
if (count < 10 || count > 30) {
System.out.println("题目数量应在10-30之间");
return;
}
generateAndSaveQuestions(user, count);
} catch (NumberFormatException e) {
System.out.println("请输入有效的数字");
}
}
private void generateAndSaveQuestions(User user, int count) {
String[] questions = generator.generateQuestions(user.getLevel(), count, user.getUsername());
if (questions == null) {
System.out.println("生成题目失败,可能存在重复题目");
return;
}
boolean success = fileManager.saveQuestions(user, questions);
if (success) {
System.out.println("题目生成成功!");
} else {
System.out.println("文件保存失败");
}
}
}

@ -1,85 +1,6 @@
import interfaces.LoginSystemInterface;
import interfaces.FileManagerInterface;
import models.User;
import models.DifficultyLevel;
import factories.ServiceFactory;
import services.QuestionGenerator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
LoginSystemInterface loginSystem = ServiceFactory.createLoginSystem();
QuestionGenerator generator = new QuestionGenerator();
FileManagerInterface fileManager = ServiceFactory.createFileManager();
while (true) {
System.out.print("请输入用户名和密码(用空格隔开):");
String input = scanner.nextLine().trim();
String[] parts = input.split("\\s+");
if (parts.length != 2) {
System.out.println("请输入正确的用户名、密码");
continue;
}
User currentUser = loginSystem.login(parts[0], parts[1]);
if (currentUser == null) {
System.out.println("请输入正确的用户名、密码");
continue;
}
System.out.println("登录成功!当前选择为" + currentUser.getLevel().getDisplayName() + "出题");
while (true) {
// 修复:使用单行字符串,避免拼接问题
System.out.println("准备生成" + currentUser.getLevel().getDisplayName() +
"数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
String command = scanner.nextLine().trim();
if (command.startsWith("切换为")) {
String levelName = command.substring(3).trim();
DifficultyLevel newLevel = loginSystem.switchLevel(levelName);
if (newLevel != null) {
currentUser.setLevel(newLevel);
System.out.println("当前选择为" + currentUser.getLevel().getDisplayName() +
"出题");
continue;
}
}
if (command.equals("-1")) {
System.out.println("退出当前用户,重新登录...");
break;
}
try {
int count = Integer.parseInt(command);
if (count < 10 || count > 30) {
System.out.println("题目数量应在10-30之间");
continue;
}
String[] questions = generator.generateQuestions(currentUser.getLevel(), count,
currentUser.getUsername());
if (questions == null) {
System.out.println("生成题目失败,可能存在重复题目");
continue;
}
boolean success = fileManager.saveQuestions(currentUser, questions);
if (success) {
System.out.println("题目生成成功!");
} else {
System.out.println("文件保存失败");
}
} catch (NumberFormatException e) {
System.out.println("请输入有效的数字");
}
}
}
Application app = new Application();
app.start();
}
}

@ -8,27 +8,28 @@ public class MathQuestion implements QuestionInterface {
private String questionText;
private DifficultyLevel difficulty;
private Random random;
private boolean isValid;
public MathQuestion(DifficultyLevel difficulty) {
this.difficulty = difficulty;
this.random = new Random();
this.questionText = generateQuestion();
this.isValid = validateQuestion();
}
@Override
public String generateQuestion() {
int operandCount = random.nextInt(5) + 1;
StringBuilder question = new StringBuilder();
switch (difficulty) {
case PRIMARY:
question.append(generatePrimaryQuestion(operandCount));
question.append(generatePrimaryQuestion());
break;
case JUNIOR:
question.append(generateJuniorQuestion(operandCount));
question.append(generateJuniorQuestion());
break;
case SENIOR:
question.append(generateSeniorQuestion(operandCount));
question.append(generateSeniorQuestion());
break;
}
@ -38,7 +39,67 @@ public class MathQuestion implements QuestionInterface {
@Override
public boolean isValid() {
return questionText != null && !questionText.trim().isEmpty();
return isValid;
}
private boolean validateQuestion() {
if (questionText == null || questionText.trim().isEmpty()) {
return false;
}
// 检查括号是否匹配
if (!isParenthesesBalanced(questionText)) {
return false;
}
// 检查是否有不合理的括号位置(如运算符后面直接跟右括号)
if (hasInvalidParentheses(questionText)) {
return false;
}
// 小学题目必须至少有2个操作数
if (difficulty == DifficultyLevel.PRIMARY) {
String expr = questionText.replace(" = ", "");
// 更严格的验证:必须包含至少一个运算符
boolean hasOperator = expr.contains("+") || expr.contains("-") ||
expr.contains("*") || expr.contains("/");
// 并且不能是单个数字的情况
boolean isSingleNumber = expr.matches("^\\d+$") ||
expr.matches("^\\(\\d+\\)$") ||
expr.matches("^√\\d+$") ||
expr.matches("^\\(\\d+\\)²$");
return hasOperator && !isSingleNumber;
}
return true;
}
private boolean isParenthesesBalanced(String expression) {
int balance = 0;
for (char c : expression.toCharArray()) {
if (c == '(') balance++;
if (c == ')') balance--;
if (balance < 0) return false; // 右括号出现在左括号之前
}
return balance == 0;
}
private boolean hasInvalidParentheses(String expression) {
// 检查是否有不合理的括号模式
String[] invalidPatterns = {
"\\(\\s*[+\\-*/]", // 左括号后直接跟运算符
"[+\\-*/]\\s*\\)", // 运算符后直接跟右括号
"\\(\\s*\\)", // 空括号
"\\d\\s*\\(", // 数字后直接跟左括号(应该是运算符后跟左括号)
"\\)\\s*\\d" // 右括号后直接跟数字(应该是运算符后跟数字)
};
for (String pattern : invalidPatterns) {
if (expression.matches(".*" + pattern + ".*")) {
return true;
}
}
return false;
}
@Override
@ -51,36 +112,127 @@ public class MathQuestion implements QuestionInterface {
return difficulty;
}
private String generatePrimaryQuestion(int operandCount) {
private String generatePrimaryQuestion() {
// 小学题目确保至少有2个操作数2-5个
int operandCount = random.nextInt(4) + 2; // 2-5个操作数
String[] operators = {"+", "-", "*", "/"};
StringBuilder question = new StringBuilder();
// 生成所有操作数
int[] operands = new int[operandCount];
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
question.append(" ").append(operators[random.nextInt(operators.length)]).append(" ");
}
question.append(random.nextInt(100) + 1);
operands[i] = random.nextInt(100) + 1;
}
if (operandCount > 2 && random.nextDouble() < 0.3) {
question.insert(0, "(").append(")");
}
// 构建基础表达式(不带括号)
question.append(operands[0]);
for (int i = 1; i < operandCount; i++) {
question.append(" ").append(operators[random.nextInt(operators.length)]).append(" ");
question.append(operands[i]);
}
// 只在有3个及以上操作数时考虑添加括号且概率降低
if (operandCount >= 3 && random.nextDouble() < 0.3) {
return addProperParentheses(question.toString());
}
return question.toString();
}
private String generateJuniorQuestion(int operandCount) {
String question = generatePrimaryQuestion(operandCount);
if (random.nextBoolean()) {
return "√" + (random.nextInt(100) + 1) + " + " + question;
} else {
return "(" + (random.nextInt(10) + 1) + ")² + " + question;
private String addProperParentheses(String expression) {
String[] parts = expression.split(" ");
// 只在合适的运算符位置添加括号
for (int attempt = 0; attempt < 10; attempt++) {
int opIndex = random.nextInt(parts.length / 2) * 2 + 1; // 随机选择一个运算符位置
if (opIndex >= 1 && opIndex < parts.length - 2) {
// 构建带括号的表达式
StringBuilder newExpr = new StringBuilder();
// 添加括号前的部分
for (int i = 0; i < opIndex - 1; i++) {
newExpr.append(parts[i]).append(" ");
}
// 添加左括号和第一个操作数
newExpr.append("(").append(parts[opIndex - 1]).append(" ");
// 添加运算符和第二个操作数
newExpr.append(parts[opIndex]).append(" ").append(parts[opIndex + 1]);
// 添加右括号
newExpr.append(")");
// 添加剩余部分
for (int i = opIndex + 2; i < parts.length; i++) {
newExpr.append(" ").append(parts[i]);
}
String result = newExpr.toString();
// 验证生成的表达式是否合理
if (!hasInvalidParentheses(result) && isParenthesesBalanced(result)) {
return result;
}
}
}
// 如果多次尝试都失败,返回原表达式(不带括号)
return expression;
}
private String generateJuniorQuestion() {
// 初中题目可以有1个操作数涉及平方、开根号
int choice = random.nextInt(4);
switch (choice) {
case 0:
// 单个操作数:开根号
return "√" + (random.nextInt(100) + 1);
case 1:
// 单个操作数:平方
return "(" + (random.nextInt(10) + 1) + ")²";
case 2:
// 多个操作数:基础运算 + 平方/开根号
String baseQuestion = generatePrimaryQuestion();
if (random.nextBoolean()) {
return "√" + (random.nextInt(100) + 1) + " + " + baseQuestion;
} else {
return "(" + (random.nextInt(10) + 1) + ")² + " + baseQuestion;
}
case 3:
// 纯基础运算(多个操作数)
return generatePrimaryQuestion();
default:
return generatePrimaryQuestion();
}
}
private String generateSeniorQuestion(int operandCount) {
String question = generatePrimaryQuestion(operandCount);
private String generateSeniorQuestion() {
// 高中题目可以有1个操作数涉及三角函数
int choice = random.nextInt(4);
String[] trigFunctions = {"sin", "cos", "tan"};
return trigFunctions[random.nextInt(trigFunctions.length)] +
"(" + (random.nextInt(90) + 1) + "°) + " + question;
switch (choice) {
case 0:
// 单个操作数:三角函数
return trigFunctions[random.nextInt(trigFunctions.length)] +
"(" + (random.nextInt(90) + 1) + "°)";
case 1:
// 三角函数 + 基础运算
String baseQuestion = generatePrimaryQuestion();
return trigFunctions[random.nextInt(trigFunctions.length)] +
"(" + (random.nextInt(90) + 1) + "°) + " + baseQuestion;
case 2:
// 复杂组合:三角函数 + 平方/开根号 + 基础运算
String complexBase = generateJuniorQuestion();
return trigFunctions[random.nextInt(trigFunctions.length)] +
"(" + (random.nextInt(90) + 1) + "°) + " + complexBase;
case 3:
// 纯基础运算(多个操作数)
return generatePrimaryQuestion();
default:
return generatePrimaryQuestion();
}
}
}

Binary file not shown.
Loading…
Cancel
Save