package com.mathapp.problemGenerators; import com.mathapp.models.Equation; import com.mathapp.models.Operator; import java.util.ArrayList; import java.util.List; /** * 高中题目生成器(最终修正版)。 * 采用更稳健的“追加”策略,从根本上避免所有索引越界和除零错误。 */ public class HighSchoolProblemGenerator extends MiddleSchoolProblemGenerator { private static final int[] PREDEFINED_ANGLES = {0, 30, 45, 60, 90}; private static final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"}; @Override protected Equation createProblem() { // 1. 调用父类方法生成一个包含平方或开方的基础题目 Equation middleSchoolEquation = super.createProblem(); List operands = new ArrayList<>(middleSchoolEquation.operands()); List operators = new ArrayList<>(middleSchoolEquation.operators()); String trigExpression; Operator connectingOperator; // 2.【最终修正策略】使用健壮性检查循环,直到生成一个绝对安全的组合 while (true) { // 2a. 生成三角函数部分,并确保它不是 tan(90°) String function; int angleInDegrees; do { function = TRIG_FUNCTIONS[random.nextInt(TRIG_FUNCTIONS.length)]; angleInDegrees = PREDEFINED_ANGLES[random.nextInt(PREDEFINED_ANGLES.length)]; } while (function.equals("tan") && angleInDegrees == 90); trigExpression = String.format("%s(%s)", function, getRadianString(angleInDegrees)); // 2b. 随机选择一个连接运算符 connectingOperator = Operator.values()[random.nextInt(Operator.values().length)]; // 2c.【健壮性检查】检查这个新运算符是否会与三角函数的值构成除零错误 boolean isTrigValueZero = (function.equals("sin") && angleInDegrees == 0) || (function.equals("tan") && angleInDegrees == 0); // 如果新运算符是除法,且三角函数的值是0,则这是一个非法组合,必须重试 if (connectingOperator == Operator.DIVIDE && isTrigValueZero) { continue; // 非法组合,重新循环 } // 如果代码能执行到这里,说明组合是安全的,可以退出循环 break; } // 3.【安全的追加操作】将生成的安全组合追加到表达式末尾 // 这种方法永远不会导致 IndexOutOfBoundsException operands.add(trigExpression); operators.add(connectingOperator); return new Equation(operands, operators); } /** * 将特殊的角度值转换为 exp4j 可以计算的、基于 pi 的弧度字符串。 */ private String getRadianString(int angleInDegrees) { switch (angleInDegrees) { case 0: return "0"; case 30: return "pi/6"; case 45: return "pi/4"; case 60: return "pi/3"; case 90: return "pi/2"; default: return "0"; } } }