|
|
|
|
@ -46,12 +46,11 @@ public class QuestionGenerator {
|
|
|
|
|
private Question generatePrimaryQuestion(int index) {
|
|
|
|
|
int operandCount = random.nextInt(4) + 2; // 2-5个操作数
|
|
|
|
|
int[] operands = new int[operandCount];
|
|
|
|
|
int[] operations = new int[operandCount - 1]; // 操作符数组
|
|
|
|
|
int[] operations = new int[operandCount - 1];
|
|
|
|
|
|
|
|
|
|
String questionText;
|
|
|
|
|
int answer;
|
|
|
|
|
double answer;
|
|
|
|
|
|
|
|
|
|
// 生成合适的题目,确保计算过程中不出现负数
|
|
|
|
|
do {
|
|
|
|
|
// 生成操作数
|
|
|
|
|
for (int i = 0; i < operandCount; i++) {
|
|
|
|
|
@ -63,11 +62,27 @@ public class QuestionGenerator {
|
|
|
|
|
operations[i] = random.nextInt(4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 构建题目并计算答案
|
|
|
|
|
questionText = buildPrimaryQuestionText(operands, operations);
|
|
|
|
|
answer = calculatePrimaryAnswer(operands, operations);
|
|
|
|
|
// 改进的括号逻辑:在可能改变计算顺序的地方加括号
|
|
|
|
|
boolean useParentheses = random.nextDouble() < 0.3 && operandCount >= 3;
|
|
|
|
|
int parenStart = -1;
|
|
|
|
|
int parenEnd = -1;
|
|
|
|
|
|
|
|
|
|
if (useParentheses) {
|
|
|
|
|
// 寻找适合加括号的位置(加减法周围)
|
|
|
|
|
parenStart = findSuitableParenthesesPosition(operations);
|
|
|
|
|
if (parenStart != -1) {
|
|
|
|
|
// 括号包含2-3个操作数
|
|
|
|
|
parenEnd = parenStart + 1;
|
|
|
|
|
if (parenEnd < operands.length - 1 && random.nextBoolean()) {
|
|
|
|
|
parenEnd++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} while (answer < 0 || !isValidPrimaryCalculation(operands, operations));
|
|
|
|
|
questionText = buildPrimaryQuestionText(operands, operations, parenStart, parenEnd);
|
|
|
|
|
answer = calculatePrimaryAnswerWithParentheses(operands, operations, parenStart, parenEnd);
|
|
|
|
|
|
|
|
|
|
} while (answer < 0 || Double.isNaN(answer) || Double.isInfinite(answer));
|
|
|
|
|
|
|
|
|
|
return generateOptions(questionText, answer, "小学");
|
|
|
|
|
}
|
|
|
|
|
@ -77,7 +92,7 @@ public class QuestionGenerator {
|
|
|
|
|
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:开根号 - 新增:记录具体操作类型
|
|
|
|
|
int[] specialOpTypes = new int[operandCount]; // 0:平方, 1:开根号
|
|
|
|
|
|
|
|
|
|
String questionText;
|
|
|
|
|
double answer;
|
|
|
|
|
@ -88,7 +103,7 @@ public class QuestionGenerator {
|
|
|
|
|
hasSpecialOp[i] = random.nextDouble() < 0.6; // 60%的概率有特殊运算
|
|
|
|
|
if (hasSpecialOp[i]) {
|
|
|
|
|
hasSpecialOperation = true;
|
|
|
|
|
specialOpTypes[i] = random.nextInt(2); // 随机选择平方或开根号,并记录下来
|
|
|
|
|
specialOpTypes[i] = random.nextInt(2); // 随机选择平方或开根号
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -149,11 +164,16 @@ public class QuestionGenerator {
|
|
|
|
|
|
|
|
|
|
// 生成合适的题目
|
|
|
|
|
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)];
|
|
|
|
|
if (hasTrigOp[i]) {
|
|
|
|
|
// 三角函数使用特殊角度值
|
|
|
|
|
int[] specialAngles = {0, 15, 30, 45, 60, 75, 90};
|
|
|
|
|
operands[i] = specialAngles[random.nextInt(specialAngles.length)];
|
|
|
|
|
} else {
|
|
|
|
|
// 普通操作数使用1-100的随机数
|
|
|
|
|
operands[i] = random.nextInt(100) + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成操作符 (0: +, 1: -, 2: *, 3: /)
|
|
|
|
|
@ -167,31 +187,69 @@ public class QuestionGenerator {
|
|
|
|
|
|
|
|
|
|
} while (Double.isNaN(answer) || Double.isInfinite(answer) || Math.abs(answer) > 10000);
|
|
|
|
|
|
|
|
|
|
return generateOptions(questionText, (int)Math.round(answer), "高中");
|
|
|
|
|
return generateOptions(questionText, answer, "高中");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 小学题目相关方法
|
|
|
|
|
private String buildPrimaryQuestionText(int[] operands, int[] operations) {
|
|
|
|
|
private int findSuitableParenthesesPosition(int[] operations) {
|
|
|
|
|
// 寻找加减法操作符的位置,在这些地方加括号才有意义
|
|
|
|
|
List<Integer> suitablePositions = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operations.length; i++) {
|
|
|
|
|
// 如果是加减法,且不是第一个操作符
|
|
|
|
|
if ((operations[i] == 0 || operations[i] == 1) && i > 0) {
|
|
|
|
|
suitablePositions.add(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (suitablePositions.isEmpty()) {
|
|
|
|
|
// 如果没有找到合适的加减法位置,随机选择一个位置
|
|
|
|
|
return operations.length > 1 ? random.nextInt(operations.length - 1) : -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从合适的位置中随机选择一个
|
|
|
|
|
return suitablePositions.get(random.nextInt(suitablePositions.size()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String buildPrimaryQuestionText(int[] operands, int[] operations, int parenStart, int parenEnd) {
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < operands.length; i++) {
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
switch (operations[i - 1]) {
|
|
|
|
|
// 在操作数前添加左括号
|
|
|
|
|
if (i == parenStart) {
|
|
|
|
|
sb.append("(");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加操作数
|
|
|
|
|
sb.append(operands[i]);
|
|
|
|
|
|
|
|
|
|
// 在操作数后添加右括号(但要在操作符之前)
|
|
|
|
|
if (i == parenEnd) {
|
|
|
|
|
sb.append(")");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加操作符(如果不是最后一个操作数)
|
|
|
|
|
if (i < operations.length) {
|
|
|
|
|
switch (operations[i]) {
|
|
|
|
|
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 sb.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int calculatePrimaryAnswer(int[] operands, int[] operations) {
|
|
|
|
|
// 先处理乘除法,再处理加减法
|
|
|
|
|
private double calculatePrimaryAnswerWithParentheses(int[] operands, int[] operations, int parenStart, int parenEnd) {
|
|
|
|
|
// 如果没有括号,使用原来的计算方法
|
|
|
|
|
if (parenStart == -1 || parenEnd == -1) {
|
|
|
|
|
return calculatePrimaryAnswer(operands, operations);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 复制操作数和操作符
|
|
|
|
|
List<Integer> numbers = new ArrayList<>();
|
|
|
|
|
List<Integer> ops = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
@ -202,33 +260,91 @@ public class QuestionGenerator {
|
|
|
|
|
ops.add(operation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理乘除法
|
|
|
|
|
// 计算括号内的表达式
|
|
|
|
|
double parenthesesResult = calculateParenthesesContent(numbers, ops, parenStart, parenEnd);
|
|
|
|
|
|
|
|
|
|
// 验证括号计算结果是否有效
|
|
|
|
|
if (parenthesesResult < 0 || Double.isNaN(parenthesesResult) || Double.isInfinite(parenthesesResult)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 用括号计算结果替换括号内的所有元素
|
|
|
|
|
replaceWithParenthesesResult(numbers, ops, parenStart, parenEnd, parenthesesResult);
|
|
|
|
|
|
|
|
|
|
// 计算剩余表达式
|
|
|
|
|
return calculateWithoutParentheses(numbers, ops);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double calculateParenthesesContent(List<Integer> numbers, List<Integer> ops, int start, int end) {
|
|
|
|
|
// 提取括号内的数字和操作符
|
|
|
|
|
List<Integer> parenNumbers = new ArrayList<>();
|
|
|
|
|
List<Integer> parenOps = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
for (int i = start; i <= end; i++) {
|
|
|
|
|
parenNumbers.add(numbers.get(i));
|
|
|
|
|
}
|
|
|
|
|
for (int i = start; i < end; i++) {
|
|
|
|
|
parenOps.add(ops.get(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算括号内的表达式(精确计算)
|
|
|
|
|
return calculateWithoutParentheses(parenNumbers, parenOps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void replaceWithParenthesesResult(List<Integer> numbers, List<Integer> ops,
|
|
|
|
|
int start, int end, double result) {
|
|
|
|
|
// 计算需要移除的元素数量
|
|
|
|
|
int numCountToRemove = end - start + 1;
|
|
|
|
|
int opCountToRemove = end - start;
|
|
|
|
|
|
|
|
|
|
// 移除括号范围内的数字
|
|
|
|
|
for (int i = 0; i < numCountToRemove; i++) {
|
|
|
|
|
numbers.remove(start);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 移除括号范围内的操作符
|
|
|
|
|
for (int i = 0; i < opCountToRemove; i++) {
|
|
|
|
|
ops.remove(start);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 插入括号计算结果
|
|
|
|
|
numbers.add(start, (int) Math.round(result));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double calculateWithoutParentheses(List<Integer> numbers, List<Integer> ops) {
|
|
|
|
|
// 转换为double列表进行计算(精确计算)
|
|
|
|
|
List<Double> doubleNumbers = new ArrayList<>();
|
|
|
|
|
for (Integer num : numbers) {
|
|
|
|
|
doubleNumbers.add(num.doubleValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 先处理乘除法(精确计算)
|
|
|
|
|
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;
|
|
|
|
|
double left = doubleNumbers.get(i);
|
|
|
|
|
double right = doubleNumbers.get(i + 1);
|
|
|
|
|
double result;
|
|
|
|
|
|
|
|
|
|
if (op == 2) {
|
|
|
|
|
result = left * right;
|
|
|
|
|
} else {
|
|
|
|
|
if (right == 0 || left % right != 0) return -1;
|
|
|
|
|
if (right == 0) return Double.NaN;
|
|
|
|
|
result = left / right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numbers.set(i, result);
|
|
|
|
|
numbers.remove(i + 1);
|
|
|
|
|
doubleNumbers.set(i, result);
|
|
|
|
|
doubleNumbers.remove(i + 1);
|
|
|
|
|
ops.remove(i);
|
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理加减法
|
|
|
|
|
int result = numbers.get(0);
|
|
|
|
|
// 处理加减法(精确计算)
|
|
|
|
|
double result = doubleNumbers.get(0);
|
|
|
|
|
for (int i = 0; i < ops.size(); i++) {
|
|
|
|
|
int op = ops.get(i);
|
|
|
|
|
int nextNum = numbers.get(i + 1);
|
|
|
|
|
double nextNum = doubleNumbers.get(i + 1);
|
|
|
|
|
|
|
|
|
|
if (op == 0) {
|
|
|
|
|
result += nextNum;
|
|
|
|
|
@ -238,33 +354,60 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
// 只在最后结果保留2位小数
|
|
|
|
|
return Math.round(result * 100) / 100.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean isValidPrimaryCalculation(int[] operands, int[] operations) {
|
|
|
|
|
try {
|
|
|
|
|
int current = operands[0];
|
|
|
|
|
private double calculatePrimaryAnswer(int[] operands, int[] operations) {
|
|
|
|
|
// 转换为double列表(精确计算)
|
|
|
|
|
List<Double> numbers = new ArrayList<>();
|
|
|
|
|
List<Integer> ops = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
for (int operand : operands) {
|
|
|
|
|
numbers.add((double) operand);
|
|
|
|
|
}
|
|
|
|
|
for (int operation : operations) {
|
|
|
|
|
ops.add(operation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理乘除法(精确计算)
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if (op == 2) {
|
|
|
|
|
result = left * right;
|
|
|
|
|
} else {
|
|
|
|
|
if (right == 0) return Double.NaN;
|
|
|
|
|
result = left / right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
numbers.set(i, result);
|
|
|
|
|
numbers.remove(i + 1);
|
|
|
|
|
ops.remove(i);
|
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
return current >= 0;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理加减法(精确计算)
|
|
|
|
|
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 {
|
|
|
|
|
if (result < nextNum) return -1;
|
|
|
|
|
result -= nextNum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 只在最后结果保留2位小数
|
|
|
|
|
return Math.round(result * 100) / 100.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 初中题目相关方法
|
|
|
|
|
@ -299,7 +442,7 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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]) {
|
|
|
|
|
@ -315,7 +458,7 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 然后按照小学的计算逻辑处理
|
|
|
|
|
// 然后按照小学的计算逻辑处理(精确计算)
|
|
|
|
|
List<Double> numbers = new ArrayList<>();
|
|
|
|
|
List<Integer> ops = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
@ -326,7 +469,7 @@ public class QuestionGenerator {
|
|
|
|
|
ops.add(operation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理乘除法
|
|
|
|
|
// 处理乘除法(精确计算)
|
|
|
|
|
for (int i = 0; i < ops.size(); i++) {
|
|
|
|
|
int op = ops.get(i);
|
|
|
|
|
if (op == 2 || op == 3) {
|
|
|
|
|
@ -348,7 +491,7 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理加减法
|
|
|
|
|
// 处理加减法(精确计算)
|
|
|
|
|
double result = numbers.get(0);
|
|
|
|
|
for (int i = 0; i < ops.size(); i++) {
|
|
|
|
|
int op = ops.get(i);
|
|
|
|
|
@ -361,7 +504,8 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
// 只在最后结果保留2位小数
|
|
|
|
|
return Math.round(result * 100) / 100.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 高中题目相关方法
|
|
|
|
|
@ -394,22 +538,34 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
case 0:
|
|
|
|
|
processedValues[i] = Math.sin(radians);
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
processedValues[i] = Math.cos(radians);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
// 避免tan(90°)等无效值
|
|
|
|
|
if (operands[i] % 180 == 90 && operands[i] % 360 != 270) {
|
|
|
|
|
return Double.NaN;
|
|
|
|
|
}
|
|
|
|
|
processedValues[i] = Math.tan(radians);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
processedValues[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
processedValues[i] = operands[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 然后按照常规计算逻辑处理
|
|
|
|
|
// 然后按照常规计算逻辑处理(精确计算)
|
|
|
|
|
List<Double> numbers = new ArrayList<>();
|
|
|
|
|
List<Integer> ops = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
@ -420,7 +576,7 @@ public class QuestionGenerator {
|
|
|
|
|
ops.add(operation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理乘除法
|
|
|
|
|
// 处理乘除法(精确计算)
|
|
|
|
|
for (int i = 0; i < ops.size(); i++) {
|
|
|
|
|
int op = ops.get(i);
|
|
|
|
|
if (op == 2 || op == 3) {
|
|
|
|
|
@ -442,7 +598,7 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理加减法
|
|
|
|
|
// 处理加减法(精确计算)
|
|
|
|
|
double result = numbers.get(0);
|
|
|
|
|
for (int i = 0; i < ops.size(); i++) {
|
|
|
|
|
int op = ops.get(i);
|
|
|
|
|
@ -455,37 +611,59 @@ public class QuestionGenerator {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
// 只在最后结果保留2位小数
|
|
|
|
|
return Math.round(result * 100) / 100.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成选项的通用方法
|
|
|
|
|
private Question generateOptions(String questionText, double answer, String level) {
|
|
|
|
|
String[] options = new String[4];
|
|
|
|
|
Set<Double> usedValues = new HashSet<>();
|
|
|
|
|
Set<String> usedValues = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
// 添加正确答案,保留1位小数
|
|
|
|
|
options[0] = String.format("%.1f", answer);
|
|
|
|
|
usedValues.add(Math.round(answer * 10) / 10.0); // 保留1位小数进行比较
|
|
|
|
|
// 检查答案是否为整数
|
|
|
|
|
boolean isIntegerAnswer = (answer == (int) answer);
|
|
|
|
|
|
|
|
|
|
// 格式化正确答案
|
|
|
|
|
String correctAnswer = formatAnswer(answer);
|
|
|
|
|
options[0] = correctAnswer;
|
|
|
|
|
usedValues.add(correctAnswer);
|
|
|
|
|
|
|
|
|
|
// 生成错误答案
|
|
|
|
|
for (int i = 1; i < 4; i++) {
|
|
|
|
|
double wrongAnswer;
|
|
|
|
|
String wrongAnswer;
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
do {
|
|
|
|
|
// 根据答案大小生成合适的错误答案
|
|
|
|
|
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位小数
|
|
|
|
|
// 基于正确答案生成错误答案
|
|
|
|
|
double wrongValue;
|
|
|
|
|
double offset = (random.nextDouble() * 5) + 1; // 1-6的偏移量
|
|
|
|
|
|
|
|
|
|
if (isIntegerAnswer) {
|
|
|
|
|
// 如果答案是整数,生成整数错误答案
|
|
|
|
|
int intAnswer = (int) answer;
|
|
|
|
|
int intOffset = random.nextInt(10) + 1; // 1-10的整数偏移
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
wrongValue = intAnswer + intOffset;
|
|
|
|
|
} else {
|
|
|
|
|
wrongValue = Math.max(1, intAnswer - intOffset);
|
|
|
|
|
}
|
|
|
|
|
// 确保是整数
|
|
|
|
|
wrongValue = (int) wrongValue;
|
|
|
|
|
} else {
|
|
|
|
|
// 如果答案是小数,生成小数错误答案
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
wrongValue = answer + offset;
|
|
|
|
|
} else {
|
|
|
|
|
wrongValue = answer - offset;
|
|
|
|
|
}
|
|
|
|
|
// 保留2位小数
|
|
|
|
|
wrongValue = Math.round(wrongValue * 100) / 100.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wrongAnswer = formatAnswer(wrongValue);
|
|
|
|
|
attempts++;
|
|
|
|
|
} while (usedValues.contains(wrongAnswer) && attempts < 20);
|
|
|
|
|
|
|
|
|
|
if (usedValues.contains(wrongAnswer)) {
|
|
|
|
|
wrongAnswer = answer + (i * 0.5) + 0.3;
|
|
|
|
|
wrongAnswer = Math.round(wrongAnswer * 10) / 10.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
options[i] = String.format("%.1f", wrongAnswer);
|
|
|
|
|
options[i] = wrongAnswer;
|
|
|
|
|
usedValues.add(wrongAnswer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -494,9 +672,8 @@ public class QuestionGenerator {
|
|
|
|
|
|
|
|
|
|
// 找到正确答案的新位置
|
|
|
|
|
int correctIndex = 0;
|
|
|
|
|
String correctAnswerStr = String.format("%.1f", answer);
|
|
|
|
|
for (int i = 0; i < options.length; i++) {
|
|
|
|
|
if (options[i].equals(correctAnswerStr)) {
|
|
|
|
|
if (options[i].equals(correctAnswer)) {
|
|
|
|
|
correctIndex = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -505,6 +682,14 @@ public class QuestionGenerator {
|
|
|
|
|
return new Question(questionText, options, correctIndex, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String formatAnswer(double answer) {
|
|
|
|
|
if (answer == (int) answer) {
|
|
|
|
|
return String.valueOf((int) answer); // 整数不显示小数
|
|
|
|
|
} else {
|
|
|
|
|
return String.format("%.2f", answer); // 小数保留2位
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void shuffleArray(String[] array) {
|
|
|
|
|
for (int i = array.length - 1; i > 0; i--) {
|
|
|
|
|
int j = random.nextInt(i + 1);
|
|
|
|
|
|