题目生成修改

huangsihui_branch
柳意 2 months ago
parent a196139e9a
commit 0d80514510

@ -11,7 +11,7 @@ public class QuestionGenerator {
public List<Question> generateQuestions(String level, int count) { public List<Question> generateQuestions(String level, int count) {
List<Question> questions = new ArrayList<>(); List<Question> questions = new ArrayList<>();
Set<String> questionTexts = new HashSet<>(); // 防止重复题目 Set<String> questionTexts = new HashSet<>();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Question question; Question question;
@ -44,225 +44,275 @@ public class QuestionGenerator {
} }
private Question generatePrimaryQuestion(int index) { private Question generatePrimaryQuestion(int index) {
// 小学操作数2-5个确保结果不为负数 int operandCount = random.nextInt(4) + 2;
int operandCount = random.nextInt(4) + 2; // 2-5个操作数
List<Integer> operands = new ArrayList<>(); List<Integer> operands = new ArrayList<>();
List<Character> operators = new ArrayList<>(); List<Character> operators = new ArrayList<>();
// 生成操作数 (1-100) // 生成操作数和运算符,确保结果非负
for (int i = 0; i < operandCount; i++) { generateSafePrimaryExpression(operands, operators, operandCount);
operands.add(random.nextInt(100) + 1);
}
// 生成运算符 (+, -, *, /)
for (int i = 0; i < operandCount - 1; i++) {
operators.add(getRandomOperation("+-*/"));
}
// 构建表达式并计算结果,确保不为负数
String questionText; String questionText;
int result; int result;
int attempts = 0; int attempts = 0;
do { do {
// 随机决定是否使用括号
boolean useParentheses = random.nextBoolean() && operandCount >= 3; boolean useParentheses = random.nextBoolean() && operandCount >= 3;
if (useParentheses) { if (useParentheses) {
// 使用括号的表达式
int parenPos = random.nextInt(operandCount - 1); int parenPos = random.nextInt(operandCount - 1);
StringBuilder sb = new StringBuilder(); questionText = buildParenthesesExpression(operands, operators, parenPos);
result = evaluateWithParentheses(operands, operators, parenPos);
for (int i = 0; i < operandCount; i++) {
if (i == parenPos) {
sb.append("(");
}
sb.append(operands.get(i));
if (i == parenPos + 1) {
sb.append(")");
}
if (i < operandCount - 1) {
sb.append(" ").append(operators.get(i)).append(" ");
}
}
questionText = sb.toString();
result = evaluateExpressionWithParentheses(operands, operators, parenPos);
} else { } else {
// 不使用括号的表达式 questionText = buildSimpleExpression(operands, operators);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < operandCount; i++) {
sb.append(operands.get(i));
if (i < operandCount - 1) {
sb.append(" ").append(operators.get(i)).append(" ");
}
}
questionText = sb.toString();
result = evaluateSequential(operands, operators); result = evaluateSequential(operands, operators);
} }
attempts++; attempts++;
// 如果结果为负数,重新生成操作数和运算符
if (result < 0) { if (result < 0) {
operands.clear(); // 重新生成安全的表达式
operators.clear(); generateSafePrimaryExpression(operands, operators, operandCount);
for (int i = 0; i < operandCount; i++) {
operands.add(random.nextInt(100) + 1);
}
for (int i = 0; i < operandCount - 1; i++) {
operators.add(getRandomOperation("+-*/"));
}
} }
} while (result < 0 && attempts < 10); } while (result < 0 && attempts < 10);
// 如果还是负数,强制使用加法 // 如果还是负数,强制使用加法
if (result < 0) { if (result < 0) {
StringBuilder sb = new StringBuilder(); for (int i = 0; i < operators.size(); i++) {
for (int i = 0; i < operandCount; i++) { operators.set(i, '+');
sb.append(operands.get(i));
if (i < operandCount - 1) {
sb.append(" + ");
}
} }
questionText = sb.toString(); questionText = buildSimpleExpression(operands, operators);
result = operands.stream().mapToInt(Integer::intValue).sum(); result = evaluateSequential(operands, operators);
} }
return generateOptions(questionText + " = ?", result, "小学"); return generateIntOptions(questionText + " = ?", result, "小学");
}
private void generateSafePrimaryExpression(List<Integer> operands, List<Character> operators, int operandCount) {
operands.clear();
operators.clear();
// 首先生成所有操作数
for (int i = 0; i < operandCount; i++) {
operands.add(random.nextInt(100) + 1);
}
// 然后生成安全的运算符序列
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;
}
}
operators.add(op);
}
} }
private Question generateMiddleSchoolQuestion(int index) { private Question generateMiddleSchoolQuestion(int index) {
// 初中操作数1-5个至少包含平方或开根号 int type = random.nextInt(4);
int operandCount = random.nextInt(5) + 1; // 1-5个操作数 MathExpression expression = new MathExpression();
boolean hasSquareOrSqrt = false;
String questionText; switch (type) {
int result; case 0:
int attempts = 0; expression = createSquareExpression();
break;
case 1:
expression = createSqrtExpression();
break;
case 2:
expression = createSquareProductExpression();
break;
case 3:
expression = createSquareDivisionExpression();
break;
}
do { // 确保初中题目结果非负
int type = random.nextInt(4); if (expression.result < 0) {
switch (type) { expression = createSquareExpression(); // 重新生成一个肯定为正的题目
case 0: }
// a² ± b × c
int a = random.nextInt(10) + 1; // 1-10的平方
int b = random.nextInt(100) + 1;
int c = random.nextInt(100) + 1;
char op = random.nextBoolean() ? '+' : '-';
questionText = a + "² " + op + " " + b + " × " + c;
result = (op == '+') ? (a * a + b * c) : (a * a - b * c);
hasSquareOrSqrt = true;
break;
case 1: return generateIntOptions(expression.questionText + " = ?", expression.result, "初中");
// √a ± b }
int sqrtBase = findPerfectSquare(100); // 100以内的完全平方数
int sqrtVal = (int) Math.sqrt(sqrtBase);
int d = random.nextInt(100) + 1;
char op2 = random.nextBoolean() ? '+' : '-';
questionText = "√" + sqrtBase + " " + op2 + " " + d;
result = (op2 == '+') ? (sqrtVal + d) : (sqrtVal - d);
hasSquareOrSqrt = true;
break;
case 2: private MathExpression createSquareExpression() {
// a × b² ± c int a = random.nextInt(10) + 1;
int e = random.nextInt(100) + 1; int b = random.nextInt(100) + 1;
int f = random.nextInt(10) + 1; int c = random.nextInt(100) + 1;
int g = random.nextInt(100) + 1; // 只使用加法确保结果为正
char op3 = random.nextBoolean() ? '+' : '-'; char op = '+';
questionText = e + " × " + f + "² " + op3 + " " + g;
result = (op3 == '+') ? (e * f * f + g) : (e * f * f - g);
hasSquareOrSqrt = true;
break;
default: String questionText = a + "² " + op + " " + b + " × " + c;
// (a + b)² ÷ c int result = a * a + b * c;
int h = random.nextInt(50) + 1;
int i = random.nextInt(50) + 1;
int j = random.nextInt(20) + 1;
questionText = "(" + h + " + " + i + ")² ÷ " + j;
result = (h + i) * (h + i) / j;
hasSquareOrSqrt = true;
break;
}
attempts++;
} while (!hasSquareOrSqrt && attempts < 10);
return generateOptions(questionText + " = ?", result, "初中"); return new MathExpression(questionText, result);
}
private MathExpression createSqrtExpression() {
int sqrtBase = findPerfectSquare(100);
int sqrtVal = (int) Math.sqrt(sqrtBase);
int d = random.nextInt(100) + 1;
// 只使用加法确保结果为正
char op = '+';
String questionText = "√" + sqrtBase + " " + op + " " + d;
int result = sqrtVal + d;
return new MathExpression(questionText, result);
}
private MathExpression createSquareProductExpression() {
int e = random.nextInt(100) + 1;
int f = random.nextInt(10) + 1;
int g = random.nextInt(100) + 1;
// 只使用加法确保结果为正
char op = '+';
String questionText = e + " × " + f + "² " + op + " " + g;
int result = e * f * f + g;
return new MathExpression(questionText, result);
}
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);
String questionText = "(" + h + " + " + i + ")² ÷ " + j;
int result = square / j;
return new MathExpression(questionText, result);
} }
private Question generateHighSchoolQuestion(int index) { private Question generateHighSchoolQuestion(int index) {
// 高中操作数1-5个至少包含sin,cos,tan int type = random.nextInt(4);
int operandCount = random.nextInt(5) + 1; // 1-5个操作数 TrigExpression expression = new TrigExpression();
boolean hasTrigFunction = false;
String questionText; switch (type) {
double result; case 0:
int attempts = 0; expression = createSinExpression();
break;
case 1:
expression = createCosExpression();
break;
case 2:
expression = createTanExpression();
break;
case 3:
expression = createSinCosExpression();
break;
}
// 常见角度值 return generateDoubleOptions(expression.questionText + " = ?", expression.result, "高中");
double[] angles = {0, 30, 45, 60, 90, 120, 135, 150, 180}; }
String[] angleStrs = {"0°", "30°", "45°", "60°", "90°", "120°", "135°", "150°", "180°"};
double[] sinValues = {0, 0.5, Math.sqrt(2)/2, Math.sqrt(3)/2, 1, Math.sqrt(3)/2, Math.sqrt(2)/2, 0.5, 0};
double[] cosValues = {1, Math.sqrt(3)/2, Math.sqrt(2)/2, 0.5, 0, -0.5, -Math.sqrt(2)/2, -Math.sqrt(3)/2, -1};
double[] tanValues = {0, Math.sqrt(3)/3, 1, Math.sqrt(3), Double.POSITIVE_INFINITY, -Math.sqrt(3), -1, -Math.sqrt(3)/3, 0};
do { private TrigExpression createSinExpression() {
int type = random.nextInt(4); String[] angles = {"0°", "30°", "45°", "60°", "90°"};
switch (type) { double[] sinValues = {0, 0.5, 0.71, 0.87, 1.0};
case 0:
// sin(a) ± b
int idx1 = random.nextInt(angles.length);
int b = random.nextInt(100) + 1;
char op = random.nextBoolean() ? '+' : '-';
questionText = "sin(" + angleStrs[idx1] + ") " + op + " " + b;
result = (op == '+') ? (sinValues[idx1] + b) : (sinValues[idx1] - b);
hasTrigFunction = true;
break;
case 1: int idx = random.nextInt(angles.length);
// a × cos(b) int b = random.nextInt(100) + 1;
int a = random.nextInt(100) + 1; // 只使用加法确保结果为正
int idx2 = random.nextInt(angles.length); char op = '+';
questionText = a + " × cos(" + angleStrs[idx2] + ")";
result = a * cosValues[idx2];
hasTrigFunction = true;
break;
case 2: String questionText = "sin(" + angles[idx] + ") " + op + " " + b;
// tan(a) ÷ b (避免tan(90°)) double result = sinValues[idx] + b;
int idx3 = random.nextInt(angles.length);
while (angles[idx3] == 90) {
idx3 = random.nextInt(angles.length);
}
int c = random.nextInt(20) + 1;
questionText = "tan(" + angleStrs[idx3] + ") ÷ " + c;
result = tanValues[idx3] / c;
hasTrigFunction = true;
break;
default: return new TrigExpression(questionText, result);
// sin(a) × cos(b) ± c }
int idx4 = random.nextInt(angles.length);
int idx5 = random.nextInt(angles.length); private TrigExpression createCosExpression() {
int d = random.nextInt(100) + 1; String[] angles = {"0°", "30°", "45°", "60°"};
char op2 = random.nextBoolean() ? '+' : '-'; double[] cosValues = {1.0, 0.87, 0.71, 0.5};
questionText = "sin(" + angleStrs[idx4] + ") × cos(" + angleStrs[idx5] + ") " + op2 + " " + d;
result = (op2 == '+') ? (sinValues[idx4] * cosValues[idx5] + d) : (sinValues[idx4] * cosValues[idx5] - d); int idx = random.nextInt(angles.length);
hasTrigFunction = true; int a = random.nextInt(100) + 1;
break;
} String questionText = a + " × cos(" + angles[idx] + ")";
attempts++; double result = a * cosValues[idx];
} while (!hasTrigFunction && attempts < 10);
return generateOptions(questionText + " = ?", result, "高中"); return new TrigExpression(questionText, result);
}
private TrigExpression createTanExpression() {
String[] angles = {"0°", "30°", "45°", "60°"};
double[] tanValues = {0, 0.58, 1.0, 1.73};
int idx = random.nextInt(angles.length);
int c = random.nextInt(20) + 1;
String questionText = "tan(" + angles[idx] + ") ÷ " + c;
double result = tanValues[idx] / c;
return new TrigExpression(questionText, result);
}
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};
int idx1 = random.nextInt(angles.length);
int idx2 = random.nextInt(angles.length);
int d = random.nextInt(100) + 1;
// 只使用加法确保结果为正
char op = '+';
String questionText = "sin(" + angles[idx1] + ") × cos(" + angles[idx2] + ") " + op + " " + d;
double product = sinValues[idx1] * cosValues[idx2];
double result = product + d;
return new TrigExpression(questionText, result);
} }
// 辅助方法
private char getRandomOperation(String operations) { private char getRandomOperation(String operations) {
return operations.charAt(random.nextInt(operations.length())); return operations.charAt(random.nextInt(operations.length()));
} }
private String buildSimpleExpression(List<Integer> operands, List<Character> 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(" ");
}
}
return sb.toString();
}
private String buildParenthesesExpression(List<Integer> operands, List<Character> 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(" ");
}
}
return sb.toString();
}
private int evaluateSequential(List<Integer> operands, List<Character> operators) { private int evaluateSequential(List<Integer> operands, List<Character> operators) {
int result = operands.get(0); int result = operands.get(0);
for (int i = 0; i < operators.size(); i++) { for (int i = 0; i < operators.size(); i++) {
@ -271,11 +321,8 @@ public class QuestionGenerator {
return result; return result;
} }
private int evaluateExpressionWithParentheses(List<Integer> operands, List<Character> operators, int parenPos) { private int evaluateWithParentheses(List<Integer> operands, List<Character> operators, int parenPos) {
// 先计算括号内的值
int parenResult = calculate(operands.get(parenPos), operands.get(parenPos + 1), operators.get(parenPos)); int parenResult = calculate(operands.get(parenPos), operands.get(parenPos + 1), operators.get(parenPos));
// 构建新的操作数和运算符列表
List<Integer> newOperands = new ArrayList<>(); List<Integer> newOperands = new ArrayList<>();
List<Character> newOperators = new ArrayList<>(); List<Character> newOperators = new ArrayList<>();
@ -293,39 +340,43 @@ public class QuestionGenerator {
} }
} }
// 顺序计算剩余部分
return evaluateSequential(newOperands, newOperators); return evaluateSequential(newOperands, newOperators);
} }
private int calculate(int a, int b, char op) { private int calculate(int a, int b, char op) {
switch (op) { switch (op) {
case '+': return a + b; case '+': return a + b;
case '-': case '-': return Math.max(a - b, 0);
// 确保减法结果不为负数
return Math.max(a - b, 0);
case '*': return a * b; case '*': return a * b;
case '/': case '/': return (b == 0) ? a : a / b;
// 确保除法能整除且除数不为0
if (b == 0) return a;
return a / b;
default: return a + b; default: return a + b;
} }
} }
private int findPerfectSquare(int max) { private int findPerfectSquare(int max) {
// 找到小于等于max的完全平方数 List<Integer> squares = new ArrayList<>();
List<Integer> perfectSquares = new ArrayList<>();
for (int i = 1; i * i <= max; i++) { for (int i = 1; i * i <= max; i++) {
perfectSquares.add(i * i); squares.add(i * i);
} }
return perfectSquares.get(random.nextInt(perfectSquares.size())); return squares.get(random.nextInt(squares.size()));
} }
private Question generateOptions(String questionText, int answer, String level) { private int findDivisor(int number) {
List<Integer> divisors = new ArrayList<>();
for (int i = 2; i <= Math.min(20, number); i++) {
if (number % i == 0) {
divisors.add(i);
}
}
return divisors.isEmpty() ? 1 : divisors.get(random.nextInt(divisors.size()));
}
private Question generateIntOptions(String questionText, int answer, String level) {
String[] options = new String[4]; String[] options = new String[4];
Set<Integer> usedValues = new HashSet<>(); Set<Integer> usedValues = new HashSet<>();
options[0] = String.valueOf(answer); String correctAnswer = String.valueOf(answer);
options[0] = correctAnswer;
usedValues.add(answer); usedValues.add(answer);
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++) {
@ -335,27 +386,25 @@ public class QuestionGenerator {
int range = Math.max(3, Math.abs(answer) / 5 + 1); int range = Math.max(3, Math.abs(answer) / 5 + 1);
int offset = random.nextInt(range * 2 + 1) - range; int offset = random.nextInt(range * 2 + 1) - range;
wrongAnswer = answer + offset; wrongAnswer = answer + offset;
// 确保错误答案不为负数 wrongAnswer = Math.max(wrongAnswer, 0); // 确保错误答案也不为负
wrongAnswer = Math.max(wrongAnswer, 0);
attempts++; attempts++;
} while (usedValues.contains(wrongAnswer) && attempts < 20); if (attempts > 20) {
wrongAnswer = answer + (i + 1) * 10 + 5;
if (usedValues.contains(wrongAnswer)) { break;
wrongAnswer = answer + i * 10 + 5; }
wrongAnswer = Math.max(wrongAnswer, 0); } while (wrongAnswer == answer || usedValues.contains(wrongAnswer));
}
options[i] = String.valueOf(wrongAnswer); options[i] = String.valueOf(wrongAnswer);
usedValues.add(wrongAnswer); usedValues.add(wrongAnswer);
} }
shuffleArray(options); shuffleArray(options);
int correctIndex = findCorrectIndex(options, String.valueOf(answer)); int correctIndex = findCorrectIndex(options, correctAnswer);
return new Question(questionText, options, correctIndex, level); return new Question(questionText, options, correctIndex, level);
} }
private Question generateOptions(String questionText, double answer, String level) { private Question generateDoubleOptions(String questionText, double answer, String level) {
String[] options = new String[4]; String[] options = new String[4];
Set<String> usedValues = new HashSet<>(); Set<String> usedValues = new HashSet<>();
@ -367,11 +416,15 @@ public class QuestionGenerator {
String wrongAnswer; String wrongAnswer;
int attempts = 0; int attempts = 0;
do { do {
double offset = (random.nextDouble() - 0.5) * 2.0; double offset = (random.nextDouble() - 0.5) * Math.max(1, Math.abs(answer) * 0.3);
double wrongValue = answer + offset; double wrongValue = answer + offset;
wrongAnswer = formatDouble(wrongValue); wrongAnswer = formatDouble(Math.max(wrongValue, 0)); // 确保错误答案不为负
attempts++; attempts++;
} while (usedValues.contains(wrongAnswer) && attempts < 20); if (attempts > 20) {
wrongAnswer = formatDouble(answer + (i + 1) * 2.5);
break;
}
} while (usedValues.contains(wrongAnswer) || wrongAnswer.equals(correctAnswer));
options[i] = wrongAnswer; options[i] = wrongAnswer;
usedValues.add(wrongAnswer); usedValues.add(wrongAnswer);
@ -384,21 +437,15 @@ public class QuestionGenerator {
} }
private String formatDouble(double value) { private String formatDouble(double value) {
if (Double.isInfinite(value)) { if (Double.isInfinite(value)) return "∞";
return "∞"; if (Double.isNaN(value)) return "无解";
} if (Math.abs(value) < 0.001) return "0";
if (Double.isNaN(value)) { return String.format("%.2f", value).replaceAll("0*$", "").replaceAll("\\.$", "");
return "无解";
}
// 保留3位小数去除多余的0
return String.format("%.3f", value).replaceAll("0*$", "").replaceAll("\\.$", "");
} }
private int findCorrectIndex(String[] options, String correctAnswer) { private int findCorrectIndex(String[] options, String correctAnswer) {
for (int i = 0; i < options.length; i++) { for (int i = 0; i < options.length; i++) {
if (options[i].equals(correctAnswer)) { if (options[i].equals(correctAnswer)) return i;
return i;
}
} }
return 0; return 0;
} }
@ -411,4 +458,29 @@ public class QuestionGenerator {
array[i] = temp; 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;
}
}
} }
Loading…
Cancel
Save