diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..7bc07ec
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Environment-dependent path to Maven home directory
+/mavenHomeManager.xml
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/google-java-format.xml b/.idea/google-java-format.xml
new file mode 100644
index 0000000..8b57f45
--- /dev/null
+++ b/.idea/google-java-format.xml
@@ -0,0 +1,6 @@
+
+
随机生成包含加、减、乘、除运算的表达式,保证符合题目要求。 + */ public class ElementaryQuestionStrategy implements QuestionStrategy { - private final Random random = new Random(); - private final String[] operators = {"+", "-", "*", "/"}; - - @Override - public String generateQuestion() { - int operandsCount = random.nextInt(4) + 2; // 操作数 2~5 - StringBuilder sb = new StringBuilder(); - - // 生成运算符序列 - String[] chosenOps = generateOperators(operandsCount); - - // 随机决定括号 - int[] parentheses = decideParentheses(operandsCount, chosenOps); - - // 拼接表达式 - buildExpression(sb, operandsCount, chosenOps, parentheses); - - return sb.toString(); - } - - /** - * 生成运算符序列 - * 根据操作数数量,随机生成对应数量的运算符数组 - * - * @param operandsCount 操作数数量 - * @return 随机生成的运算符数组,长度为操作数数量-1 - */ - private String[] generateOperators(int operandsCount) { - String[] chosenOps = new String[operandsCount - 1]; - for (int i = 0; i < operandsCount - 1; i++) { - chosenOps[i] = operators[random.nextInt(operators.length)]; - } - return chosenOps; - } - - /** - * 决定是否需要括号,并返回括号的起始和结束位置 - * 对于3个及以上操作数,随机决定是否添加括号,并检查括号是否有效 - * - * @param operandsCount 操作数数量 - * @param chosenOps 运算符数组 - * @return 包含开括号和闭括号位置的数组,格式为[openParenIndex, closeParenIndex],-1表示不添加括号 - */ - private int[] decideParentheses(int operandsCount, String[] chosenOps) { - int openParenIndex = -1; - int closeParenIndex = -1; - - if (operandsCount > 2 && random.nextBoolean()) { - openParenIndex = random.nextInt(operandsCount - 1); - closeParenIndex = random.nextInt(operandsCount - openParenIndex - 1) + openParenIndex + 1; - - // 如果括号包裹整个表达式,则不需要括号 - if (openParenIndex == 0 && closeParenIndex == operandsCount - 1) { - openParenIndex = -1; - closeParenIndex = -1; - } else { - // 检查括号内的运算符优先级是否相同,如果相同则不需要括号 - boolean samePrecedence = checkPrecedenceEquality(chosenOps, openParenIndex, closeParenIndex); - if (samePrecedence) { - openParenIndex = -1; - closeParenIndex = -1; - } - } - } - return new int[]{openParenIndex, closeParenIndex}; - } - - /** - * 判断括号内的运算符优先级是否相同 - * 用于决定是否需要添加括号(如果优先级都相同,则括号是冗余的) - * - * @param chosenOps 运算符数组 - * @param openParenIndex 开括号位置 - * @param closeParenIndex 闭括号位置 - * @return 如果括号内所有运算符优先级相同则返回true,否则返回false - */ - private boolean checkPrecedenceEquality(String[] chosenOps, int openParenIndex, int closeParenIndex) { - int precedence = getPrecedence(chosenOps[openParenIndex]); - for (int i = openParenIndex; i < closeParenIndex; i++) { - if (getPrecedence(chosenOps[i]) != precedence) { - return false; - } - } - return true; - } - - /** - * 构建数学表达式 - * 根据操作数、运算符和括号位置,拼接完整的数学表达式 - * - * @param sb StringBuilder对象,用于构建表达式 - * @param operandsCount 操作数数量 - * @param chosenOps 运算符数组 - * @param parentheses 括号位置数组,格式为[openParenIndex, closeParenIndex] - */ - private void buildExpression(StringBuilder sb, int operandsCount, String[] chosenOps, int[] parentheses) { - int prevNum = random.nextInt(100) + 1; - int openParenIndex = parentheses[0]; - int closeParenIndex = parentheses[1]; - - // 处理第一个操作数可能的开括号 - if (openParenIndex == 0) sb.append("("); - sb.append(prevNum); - - // 处理最后一个操作数可能的闭括号 - if (closeParenIndex == operandsCount - 1) sb.append(")"); - - // 构建剩余的操作数和运算符 - for (int i = 1; i < operandsCount; i++) { - String op = chosenOps[i - 1]; - sb.append(" ").append(op).append(" "); - - // 根据运算符生成下一个操作数 - int num = generateOperand(op, prevNum); - - // 添加括号(如果需要) - if (i == openParenIndex) sb.append("("); - sb.append(num); - if (i == closeParenIndex) sb.append(")"); - - prevNum = num; // 更新上一个数字,供下一轮计算使用 - } - } - - /** - * 生成每个操作数 - * 确保生成的操作数符合题目要求,特别是减法不会导致负数结果 - * - * @param op 当前运算符 - * @param prevNum 前一个操作数的值 - * @return 生成的操作数 - */ - private int generateOperand(String op, int prevNum) { - int num = random.nextInt(100) + 1; // 默认生成1-100之间的随机数 - - // 如果是减法运算符,确保不会出现负数结果 - if (op.equals("-") && num > prevNum) { - num = random.nextInt(prevNum) + 1; // 保证 num <= prevNum,避免负数结果 - } - return num; - } - - private int getPrecedence(String op) { - if (op.equals("+") || op.equals("-")) return 1; - if (op.equals("*") || op.equals("/")) return 2; - return 0; + private static final String[] OPERATORS = {"+", "-", "*", "/"}; + private final Random random = new Random(); + + @Override + public String generateQuestion() { + int operandsCount = random.nextInt(4) + 2; // 操作数数量:2~5 + StringBuilder sb = new StringBuilder(); + + // 生成运算符序列 + String[] chosenOps = generateOperators(operandsCount); + + // 随机决定括号位置 + int[] parentheses = decideParentheses(operandsCount, chosenOps); + + // 拼接表达式 + buildExpression(sb, operandsCount, chosenOps, parentheses); + + return sb.toString(); + } + + /** + * 根据操作数数量,随机生成运算符数组。 + * + * @param operandsCount 操作数数量 + * @return 随机生成的运算符数组,长度为操作数数量 - 1 + */ + private String[] generateOperators(int operandsCount) { + String[] chosenOps = new String[operandsCount - 1]; + for (int i = 0; i < operandsCount - 1; i++) { + chosenOps[i] = OPERATORS[random.nextInt(OPERATORS.length)]; } + return chosenOps; + } + + /** + * 构建数学表达式。 + * + * @param sb StringBuilder 对象 + * @param operandsCount 操作数数量 + * @param chosenOps 运算符数组 + * @param parentheses 括号位置数组 [openParenIndex, closeParenIndex] + */ + private void buildExpression( + StringBuilder sb, int operandsCount, String[] chosenOps, int[] parentheses) { + int openParenIndex = parentheses[0]; + int closeParenIndex = parentheses[1]; + + // 生成第一个操作数 + int prevNum = random.nextInt(100) + 1; + + // 如果开括号在第一个操作数之前 + if (openParenIndex == 0) { + sb.append("("); + } + sb.append(prevNum); + + // 如果闭括号在第一个操作数之后(即只包含第一个操作数) + if (closeParenIndex == 0) { + sb.append(")"); + } + + for (int i = 1; i < operandsCount; i++) { + String op = chosenOps[i - 1]; + sb.append(" ").append(op).append(" "); + + int num = generateOperand(op, prevNum); + + // 如果开括号在当前操作数之前 + if (i == openParenIndex) { + sb.append("("); + } + + sb.append(num); + + // 如果闭括号在当前操作数之后 + if (i == closeParenIndex) { + sb.append(")"); + } + + prevNum = num; + } + + // 确保括号正确闭合(安全措施) + String expression = sb.toString(); + int openCount = countChar(expression, '('); + int closeCount = countChar(expression, ')'); + + // 如果括号不匹配,重新生成表达式 + if (openCount != closeCount) { + sb.setLength(0); // 清空 StringBuilder + // 递归调用生成新的表达式(或者去掉所有括号) + buildExpressionWithoutParentheses(sb, operandsCount, chosenOps); + } + } + + /** + * 构建没有括号的表达式(备用方法)。 + */ + private void buildExpressionWithoutParentheses( + StringBuilder sb, int operandsCount, String[] chosenOps) { + int prevNum = random.nextInt(100) + 1; + sb.append(prevNum); + + for (int i = 1; i < operandsCount; i++) { + String op = chosenOps[i - 1]; + sb.append(" ").append(op).append(" "); + + int num = generateOperand(op, prevNum); + sb.append(num); + prevNum = num; + } + } + + /** + * 计算字符串中特定字符的数量。 + * + * @param str 输入字符串 + * @param ch 要统计的字符 + * @return 字符出现次数 + */ + private int countChar(String str, char ch) { + int count = 0; + for (int i = 0; i < str.length(); i++) { + if (str.charAt(i) == ch) { + count++; + } + } + return count; + } + + /** + * 决定是否需要括号,并返回括号位置。 改进版本:确保括号位置有效。 + * + * @param operandsCount 操作数数量 + * @param chosenOps 运算符数组 + * @return 括号位置数组 [openParenIndex, closeParenIndex] + */ + private int[] decideParentheses(int operandsCount, String[] chosenOps) { + if (operandsCount <= 2) { + return new int[] {-1, -1}; // 操作数太少,不需要括号 + } + + if (!random.nextBoolean()) { + return new int[] {-1, -1}; // 随机决定不加括号 + } + + // 生成有效的括号位置 + int openParenIndex = random.nextInt(operandsCount - 1); + int closeParenIndex = + random.nextInt(operandsCount - openParenIndex - 1) + openParenIndex + 1; + + // 确保至少包含 2 个操作数 + if (closeParenIndex - openParenIndex < 2) { + closeParenIndex = openParenIndex + 1; + } + + // 如果括号包裹整个表达式,则不需要括号 + if (openParenIndex == 0 && closeParenIndex == operandsCount - 1) { + return new int[] {-1, -1}; + } + + // 检查括号内运算符是否同一优先级,如果是则不需要括号 + boolean samePrecedence = checkPrecedenceEquality(chosenOps, openParenIndex, closeParenIndex); + if (samePrecedence) { + return new int[] {-1, -1}; + } + + return new int[] {openParenIndex, closeParenIndex}; + } + + /** + * 判断括号内的运算符是否具有相同优先级。 + * + * @param chosenOps 运算符数组 + * @param openParenIndex 开括号位置 + * @param closeParenIndex 闭括号位置 + * @return true 如果括号内运算符优先级相同 + */ + private boolean checkPrecedenceEquality( + String[] chosenOps, int openParenIndex, int closeParenIndex) { + int precedence = getPrecedence(chosenOps[openParenIndex]); + for (int i = openParenIndex; i < closeParenIndex; i++) { + if (getPrecedence(chosenOps[i]) != precedence) { + return false; + } + } + return true; + } + + /** + * 根据运算符生成操作数。 + * + *
特别处理减法,确保不会出现负数结果。
+ *
+ * @param op 当前运算符
+ * @param prevNum 上一个操作数
+ * @return 生成的操作数
+ */
+ private int generateOperand(String op, int prevNum) {
+ int num = random.nextInt(100) + 1;
+ if (op.equals("-") && num > prevNum) {
+ num = random.nextInt(prevNum) + 1;
+ }
+ return num;
+ }
+
+ /**
+ * 获取运算符的优先级。
+ *
+ * @param op 运算符
+ * @return 优先级数值
+ */
+ private int getPrecedence(String op) {
+ if (op.equals("+") || op.equals("-")) {
+ return 1;
+ }
+ if (op.equals("*") || op.equals("/")) {
+ return 2;
+ }
+ return 0;
+ }
}
diff --git a/src/FileUtils.java b/src/FileUtils.java
index a24ab81..8c89b9b 100644
--- a/src/FileUtils.java
+++ b/src/FileUtils.java
@@ -1,64 +1,97 @@
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
/**
- * 文件工具类:生成文件名、保存题目、读取已有题目
+ * 文件工具类:用于生成文件名、保存题目、读取已有题目。
*/
public class FileUtils {
- // 生成文件名
- public static String generateFileName() {
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
- return sdf.format(new Date()) + ".txt";
- }
+ /**
+ * 生成基于时间戳的文件名。
+ *
+ * @return 文件名,格式为 yyyy-MM-dd-HH-mm-ss.txt
+ */
+ public static String generateFileName() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
+ return sdf.format(new Date()) + ".txt";
+ }
- // 保存题目到用户文件夹
- public static void saveQuestionsToFile(String userId, String fileName, List
+ * 随机生成包含基本运算和三角函数的数学表达式。
+ */
public class HighSchoolQuestionStrategy implements QuestionStrategy {
- private final Random random = new Random();
- private final String[] basicOps = {"+", "-", "*", "/"};
- private final String[] trigFuncs = {"sin", "cos", "tan"};
-
- @Override
- public String generateQuestion() {
- // 随机操作数个数 2-5
- int operandsCount = random.nextInt(4) + 2;
- StringBuilder sb = new StringBuilder();
- boolean hasTrig = false;
-
- for (int i = 0; i < operandsCount; i++) {
- int num = random.nextInt(100) + 1;
-
- // 每个操作数有概率加三角函数
- if (random.nextBoolean()) {
- String func = trigFuncs[random.nextInt(trigFuncs.length)];
- sb.append(func).append("(").append(num).append(")");
- hasTrig = true;
- } else {
- sb.append(num);
- }
-
- if (i != operandsCount - 1) {
- String op = basicOps[random.nextInt(basicOps.length)];
- sb.append(" ").append(op).append(" ");
- }
- }
-
- // 确保至少一个三角函数
- if (!hasTrig) {
- String func = trigFuncs[random.nextInt(trigFuncs.length)];
- int num = random.nextInt(100) + 1;
- return func + "(" + num + ") + " + sb.toString();
- }
-
- return sb.toString();
+ private static final String[] BASIC_OPS = {"+", "-", "*", "/"};
+ private static final String[] TRIG_FUNCS = {"sin", "cos", "tan"};
+
+ private final Random random = new Random();
+
+ @Override
+ public String generateQuestion() {
+ // 随机操作数个数:2~5
+ int operandsCount = random.nextInt(4) + 2;
+ StringBuilder sb = new StringBuilder();
+ boolean hasTrig = false;
+
+ for (int i = 0; i < operandsCount; i++) {
+ int num = random.nextInt(100) + 1;
+
+ // 每个操作数有概率带三角函数
+ if (random.nextBoolean()) {
+ String func = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)];
+ sb.append(func).append("(").append(num).append(")");
+ hasTrig = true;
+ } else {
+ sb.append(num);
+ }
+
+ if (i != operandsCount - 1) {
+ String op = BASIC_OPS[random.nextInt(BASIC_OPS.length)];
+ sb.append(" ").append(op).append(" ");
+ }
+ }
+
+ // 确保至少包含一个三角函数
+ if (!hasTrig) {
+ String func = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)];
+ int num = random.nextInt(100) + 1;
+ return func + "(" + num + ") + " + sb;
}
+
+ return sb.toString();
+ }
}
diff --git a/src/Main.java b/src/Main.java
index 3a5deeb..57b714e 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -2,99 +2,121 @@ import java.io.IOException;
import java.util.Scanner;
/**
- * 程序入口类,负责处理登录和题目生成。
+ * 程序入口类。负责用户登录和题目生成。
*/
public class Main {
- public static void main(String[] args) throws IOException {
- Scanner scanner = new Scanner(System.in);
- User currentUser = null;
+ /**
+ * 程序入口。
+ *
+ * @param args 命令行参数
+ * @throws IOException 文件写入失败时抛出
+ */
+ public static void main(String[] args) throws IOException {
+ Scanner scanner = new Scanner(System.in);
+ User currentUser = null;
+ System.out.println("-----------------欢迎来到中小学数学卷子自动生成程序-----------------");
- // 登录流程
- while (true) {
- while (currentUser == null) {
- System.out.print("请输入用户名和密码,用空格分隔:");
- String username = scanner.next();
- String password = scanner.next();
+ // 登录流程
+ while (true) {
+ while (currentUser == null) {
+ System.out.print("请输入用户名和密码,用空格分隔:");
+ String username = scanner.next();
+ String password = scanner.next();
- currentUser = User.login(username, password);
+ currentUser = User.login(username, password);
- if (currentUser == null) {
- System.out.println("请输入正确的用户名、密码");
- } else {
- clearScreen(); //登录成功清屏
- System.out.println("当前选择为 " + currentUser.getRole() + " 出题");
- }
- }
+ if (currentUser == null) {
+ System.out.println("请输入正确的用户名、密码");
+ } else {
+ clearScreen(); // 登录成功清屏
+ System.out.println("当前选择为 " + currentUser.getRole() + " 出题");
+ }
+ }
- // 每次登录后初始化当前出题类型(账号默认类型)
- String currentRole = currentUser.getRole();
+ // 每次登录后初始化当前出题类型(账号默认类型)
+ String currentRole = currentUser.getRole();
- // 题目生成流程
- while (true) {
- System.out.println("准备生成 " + currentRole
- + " 数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):");
+ // 题目生成流程
+ while (true) {
+ System.out.println(
+ "准备生成 " + currentRole
+ + " 数学题目,请输入生成题目数量(输入 -1 将退出当前用户,重新登录):");
- String input = scanner.next();
+ String input = scanner.next();
- // 退出登录
- if (input.equals("-1")) {
- currentUser = null;
- clearScreen();
- System.out.println("已退出当前用户,重新登录...");
- break;
- }
+ // 退出登录
+ if (input.equals("-1")) {
+ currentUser = null;
+ clearScreen();
+ System.out.println("已退出当前用户,重新登录...");
+ break;
+ }
- // 检测切换命令
- if (input.startsWith("切换为")) {
- String newRole = input.substring(3).trim();
- if (!newRole.equals("小学") && !newRole.equals("初中") && !newRole.equals("高中")) {
- System.out.println("请输入小学、初中和高中三个选项中的一个"+"(当前类型为"+currentRole+")");
- continue;
- }
- currentRole = newRole;
- clearScreen();
- System.out.println("系统提示:准备生成 " + currentRole + " 数学题目,请输入生成题目数量");
- continue;
- }
+ // 检测切换命令
+ if (input.startsWith("切换为")) {
+ String newRole = input.substring(3).trim();
+ if (!newRole.equals("小学")
+ && !newRole.equals("初中")
+ && !newRole.equals("高中")) {
+ System.out.println(
+ "请输入小学、初中和高中三个选项中的一个"
+ + " (当前类型为 " + currentRole + ")");
+ continue;
+ }
+ currentRole = newRole;
+ clearScreen();
+ System.out.println(
+ "系统提示:准备生成 " + currentRole + " 数学题目,请输入生成题目数量");
+ continue;
+ }
- // 输入题目数量
- int questionCount;
- try {
- questionCount = Integer.parseInt(input);
- } catch (NumberFormatException e) {
- System.out.println("请输入有效的数字或使用“切换为小学/初中/高中”命令"+"(当前类型为"+currentRole+")");
- continue;
- }
+ // 输入题目数量
+ int questionCount;
+ try {
+ questionCount = Integer.parseInt(input);
+ } catch (NumberFormatException e) {
+ System.out.println(
+ "请输入有效的数字或使用“切换为小学/初中/高中”命令"
+ + " (当前类型为 " + currentRole + ")");
+ continue;
+ }
- if (questionCount < 10 || questionCount > 30) {
- System.out.println("请输入有效的题目数量 (10-30) 或 -1 退出");
- continue;
- }
+ if (questionCount < 10 || questionCount > 30) {
+ System.out.println("请输入有效的题目数量 (10-30) 或 -1 退出");
+ continue;
+ }
- clearScreen();
+ clearScreen();
- // 把 currentRole 传给 QuestionGenerator
- QuestionGenerator generator = new QuestionGenerator(currentUser, currentRole);
- generator.generateQuestions(questionCount);
- System.out.println("题目已生成并保存!\n");
- }
- }
+ // 生成题目
+ QuestionGenerator generator =
+ new QuestionGenerator(currentUser, currentRole);
+ generator.generateQuestions(questionCount);
+ System.out.println("题目已生成并保存!\n");
+ }
}
+ }
- /**
- * 清屏方法
- */
- public static void clearScreen() {
- try {
- if (System.getProperty("os.name").contains("Windows")) {
- new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
- } else {
- new ProcessBuilder("clear").inheritIO().start().waitFor();
- }
- } catch (Exception e) {
- for (int i = 0; i < 50; i++) {
- System.out.println();
- }
- }
+ /**
+ * 清屏方法。
+ */
+ public static void clearScreen() {
+ try {
+ if (System.getProperty("os.name").contains("Windows")) {
+ new ProcessBuilder("cmd", "/c", "cls")
+ .inheritIO()
+ .start()
+ .waitFor();
+ } else {
+ new ProcessBuilder("clear")
+ .inheritIO()
+ .start()
+ .waitFor();
+ }
+ } catch (Exception e) {
+ for (int i = 0; i < 50; i++) {
+ System.out.println();
+ }
}
+ }
}
diff --git a/src/MathQuestion.java b/src/MathQuestion.java
index c727b28..356bbce 100644
--- a/src/MathQuestion.java
+++ b/src/MathQuestion.java
@@ -1,21 +1,36 @@
/**
- * 数学题目类,表示每一道数学题。
+ * 数学题目类。表示每一道数学题。
*/
public class MathQuestion {
- private int questionNumber;
- private String questionText;
+ private final int questionNumber;
+ private final String questionText;
- // 构造方法
- public MathQuestion(int questionNumber, String questionText) {
- this.questionNumber = questionNumber;
- this.questionText = questionText;
- }
+ /**
+ * 构造方法。
+ *
+ * @param questionNumber 题号
+ * @param questionText 题目内容
+ */
+ public MathQuestion(int questionNumber, String questionText) {
+ this.questionNumber = questionNumber;
+ this.questionText = questionText;
+ }
- public int getQuestionNumber() {
- return questionNumber;
- }
+ /**
+ * 获取题号。
+ *
+ * @return 题号
+ */
+ public int getQuestionNumber() {
+ return questionNumber;
+ }
- public String getQuestionText() {
- return questionText;
- }
+ /**
+ * 获取题目内容。
+ *
+ * @return 题目内容
+ */
+ public String getQuestionText() {
+ return questionText;
+ }
}
diff --git a/src/MiddleSchoolQuestionStrategy.java b/src/MiddleSchoolQuestionStrategy.java
index aa4c595..629cabe 100644
--- a/src/MiddleSchoolQuestionStrategy.java
+++ b/src/MiddleSchoolQuestionStrategy.java
@@ -1,47 +1,50 @@
import java.util.Random;
+/**
+ * 初中数学题策略实现类。用于生成包含平方和根号的数学题目。
+ */
public class MiddleSchoolQuestionStrategy implements QuestionStrategy {
- private final Random random = new Random();
- private final String[] basicOps = {"+", "-", "*", "/"}; // 基本运算符
+ private final Random random = new Random();
+ private final String[] basicOps = {"+", "-", "*", "/"};
- @Override
- public String generateQuestion() {
- // 随机操作数个数 2-5
- int operandsCount = random.nextInt(4) + 2;
- StringBuilder sb = new StringBuilder();
- boolean hasSquareOrRoot = false;
+ @Override
+ public String generateQuestion() {
+ // 随机操作数个数 2-5。
+ int operandsCount = random.nextInt(4) + 2;
+ StringBuilder sb = new StringBuilder();
+ boolean hasSquareOrRoot = false;
- // 生成运算符和操作数
- for (int i = 0; i < operandsCount; i++) {
- int num = random.nextInt(100) + 1; // 生成1-100之间的数字
+ // 生成运算符和操作数。
+ for (int i = 0; i < operandsCount; i++) {
+ int num = random.nextInt(100) + 1; // 生成 1-100 之间的数字。
- // 每个操作数有概率平方或开根号
- if (random.nextBoolean()) {
- if (random.nextBoolean()) {
- sb.append("(").append(num).append(")^2");
- hasSquareOrRoot = true; // 标记是否已经使用了平方或根号
- } else {
- // 确保根号下的数为正
- int rootNumber = random.nextInt(100) + 1; // 始终生成正整数
- sb.append("√(").append(rootNumber).append(")");
- hasSquareOrRoot = true; // 标记是否已经使用了平方或根号
- }
- } else {
- sb.append(num); // 普通数字
- }
-
- // 添加运算符(除最后一个操作数外)
- if (i != operandsCount - 1) {
- String op = basicOps[random.nextInt(basicOps.length)];
- sb.append(" ").append(op).append(" ");
- }
- }
- // 如果没有平方或根号,强制添加一个
- if (!hasSquareOrRoot) {
- // 确保根号下的数为正
- int rootNumber = random.nextInt(100) + 1; // 始终生成正整数
- sb.append(" + √(").append(rootNumber).append(")");
+ // 每个操作数有概率平方或开根号。
+ if (random.nextBoolean()) {
+ if (random.nextBoolean()) {
+ sb.append("(").append(num).append(")^2");
+ hasSquareOrRoot = true;
+ } else {
+ // 确保根号下的数为正。
+ int rootNumber = random.nextInt(100) + 1;
+ sb.append("√(").append(rootNumber).append(")");
+ hasSquareOrRoot = true;
}
- return sb.toString();
+ } else {
+ sb.append(num);
+ }
+
+ // 添加运算符(除最后一个操作数外)。
+ if (i != operandsCount - 1) {
+ String op = basicOps[random.nextInt(basicOps.length)];
+ sb.append(" ").append(op).append(" ");
+ }
+ }
+
+ // 如果没有平方或根号,强制添加一个。
+ if (!hasSquareOrRoot) {
+ int rootNumber = random.nextInt(100) + 1;
+ sb.append(" + √(").append(rootNumber).append(")");
}
+ return sb.toString();
+ }
}
diff --git a/src/QuestionGenerator.java b/src/QuestionGenerator.java
index bd56c29..a9c70a6 100644
--- a/src/QuestionGenerator.java
+++ b/src/QuestionGenerator.java
@@ -1,51 +1,74 @@
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
/**
- * 题目生成器类
+ * 题目生成器类。根据用户角色使用不同策略生成数学题目。
*/
public class QuestionGenerator {
- private User user;
- private String role;
+ private static final int MAX_TRY_MULTIPLIER = 100;
- public QuestionGenerator(User user, String role) {
- this.user = user;
- this.role = role;
- }
+ /** 当前用户对象。 */
+ private final User user;
+
+ /** 当前用户角色(小学/初中/高中)。 */
+ private final String role;
+
+ /**
+ * 构造方法。
+ *
+ * @param user 用户对象
+ * @param role 用户角色
+ */
+ public QuestionGenerator(User user, String role) {
+ this.user = user;
+ this.role = role;
+ }
+
+ /**
+ * 生成指定数量的题目并保存到文件中。
+ *
+ * @param questionCount 要生成的题目数量
+ * @throws IOException 写文件失败时抛出
+ */
+ public void generateQuestions(int questionCount) throws IOException {
+ // 获取策略
+ QuestionStrategy strategy = QuestionStrategyFactory.getStrategy(role);
- public void generateQuestions(int questionCount) throws IOException {
- // 获取策略
- QuestionStrategy strategy = QuestionStrategyFactory.getStrategy(role);
-
- // 读出该用户所有历史题目
- Set