package mathpuzzle.service; import static mathpuzzle.service.PrimarySchoolGenerator.isNumeric; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * 高中题目生成器 题目必须包含至少一个 sin, cos, tan 三角函数运算符 */ public class SeniorHighGenerator implements QuestionGenerator { private static final String[] TRIG_FUNCS = {"sin", "cos", "tan"}; private static final String[] OPERATORS = {"+", "-", "*", "/"}; private final Random random = new Random(); @Override public List generateQuestions(int count) { List questions = new ArrayList<>(); for (int i = 0; i < count; i++) { String question = generateSingleQuestion(); questions.add(question); } return questions; } private String generateSingleQuestion() { List parts = new ArrayList<>(); int operandCount = random.nextInt(5) + 1; parts = generateBase(operandCount, parts); String advancedOp; // hasAdvancedOp用以检测下面的循环是否加入了高级运算符,如果没有就启动保底 if (operandCount == 1) { advancedOp = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)]; parts.set(0, advancedOp + parts.get(0)); } else { // 遍历查找左括号的合理位置 for (int i = 0; i < parts.size(); i++) { // 最后一次循环保底生成高中三角函数 if (i == parts.size() - 1) { advancedOp = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)]; parts.set(i, advancedOp + parts.get(i)); } else if (isNumeric(parts.get(i)) && random.nextBoolean()) {// 随机数看是否为操作数且随即进入生成程序 // 进入随机生成tan\sin\cos的程序 parts = generateTrig(parts, i); break; } } } return String.join(" ", parts) + " ="; } // 产生基本操作 public List generateBase(int operandCount, List parts) { for (int i = 0; i < operandCount; i++) { int num = random.nextInt(100) + 1; parts.add(String.valueOf(num)); if (i < operandCount - 1) { parts.add(OPERATORS[random.nextInt(OPERATORS.length)]); } } return parts; } // 产生三角函数运算符 public List generateTrig(List parts, int i) { String trigOp = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)]; if (random.nextBoolean()) { parts.set(i, trigOp + parts.get(i)); } else { parts.set(i, trigOp + "(" + parts.get(i)); // 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况 if (i == parts.size() - 3) { parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")"); } else { while (true) { int i2 = random.nextInt(parts.size() - 3 - i) + 2; if (isNumeric(parts.get(i + i2))) { parts.set(i + i2, parts.get(i + i2) + ")"); break; } } } } return parts; } }