package service; import model.Question; import java.util.List; import java.util.ArrayList; import java.util.Stack; public class PrimaryQuestionGenerator extends AbstractQuestionGenerator { private static final String[] OPERATORS = {"+", "-" , "×", "÷"}; public PrimaryQuestionGenerator() { super("小学"); } @Override public Question generateQuestion() { int operandCount = random.nextInt(4) + 2; // 2-5个操作数 List operands = new ArrayList<>(); List operators = new ArrayList<>(); // 生成操作数和运算符,确保结果为非负整数 boolean valid = false; String content = ""; int answer = 0; int attempts = 0; int maxAttempts = 100; // 添加最大尝试次数 while (!valid && attempts < maxAttempts) { attempts++; // 计数 operands.clear(); operators.clear(); // 生成操作数 for (int i = 0; i < operandCount; i++) { operands.add(getRandomOperand()); } // 生成运算符,限制最多只有一个除法 boolean hasDivision = false; for (int i = 0; i < operandCount - 1; i++) { String op; // 如果已经有除法了,就只生成其他运算符 if (hasDivision) { String[] otherOperators = {"+", "-", "×"}; op = getRandomOperator(otherOperators); } else { op = getRandomOperator(OPERATORS); if (op.equals("÷")) { hasDivision = true; // 确保除法能整除:调整被除数 int divisor = operands.get(i + 1); int dividend = operands.get(i); // 如果当前不能整除,调整被除数 if (divisor == 0 || dividend % divisor != 0) { // 如果除数为0,重新生成除数 if (divisor == 0) { divisor = random.nextInt(9) + 2; // 2-10 operands.set(i + 1, divisor); } // 调整被除数为除数的倍数 int multiple = random.nextInt(3) + 1; // 1-3倍 operands.set(i, divisor * multiple); } } } operators.add(op); } content = buildPrimaryContent(operands, operators); answer = calculateExpression(content); valid = answer >= 0; // 验证答案是否非负整数 } // 如果多次尝试都失败,生成一个简单的保底题目 if (!valid) { return generateSimpleQuestion(); } OptionsResult options = generateOptions(answer); return new Question(content, options, options.getCorrectIndex(), difficulty); } // 生成简单的保底题目 private Question generateSimpleQuestion() { int a = random.nextInt(10) + 5; // 5-14 int b = random.nextInt(5) + 1; // 1-5 String[] simpleOps = {"+", "×"}; String op = simpleOps[random.nextInt(simpleOps.length)]; String content; int answer; if (op.equals("+")) { content = a + " + " + b + " = ?"; answer = a + b; } else { content = a + " × " + b + " = ?"; answer = a * b; } OptionsResult options = generateOptions(answer); return new Question(content, options, options.getCorrectIndex(), difficulty); } private String buildPrimaryContent(List operands, List operators) { StringBuilder content = new StringBuilder(); // 随机决定是否加括号(只在有3个及以上操作数时) boolean useParentheses = random.nextDouble() < 0.6 && operands.size() > 2; if (useParentheses) { // 随机决定括号包含的操作数数量(至少2个,最多 operands.size()-1 个) int parenLength = random.nextInt(operands.size() - 1) + 2; // 随机决定括号的起始位置 int start = random.nextInt(operands.size() - parenLength + 1); int end = start + parenLength - 1; for (int i = 0; i < operands.size(); i++) { if (i == start) { content.append("("); } content.append(operands.get(i)); if (i == end) { content.append(")"); } if (i < operators.size()) { content.append(" ").append(operators.get(i)).append(" "); } } } else { for (int i = 0; i < operands.size(); i++) { content.append(operands.get(i)); if (i < operators.size()) { content.append(" ").append(operators.get(i)).append(" "); } } } content.append(" = ?"); return content.toString(); } private int calculateExpression(String expression) { try { // 移除 "= ?" 部分 String mathExpr = expression.replace(" = ?", "").trim(); return evaluate(mathExpr); } catch (Exception e) { return -1; // 计算失败 } } private int evaluate(String expression) { Stack numbers = new Stack<>(); Stack ops = new Stack<>(); for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); if (c == ' ') { continue; // 跳过空格 } if (Character.isDigit(c)) { // 读取完整数字 int num = 0; while (i < expression.length() && Character.isDigit(expression.charAt(i))) { num = num * 10 + (expression.charAt(i) - '0'); i++; } i--; numbers.push(num); } else if (c == '(') { ops.push(c); } else if (c == ')') { // 计算括号内的所有运算 while (ops.peek() != '(') { int result = applyOp(ops.pop(), numbers.pop(), numbers.pop()); if (result < 0) return -1; // 检查中间结果是否负数 numbers.push(result); } ops.pop(); // 弹出 '(' } else if (isOperator(c)) { // 处理运算符优先级:如果栈顶运算符优先级更高或相等,先计算栈顶的 while (!ops.isEmpty() && hasPrecedence(ops.peek(), c)) { int result = applyOp(ops.pop(), numbers.pop(), numbers.pop()); if (result < 0) return -1; // 检查中间结果是否负数 numbers.push(result); } ops.push(c); } } // 计算剩余表达式 while (!ops.isEmpty()) { int result = applyOp(ops.pop(), numbers.pop(), numbers.pop()); if (result < 0) return -1; // 检查中间结果是否负数 numbers.push(result); } return numbers.pop(); } private boolean hasPrecedence(char op1, char op2) { if (op1 == '(' || op1 == ')') { return false; } // op1是栈顶运算符,op2是当前运算符 // 如果栈顶运算符优先级高于或等于当前运算符,返回true(先计算栈顶的) if ((op1 == '×' || op1 == '÷') && (op2 == '+' || op2 == '-')) { return true; } // 同级运算符从左到右计算 if ((op1 == '+' || op1 == '-') && (op2 == '+' || op2 == '-')) { return true; } if ((op1 == '×' || op1 == '÷') && (op2 == '×' || op2 == '÷')) { return true; } return false; } private boolean isOperator(char c) { return c == '+' || c == '-' || c == '×' || c == '÷'; } private int applyOp(char op, int b, int a) { switch (op) { case '+': return a + b; case '-': int result = a - b; return result >= 0 ? result : -1; // 确保非负 case '×': return a * b; case '÷': if (b == 0 || a % b != 0) { return -1; // 除数为0或不整除 } return a / b; default: return -1; } } }