You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
TestSystem/src/main/java/com/mathapp/problemGenerators/HighSchoolProblemGenerator....

77 lines
2.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<String> operands = new ArrayList<>(middleSchoolEquation.operands());
List<Operator> 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";
}
}
}