From 6dd2bf888bd53bd990c7d55c09e2531fdb512e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B3=E6=84=8F?= <1449892469@qq.com> Date: Sat, 11 Oct 2025 11:21:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=AD=94=E6=A1=88=E7=94=9F?= =?UTF-8?q?=E6=88=90=E4=BC=98=E5=85=88=E7=BA=A7=E7=AE=97=E6=B3=95=E5=92=8C?= =?UTF-8?q?=E5=88=9D=E4=B8=AD=E5=BC=80=E6=A0=B9=E5=8F=B7=E8=A6=81=E6=B1=82?= =?UTF-8?q?=EF=BC=88=E4=BB=BB=E6=84=8F=E6=93=8D=E4=BD=9C=E6=95=B0=EF=BC=8C?= =?UTF-8?q?=E8=80=8C=E9=9D=9E=E5=AE=8C=E5=85=A8=E5=B9=B3=E6=96=B9=E6=95=B0?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/vcs.xml | 6 + .../mathlearning/model/QuestionGenerator.java | 692 +++++++++--------- 2 files changed, 367 insertions(+), 331 deletions(-) create mode 100644 .idea/vcs.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..c8397c9 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/com/mathlearning/model/QuestionGenerator.java b/src/com/mathlearning/model/QuestionGenerator.java index 871427b..d45a941 100644 --- a/src/com/mathlearning/model/QuestionGenerator.java +++ b/src/com/mathlearning/model/QuestionGenerator.java @@ -11,7 +11,7 @@ public class QuestionGenerator { public List generateQuestions(String level, int count) { List questions = new ArrayList<>(); - Set questionTexts = new HashSet<>(); + Set questionTexts = new HashSet<>(); // 防止重复题目 for (int i = 0; i < count; i++) { Question question; @@ -44,443 +44,473 @@ public class QuestionGenerator { } private Question generatePrimaryQuestion(int index) { - int operandCount = random.nextInt(4) + 2; - List operands = new ArrayList<>(); - List operators = new ArrayList<>(); - - // 生成操作数和运算符,确保结果非负 - generateSafePrimaryExpression(operands, operators, operandCount); + int operandCount = random.nextInt(4) + 2; // 2-5个操作数 + int[] operands = new int[operandCount]; + int[] operations = new int[operandCount - 1]; // 操作符数组 String questionText; - int result; - int attempts = 0; + int answer; + // 生成合适的题目,确保计算过程中不出现负数 do { - boolean useParentheses = random.nextBoolean() && operandCount >= 3; - if (useParentheses) { - int parenPos = random.nextInt(operandCount - 1); - questionText = buildParenthesesExpression(operands, operators, parenPos); - result = evaluateWithParentheses(operands, operators, parenPos); - } else { - questionText = buildSimpleExpression(operands, operators); - result = evaluateSequential(operands, operators); + // 生成操作数 + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 } - attempts++; - if (result < 0) { - // 重新生成安全的表达式 - generateSafePrimaryExpression(operands, operators, operandCount); + // 生成操作符 (0: +, 1: -, 2: *, 3: /) + for (int i = 0; i < operations.length; i++) { + operations[i] = random.nextInt(4); } - } while (result < 0 && attempts < 10); - // 如果还是负数,强制使用加法 - if (result < 0) { - for (int i = 0; i < operators.size(); i++) { - operators.set(i, '+'); - } - questionText = buildSimpleExpression(operands, operators); - result = evaluateSequential(operands, operators); - } + // 构建题目并计算答案 + questionText = buildPrimaryQuestionText(operands, operations); + answer = calculatePrimaryAnswer(operands, operations); + + } while (answer < 0 || !isValidPrimaryCalculation(operands, operations)); - return generateIntOptions(questionText + " = ?", result, "小学"); + return generateOptions(questionText, answer, "小学"); } - private void generateSafePrimaryExpression(List operands, List operators, int operandCount) { - operands.clear(); - operators.clear(); + private Question generateMiddleSchoolQuestion(int index) { + int operandCount = random.nextInt(5) + 1; // 1-5个操作数 + int[] operands = new int[operandCount]; + int[] operations = new int[Math.max(0, operandCount - 1)]; // 操作符数组 + boolean[] hasSpecialOp = new boolean[operandCount]; // 标记哪些操作数有平方或开根号 + int[] specialOpTypes = new int[operandCount]; // 0:平方, 1:开根号 - 新增:记录具体操作类型 - // 首先生成所有操作数 - for (int i = 0; i < operandCount; i++) { - operands.add(random.nextInt(100) + 1); - } + String questionText; + double answer; - // 然后生成安全的运算符序列 - int currentValue = operands.get(0); - for (int i = 1; i < operandCount; i++) { - char op; - if (currentValue < operands.get(i)) { - // 如果当前值小于下一个操作数,避免减法导致负数 - if (random.nextBoolean()) { - op = '+'; - currentValue += operands.get(i); - } else { - op = (random.nextBoolean() && currentValue > 0) ? '*' : '+'; - if (op == '*') currentValue *= operands.get(i); - else currentValue += operands.get(i); - } - } else { - // 可以安全使用减法 - op = getRandomOperation("+-*/"); - switch (op) { - case '+': currentValue += operands.get(i); break; - case '-': currentValue -= operands.get(i); break; - case '*': currentValue *= operands.get(i); break; - case '/': - if (operands.get(i) != 0) currentValue /= operands.get(i); - else currentValue += operands.get(i); - break; - } + // 确保至少有一个平方或开根号运算符 + boolean hasSpecialOperation = false; + for (int i = 0; i < operandCount; i++) { + hasSpecialOp[i] = random.nextDouble() < 0.6; // 60%的概率有特殊运算 + if (hasSpecialOp[i]) { + hasSpecialOperation = true; + specialOpTypes[i] = random.nextInt(2); // 随机选择平方或开根号,并记录下来 } - operators.add(op); } - } - private Question generateMiddleSchoolQuestion(int index) { - int type = random.nextInt(4); - MathExpression expression = new MathExpression(); - - switch (type) { - case 0: - expression = createSquareExpression(); - break; - case 1: - expression = createSqrtExpression(); - break; - case 2: - expression = createSquareProductExpression(); - break; - case 3: - expression = createSquareDivisionExpression(); - break; + // 如果没有特殊运算,强制至少一个 + if (!hasSpecialOperation && operandCount > 0) { + int idx = random.nextInt(operandCount); + hasSpecialOp[idx] = true; + specialOpTypes[idx] = random.nextInt(2); } - // 确保初中题目结果非负 - if (expression.result < 0) { - expression = createSquareExpression(); // 重新生成一个肯定为正的题目 - } + // 生成合适的题目 + do { + // 生成操作数 + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } - return generateIntOptions(expression.questionText + " = ?", expression.result, "初中"); - } + // 生成操作符 (0: +, 1: -, 2: *, 3: /) + for (int i = 0; i < operations.length; i++) { + operations[i] = random.nextInt(4); + } - private MathExpression createSquareExpression() { - int a = random.nextInt(10) + 1; - int b = random.nextInt(100) + 1; - int c = random.nextInt(100) + 1; - // 只使用加法确保结果为正 - char op = '+'; + // 构建题目并计算答案 + questionText = buildMiddleSchoolQuestionText(operands, operations, hasSpecialOp, specialOpTypes); + answer = calculateMiddleSchoolAnswer(operands, operations, hasSpecialOp, specialOpTypes); - String questionText = a + "² " + op + " " + b + " × " + c; - int result = a * a + b * c; + } while (Double.isNaN(answer) || Double.isInfinite(answer) || Math.abs(answer) > 10000); - return new MathExpression(questionText, result); + return generateOptions(questionText, answer, "初中"); } - private MathExpression createSqrtExpression() { - int sqrtBase = findPerfectSquare(100); - int sqrtVal = (int) Math.sqrt(sqrtBase); - int d = random.nextInt(100) + 1; - // 只使用加法确保结果为正 - char op = '+'; + private Question generateHighSchoolQuestion(int index) { + int operandCount = random.nextInt(5) + 1; // 1-5个操作数 + int[] operands = new int[operandCount]; + int[] operations = new int[Math.max(0, operandCount - 1)]; // 操作符数组 + boolean[] hasTrigOp = new boolean[operandCount]; // 标记哪些操作数有三角函数 + int[] trigFunctions = new int[operandCount]; // 0:sin, 1:cos, 2:tan - String questionText = "√" + sqrtBase + " " + op + " " + d; - int result = sqrtVal + d; + String questionText; + double answer; - return new MathExpression(questionText, result); - } + // 确保至少有一个三角函数运算符 + boolean hasTrigOperation = false; + for (int i = 0; i < operandCount; i++) { + hasTrigOp[i] = random.nextDouble() < 0.6; // 60%的概率有三角函数 + if (hasTrigOp[i]) { + hasTrigOperation = true; + trigFunctions[i] = random.nextInt(3); // 随机选择三角函数 + } + } - private MathExpression createSquareProductExpression() { - int e = random.nextInt(100) + 1; - int f = random.nextInt(10) + 1; - int g = random.nextInt(100) + 1; - // 只使用加法确保结果为正 - char op = '+'; + // 如果没有三角函数,强制至少一个 + if (!hasTrigOperation && operandCount > 0) { + int idx = random.nextInt(operandCount); + hasTrigOp[idx] = true; + trigFunctions[idx] = random.nextInt(3); + } - String questionText = e + " × " + f + "² " + op + " " + g; - int result = e * f * f + g; + // 生成合适的题目 + do { + // 生成操作数 (角度值,通常用特殊角度) + for (int i = 0; i < operandCount; i++) { + // 使用常见角度:0, 30, 45, 60, 90等 + int[] commonAngles = {0, 30, 45, 60, 90, 120, 135, 150, 180}; + operands[i] = commonAngles[random.nextInt(commonAngles.length)]; + } - return new MathExpression(questionText, result); - } + // 生成操作符 (0: +, 1: -, 2: *, 3: /) + for (int i = 0; i < operations.length; i++) { + operations[i] = random.nextInt(4); + } - private MathExpression createSquareDivisionExpression() { - int h = random.nextInt(50) + 1; - int i = random.nextInt(50) + 1; - int sum = h + i; - int square = sum * sum; - int j = findDivisor(square); + // 构建题目并计算答案 + questionText = buildHighSchoolQuestionText(operands, operations, hasTrigOp, trigFunctions); + answer = calculateHighSchoolAnswer(operands, operations, hasTrigOp, trigFunctions); - String questionText = "(" + h + " + " + i + ")² ÷ " + j; - int result = square / j; + } while (Double.isNaN(answer) || Double.isInfinite(answer) || Math.abs(answer) > 10000); - return new MathExpression(questionText, result); + return generateOptions(questionText, (int)Math.round(answer), "高中"); } - private Question generateHighSchoolQuestion(int index) { - int type = random.nextInt(4); - TrigExpression expression = new TrigExpression(); + // 小学题目相关方法 + private String buildPrimaryQuestionText(int[] operands, int[] operations) { + StringBuilder sb = new StringBuilder(); - switch (type) { - case 0: - expression = createSinExpression(); - break; - case 1: - expression = createCosExpression(); - break; - case 2: - expression = createTanExpression(); - break; - case 3: - expression = createSinCosExpression(); - break; + for (int i = 0; i < operands.length; i++) { + if (i > 0) { + switch (operations[i - 1]) { + case 0: sb.append(" + "); break; + case 1: sb.append(" - "); break; + case 2: sb.append(" × "); break; + case 3: sb.append(" ÷ "); break; + } + } + sb.append(operands[i]); } + sb.append(" = ?"); - return generateDoubleOptions(expression.questionText + " = ?", expression.result, "高中"); + return sb.toString(); } - private TrigExpression createSinExpression() { - String[] angles = {"0°", "30°", "45°", "60°", "90°"}; - double[] sinValues = {0, 0.5, 0.71, 0.87, 1.0}; + private int calculatePrimaryAnswer(int[] operands, int[] operations) { + // 先处理乘除法,再处理加减法 + List numbers = new ArrayList<>(); + List ops = new ArrayList<>(); - int idx = random.nextInt(angles.length); - int b = random.nextInt(100) + 1; - // 只使用加法确保结果为正 - char op = '+'; + for (int operand : operands) { + numbers.add(operand); + } + for (int operation : operations) { + ops.add(operation); + } - String questionText = "sin(" + angles[idx] + ") " + op + " " + b; - double result = sinValues[idx] + b; + // 处理乘除法 + for (int i = 0; i < ops.size(); i++) { + int op = ops.get(i); + if (op == 2 || op == 3) { + int left = numbers.get(i); + int right = numbers.get(i + 1); + int result; - return new TrigExpression(questionText, result); - } + if (op == 2) { + result = left * right; + } else { + if (right == 0 || left % right != 0) return -1; + result = left / right; + } - private TrigExpression createCosExpression() { - String[] angles = {"0°", "30°", "45°", "60°"}; - double[] cosValues = {1.0, 0.87, 0.71, 0.5}; + numbers.set(i, result); + numbers.remove(i + 1); + ops.remove(i); + i--; + } + } - int idx = random.nextInt(angles.length); - int a = random.nextInt(100) + 1; + // 处理加减法 + int result = numbers.get(0); + for (int i = 0; i < ops.size(); i++) { + int op = ops.get(i); + int nextNum = numbers.get(i + 1); - String questionText = a + " × cos(" + angles[idx] + ")"; - double result = a * cosValues[idx]; + if (op == 0) { + result += nextNum; + } else { + if (result < nextNum) return -1; + result -= nextNum; + } + } - return new TrigExpression(questionText, result); + return result; } - private TrigExpression createTanExpression() { - String[] angles = {"0°", "30°", "45°", "60°"}; - double[] tanValues = {0, 0.58, 1.0, 1.73}; + private boolean isValidPrimaryCalculation(int[] operands, int[] operations) { + try { + int current = operands[0]; + + for (int i = 0; i < operations.length; i++) { + int next = operands[i + 1]; + int op = operations[i]; + + if (op == 1) { + if (current < next) return false; + current = current - next; + } else if (op == 0) { + current = current + next; + } else if (op == 2) { + current = current * next; + } else if (op == 3) { + if (next == 0 || current % next != 0) return false; + current = current / next; + } + } + return current >= 0; + } catch (Exception e) { + return false; + } + } - int idx = random.nextInt(angles.length); - int c = random.nextInt(20) + 1; + // 初中题目相关方法 + private String buildMiddleSchoolQuestionText(int[] operands, int[] operations, boolean[] hasSpecialOp, int[] specialOpTypes) { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < operands.length; i++) { + if (i > 0) { + switch (operations[i - 1]) { + case 0: sb.append(" + "); break; + case 1: sb.append(" - "); break; + case 2: sb.append(" × "); break; + case 3: sb.append(" ÷ "); break; + } + } - String questionText = "tan(" + angles[idx] + ") ÷ " + c; - double result = tanValues[idx] / c; + if (hasSpecialOp[i]) { + if (specialOpTypes[i] == 0) { + // 平方 + sb.append(operands[i]).append("²"); + } else { + // 开根号 + sb.append("√").append(operands[i]); + } + } else { + sb.append(operands[i]); + } + } + sb.append(" = ?"); - return new TrigExpression(questionText, result); + return sb.toString(); } - private TrigExpression createSinCosExpression() { - String[] angles = {"0°", "30°", "45°", "60°"}; - double[] sinValues = {0, 0.5, 0.71, 0.87}; - double[] cosValues = {1.0, 0.87, 0.71, 0.5}; + private double calculateMiddleSchoolAnswer(int[] operands, int[] operations, boolean[] hasSpecialOp, int[] specialOpTypes) { + // 先处理特殊运算(平方和开根号) + double[] processedValues = new double[operands.length]; + for (int i = 0; i < operands.length; i++) { + if (hasSpecialOp[i]) { + if (specialOpTypes[i] == 0) { + // 平方 + processedValues[i] = operands[i] * operands[i]; + } else { + // 开根号 + processedValues[i] = Math.sqrt(operands[i]); + } + } else { + processedValues[i] = operands[i]; + } + } - int idx1 = random.nextInt(angles.length); - int idx2 = random.nextInt(angles.length); - int d = random.nextInt(100) + 1; - // 只使用加法确保结果为正 - char op = '+'; + // 然后按照小学的计算逻辑处理 + List numbers = new ArrayList<>(); + List ops = new ArrayList<>(); - String questionText = "sin(" + angles[idx1] + ") × cos(" + angles[idx2] + ") " + op + " " + d; - double product = sinValues[idx1] * cosValues[idx2]; - double result = product + d; + for (double value : processedValues) { + numbers.add(value); + } + for (int operation : operations) { + ops.add(operation); + } - return new TrigExpression(questionText, result); - } + // 处理乘除法 + for (int i = 0; i < ops.size(); i++) { + int op = ops.get(i); + if (op == 2 || op == 3) { + double left = numbers.get(i); + double right = numbers.get(i + 1); + double result; - private char getRandomOperation(String operations) { - return operations.charAt(random.nextInt(operations.length())); - } + if (op == 2) { + result = left * right; + } else { + if (right == 0) return Double.NaN; + result = left / right; + } - private String buildSimpleExpression(List operands, List operators) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < operands.size(); i++) { - sb.append(operands.get(i)); - if (i < operands.size() - 1) { - sb.append(" ").append(operators.get(i)).append(" "); + numbers.set(i, result); + numbers.remove(i + 1); + ops.remove(i); + i--; } } - return sb.toString(); - } - private String buildParenthesesExpression(List operands, List operators, int parenPos) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < operands.size(); i++) { - if (i == parenPos) sb.append("("); - sb.append(operands.get(i)); - if (i == parenPos + 1) sb.append(")"); - if (i < operands.size() - 1) { - sb.append(" ").append(operators.get(i)).append(" "); + // 处理加减法 + double result = numbers.get(0); + for (int i = 0; i < ops.size(); i++) { + int op = ops.get(i); + double nextNum = numbers.get(i + 1); + + if (op == 0) { + result += nextNum; + } else { + result -= nextNum; } } - return sb.toString(); - } - private int evaluateSequential(List operands, List operators) { - int result = operands.get(0); - for (int i = 0; i < operators.size(); i++) { - result = calculate(result, operands.get(i + 1), operators.get(i)); - } return result; } - private int evaluateWithParentheses(List operands, List operators, int parenPos) { - int parenResult = calculate(operands.get(parenPos), operands.get(parenPos + 1), operators.get(parenPos)); - List newOperands = new ArrayList<>(); - List newOperators = new ArrayList<>(); + // 高中题目相关方法 + private String buildHighSchoolQuestionText(int[] operands, int[] operations, boolean[] hasTrigOp, int[] trigFunctions) { + StringBuilder sb = new StringBuilder(); - for (int i = 0; i < operands.size(); i++) { - if (i == parenPos) { - newOperands.add(parenResult); - } else if (i != parenPos + 1) { - newOperands.add(operands.get(i)); + for (int i = 0; i < operands.length; i++) { + if (i > 0) { + switch (operations[i - 1]) { + case 0: sb.append(" + "); break; + case 1: sb.append(" - "); break; + case 2: sb.append(" × "); break; + case 3: sb.append(" ÷ "); break; + } } - } - for (int i = 0; i < operators.size(); i++) { - if (i != parenPos) { - newOperators.add(operators.get(i)); + if (hasTrigOp[i]) { + switch (trigFunctions[i]) { + case 0: sb.append("sin(").append(operands[i]).append("°)"); break; + case 1: sb.append("cos(").append(operands[i]).append("°)"); break; + case 2: sb.append("tan(").append(operands[i]).append("°)"); break; + } + } else { + sb.append(operands[i]); } } + sb.append(" = ?"); - return evaluateSequential(newOperands, newOperators); + return sb.toString(); } - private int calculate(int a, int b, char op) { - switch (op) { - case '+': return a + b; - case '-': return Math.max(a - b, 0); - case '*': return a * b; - case '/': return (b == 0) ? a : a / b; - default: return a + b; + private double calculateHighSchoolAnswer(int[] operands, int[] operations, boolean[] hasTrigOp, int[] trigFunctions) { + // 先处理三角函数运算 + double[] processedValues = new double[operands.length]; + for (int i = 0; i < operands.length; i++) { + if (hasTrigOp[i]) { + double radians = Math.toRadians(operands[i]); + switch (trigFunctions[i]) { + case 0: processedValues[i] = Math.sin(radians); break; + case 1: processedValues[i] = Math.cos(radians); break; + case 2: processedValues[i] = Math.tan(radians); break; + } + } else { + processedValues[i] = operands[i]; + } } - } - private int findPerfectSquare(int max) { - List squares = new ArrayList<>(); - for (int i = 1; i * i <= max; i++) { - squares.add(i * i); - } - return squares.get(random.nextInt(squares.size())); - } + // 然后按照常规计算逻辑处理 + List numbers = new ArrayList<>(); + List ops = new ArrayList<>(); - private int findDivisor(int number) { - List divisors = new ArrayList<>(); - for (int i = 2; i <= Math.min(20, number); i++) { - if (number % i == 0) { - divisors.add(i); - } + for (double value : processedValues) { + numbers.add(value); + } + for (int operation : operations) { + ops.add(operation); } - return divisors.isEmpty() ? 1 : divisors.get(random.nextInt(divisors.size())); - } - - private Question generateIntOptions(String questionText, int answer, String level) { - String[] options = new String[4]; - Set usedValues = new HashSet<>(); - String correctAnswer = String.valueOf(answer); - options[0] = correctAnswer; - usedValues.add(answer); + // 处理乘除法 + for (int i = 0; i < ops.size(); i++) { + int op = ops.get(i); + if (op == 2 || op == 3) { + double left = numbers.get(i); + double right = numbers.get(i + 1); + double result; - for (int i = 1; i < 4; i++) { - int wrongAnswer; - int attempts = 0; - do { - int range = Math.max(3, Math.abs(answer) / 5 + 1); - int offset = random.nextInt(range * 2 + 1) - range; - wrongAnswer = answer + offset; - wrongAnswer = Math.max(wrongAnswer, 0); // 确保错误答案也不为负 - attempts++; - if (attempts > 20) { - wrongAnswer = answer + (i + 1) * 10 + 5; - break; + if (op == 2) { + result = left * right; + } else { + if (right == 0) return Double.NaN; + result = left / right; } - } while (wrongAnswer == answer || usedValues.contains(wrongAnswer)); - options[i] = String.valueOf(wrongAnswer); - usedValues.add(wrongAnswer); + numbers.set(i, result); + numbers.remove(i + 1); + ops.remove(i); + i--; + } } - shuffleArray(options); - int correctIndex = findCorrectIndex(options, correctAnswer); + // 处理加减法 + double result = numbers.get(0); + for (int i = 0; i < ops.size(); i++) { + int op = ops.get(i); + double nextNum = numbers.get(i + 1); - return new Question(questionText, options, correctIndex, level); + if (op == 0) { + result += nextNum; + } else { + result -= nextNum; + } + } + + return result; } - private Question generateDoubleOptions(String questionText, double answer, String level) { + // 生成选项的通用方法 + private Question generateOptions(String questionText, double answer, String level) { String[] options = new String[4]; - Set usedValues = new HashSet<>(); + Set usedValues = new HashSet<>(); - String correctAnswer = formatDouble(answer); - options[0] = correctAnswer; - usedValues.add(correctAnswer); + // 添加正确答案,保留1位小数 + options[0] = String.format("%.1f", answer); + usedValues.add(Math.round(answer * 10) / 10.0); // 保留1位小数进行比较 + // 生成错误答案 for (int i = 1; i < 4; i++) { - String wrongAnswer; + double wrongAnswer; int attempts = 0; do { - double offset = (random.nextDouble() - 0.5) * Math.max(1, Math.abs(answer) * 0.3); - double wrongValue = answer + offset; - wrongAnswer = formatDouble(Math.max(wrongValue, 0)); // 确保错误答案不为负 + // 根据答案大小生成合适的错误答案 + double range = Math.max(2, Math.abs(answer) / 4 + 1); + double offset = (random.nextDouble() * range * 2) - range; + wrongAnswer = answer + offset; + wrongAnswer = Math.round(wrongAnswer * 10) / 10.0; // 保留1位小数 attempts++; - if (attempts > 20) { - wrongAnswer = formatDouble(answer + (i + 1) * 2.5); - break; - } - } while (usedValues.contains(wrongAnswer) || wrongAnswer.equals(correctAnswer)); + } while (usedValues.contains(wrongAnswer) && attempts < 20); - options[i] = wrongAnswer; + if (usedValues.contains(wrongAnswer)) { + wrongAnswer = answer + (i * 0.5) + 0.3; + wrongAnswer = Math.round(wrongAnswer * 10) / 10.0; + } + + options[i] = String.format("%.1f", wrongAnswer); usedValues.add(wrongAnswer); } + // 打乱选项顺序 shuffleArray(options); - int correctIndex = findCorrectIndex(options, correctAnswer); - - return new Question(questionText, options, correctIndex, level); - } - private String formatDouble(double value) { - if (Double.isInfinite(value)) return "∞"; - if (Double.isNaN(value)) return "无解"; - if (Math.abs(value) < 0.001) return "0"; - return String.format("%.2f", value).replaceAll("0*$", "").replaceAll("\\.$", ""); - } - - private int findCorrectIndex(String[] options, String correctAnswer) { + // 找到正确答案的新位置 + int correctIndex = 0; + String correctAnswerStr = String.format("%.1f", answer); for (int i = 0; i < options.length; i++) { - if (options[i].equals(correctAnswer)) return i; + if (options[i].equals(correctAnswerStr)) { + correctIndex = i; + break; + } } - return 0; + + return new Question(questionText, options, correctIndex, level); } private void shuffleArray(String[] array) { for (int i = array.length - 1; i > 0; i--) { - int index = random.nextInt(i + 1); - String temp = array[index]; - array[index] = array[i]; - array[i] = temp; - } - } - - // 辅助类来存储题目和答案 - private static class MathExpression { - String questionText; - int result; - - MathExpression() {} - - MathExpression(String questionText, int result) { - this.questionText = questionText; - this.result = result; - } - } - - private static class TrigExpression { - String questionText; - double result; - - TrigExpression() {} - - TrigExpression(String questionText, double result) { - this.questionText = questionText; - this.result = result; + int j = random.nextInt(i + 1); + String temp = array[i]; + array[i] = array[j]; + array[j] = temp; } } } \ No newline at end of file