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