diff --git a/src/main/java/com/ybw/mathapp/service/JuniorHighGenerator.java b/src/main/java/com/ybw/mathapp/service/JuniorHighGenerator.java index 853218c..a14790e 100644 --- a/src/main/java/com/ybw/mathapp/service/JuniorHighGenerator.java +++ b/src/main/java/com/ybw/mathapp/service/JuniorHighGenerator.java @@ -13,7 +13,7 @@ import java.util.Random; * 题目结构包含基本的四则运算和高级运算的组合。 * * @author 杨博文 - * @version 1.0 + * @version 1.1 * @since 2025 */ public class JuniorHighGenerator implements QuestionGenerator { @@ -55,31 +55,36 @@ public class JuniorHighGenerator implements QuestionGenerator { List parts = new ArrayList<>(); int operandCount = random.nextInt(5) + 1; parts = generateBase(operandCount, parts); - // hasAdvancedOp用以检测下面的循环是否加入了高级运算符,如果没有就启动保底 + boolean hasAdvancedOp = false; + if (operandCount == 1) { + // 对于单个操作数,直接添加高级运算符 if ("平方".equals(ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)])) { parts.add("平方"); } else { - parts.add(0, "开根号"); + // 为单个操作数的开根号添加括号 + parts.set(0, "开根号 ( " + parts.get(0) + " )"); } hasAdvancedOp = true; } else { - // 遍历查找左括号的合理位置 - for (int i = 0; i < parts.size() - 2; i++) { + // 遍历所有可能的操作数位置 (索引为偶数) + // 修复:循环条件确保最后一个操作数也能被检查 + for (int i = 0; i < parts.size(); i += 2) { // 只检查操作数索引 (0, 2, 4, ...) // 该位置要为操作数且随机添加括号 if (isNumeric(parts.get(i)) && random.nextBoolean()) { - // 随机数看取出来的是不是开根号运算符 + // 随机选择高级运算符 if ("开根号".equals(ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)])) { parts = generateRoot(parts, i); - } else { // 如果不是开根号就是平方运算 + } else { // 平方运算 parts = generateSquare(parts, i); } hasAdvancedOp = true; - break; + break; // 添加成功后退出循环 } } } + // 启动保底强制加入一个高级运算符 if (!hasAdvancedOp) { parts = forceAddAdvancedOp(parts); @@ -119,10 +124,13 @@ public class JuniorHighGenerator implements QuestionGenerator { public List forceAddAdvancedOp(List parts) { String advancedOp = ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)]; if ("平方".equals(advancedOp)) { - parts.add("平方"); + // 对整个表达式进行平方 + parts.add(0, "("); // 在开头添加左括号 + parts.add(") 平方"); // 在末尾添加右括号和"平方" } else { // 开根号 - parts.set(0, "开根号 ( " + parts.get(0)); - parts.set(parts.size() - 1, parts.get(parts.size() - 1) + " )"); + // 对整个表达式进行开根号 + parts.add(0, "开根号 ( "); // 在开头添加"开根号 ( " + parts.add(" )"); // 在末尾添加" )" } return parts; } @@ -134,26 +142,19 @@ public class JuniorHighGenerator implements QuestionGenerator { * 进行开根号,或者对一段子表达式进行开根号。 * * @param parts 包含表达式各部分的列表 - * @param i 开根号运算的起始位置 + * @param i 开根号运算的起始位置 (操作数索引) * @return 添加了开根号运算的表达式列表 */ public List generateRoot(List parts, int i) { if (random.nextBoolean()) { + // 对单个操作数进行开根号 parts.set(i, "开根号 ( " + parts.get(i) + " )"); } else { - parts.set(i, "开根号 ( " + 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; - } - } - } + // 对子表达式进行开根号 + parts.set(i, "开根号 ( " + parts.get(i)); // 在起始操作数前添加左括号和"开根号 (" + int endIndex = findMatchingEndIndex(parts, i); // 查找匹配的结束操作数索引 + String currentEnd = parts.get(endIndex); + parts.set(endIndex, currentEnd + " )"); // 在结束操作数后添加右括号 } return parts; } @@ -164,23 +165,50 @@ public class JuniorHighGenerator implements QuestionGenerator { *

该方法在表达式指定位置添加平方运算,对一段子表达式进行平方运算。 * * @param parts 包含表达式各部分的列表 - * @param i 平方运算的起始位置 + * @param i 平方运算的起始位置 (操作数索引) * @return 添加了平方运算的表达式列表 */ public List generateSquare(List parts, int i) { - parts.set(i, "(" + parts.get(i)); - // 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况 - if (i == parts.size() - 3) { - parts.set(parts.size() - 1, parts.get(parts.size() - 1) + " )"); + parts.set(i, "(" + parts.get(i)); // 在起始操作数前添加左括号 + int endIndex = findMatchingEndIndex(parts, i); // 查找匹配的结束操作数索引 + String currentEnd = parts.get(endIndex); + parts.set(endIndex, currentEnd + " ) 平方"); // 在结束操作数后添加右括号和"平方" + return parts; + } + + /** + * 辅助方法:查找子表达式的结束操作数索引。 从起始操作数索引 i 开始,随机决定子表达式的结束位置 (必须是操作数索引)。 为了简化,这里选择从 i+2 + * 开始到最后一个操作数之间的随机一个操作数索引。 + * + * @param parts 表达式各部分列表 + * @param i 起始操作数索引 + * @return 结束操作数索引 + */ + private int findMatchingEndIndex(List parts, int i) { + // 获取最后一个操作数的索引 + int lastOperandIndex = parts.size() - 1; + if (lastOperandIndex % 2 != 0) { + lastOperandIndex--; // 如果列表长度是偶数,最后一个元素是运算符,需要减1得到最后一个操作数索引 + } + + // 确保范围是有效的操作数索引 + if (i >= lastOperandIndex) { + return lastOperandIndex; // 如果i已经是最后一个或超出,返回最后一个 + } + + // 在 [i+2, lastOperandIndex] 范围内选择一个操作数索引 (步长为2) + // 确保至少包含一个运算符,所以从i+2开始 + List possibleEndIndices = new ArrayList<>(); + for (int idx = i + 2; idx <= lastOperandIndex; idx += 2) { + possibleEndIndices.add(idx); + } + + if (!possibleEndIndices.isEmpty()) { + // 随机选择一个可能的结束索引 + return possibleEndIndices.get(random.nextInt(possibleEndIndices.size())); } 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 i; } - return parts; } } \ No newline at end of file diff --git a/users.txt b/users.txt deleted file mode 100644 index 69fac9c..0000000 --- a/users.txt +++ /dev/null @@ -1,2 +0,0 @@ -ybw,1798231811@qq.com,Ybw1234 -wsf,3310207578@qq.com,Wsf1234