From 16ae5713e34be24d185d2f98f83f346edaa36234 Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:54:33 +0800 Subject: [PATCH 01/11] ADD file via upload --- src/BracketManager.java | 148 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 src/BracketManager.java diff --git a/src/BracketManager.java b/src/BracketManager.java new file mode 100644 index 0000000..ce53f57 --- /dev/null +++ b/src/BracketManager.java @@ -0,0 +1,148 @@ +import java.util.List; +import java.util.Random; + +/** + * 负责生成并添加括号 + */ +public class BracketManager { + private static final Random RANDOM = new Random(); + + /** + * 根据元素个数选择括号对数 + * 3 -> 80% 1对 20%0对 + * 4 -> 90% 1对 10%2对 + * 5 -> 50% 1对 50%2对 + */ + public int decideParenthesesPairs(int numCount) { + return switch (numCount) { + case 3 -> RANDOM.nextDouble() < 0.8 ? 1 : 0; + case 4 -> RANDOM.nextDouble() < 0.9 ? 1 : 2; + case 5 -> RANDOM.nextDouble() < 0.5 ? 1 : 2; + default -> 0; + }; + } + + // 添加括号 + public String addParentheses(String expression, int pairs, List numPositions) { + String[] tokens = expression.split(" "); + int numCount = numPositions.size(); + boolean[] markLeft = new boolean[numCount]; + boolean[] markRight = new boolean[numCount]; + + generateBracketPositions(numCount, numPositions, pairs, tokens, markLeft, markRight); + String result = insertBrackets(tokens, markLeft, markRight); + return validateParentheses(result) ? result : expression; + } + + //计算生成括号的位置 + private void generateBracketPositions(int numCount, List numPositions, int pairs, String[] tokens, + boolean[] markLeft, boolean[] markRight) { + int attempts = 0; + for (int p = 0; p < pairs && attempts < 50; p++, attempts++) { + boolean placed = false; + for (int tries = 0; tries < 50 && !placed; tries++) { + int start = RANDOM.nextInt(numCount - 1); + int end = start + 1 + RANDOM.nextInt(numCount - start - 1); + if (end >= numCount) end = numCount - 1; + + // 20%概率尝试嵌套在已有括号内部 + if (RANDOM.nextDouble() < 0.2) { + for (int i = 0; i < numCount; i++) { + if (markLeft[i]) { + start = i; + end = i + RANDOM.nextInt(numCount - i); + break; + } + } + } + + if (canPlaceBracket(start, end, markLeft, markRight, numPositions, tokens)) { + markLeft[start] = true; + markRight[end] = true; + placed = true; + } + } + } + } + + //检测添加括号的合法性 + private boolean canPlaceBracket(int start, int end, boolean[] markLeft, boolean[] markRight, + List numPositions, String[] tokens) { + if (isOuterMostBracket(start, end, markLeft.length)) return false; + if (isInvalidOverlap(start, end, markLeft, markRight)) return false; + return isValidBracketRange(tokens, numPositions, start, end); + } + + //避免最外层括号 + private boolean isOuterMostBracket(int start, int end, int numCount) { + return start == 0 && end == numCount - 1; + } + + //允许嵌套但禁止交叉 + private boolean isInvalidOverlap(int start, int end, boolean[] markLeft, boolean[] markRight) { + for (int i = start; i <= end; i++) { + // start/end可重合,内部禁止已有左右括号 + if ((i != start && markLeft[i]) || (i != end && markRight[i])) return true; + } + return false; + } + + //检测括号是否有意义(优先级) + private boolean isValidBracketRange(String[] tokens, List numPositions, int start, int end) { + int opStart = numPositions.get(start) + 1; + int opEnd = numPositions.get(end) - 1; + String firstOp = null; + boolean hasHigherOuterOp = false; + + for (int i = opStart; i <= opEnd; i += 2) { + if (!isNumber(tokens[i])) { + if (firstOp == null) firstOp = tokens[i]; + else if (isDifferentPriority(firstOp, tokens[i])) { + hasHigherOuterOp = true; + break; + } + } + } + return hasHigherOuterOp || firstOp == null; + } + + //比较运算符优先级 + private boolean isDifferentPriority(String op1, String op2) { + int p1 = (op1.equals("+") || op1.equals("-")) ? 1 : 2; + int p2 = (op2.equals("+") || op2.equals("-")) ? 1 : 2; + return p1 != p2; + } + + //插入操作 + private String insertBrackets(String[] tokens, boolean[] markLeft, boolean[] markRight) { + StringBuilder sb = new StringBuilder(); + int numIndex = 0; + for (String token : tokens) { + if (isNumber(token)) { + if (markLeft[numIndex]) sb.append("( "); + sb.append(token); + if (markRight[numIndex]) sb.append(" )"); + numIndex++; + } else { + sb.append(" ").append(token).append(" "); + } + } + return sb.toString(); + } + + //检查括号是否缺失 + private boolean validateParentheses(String expr) { + int balance = 0; + for (char c : expr.toCharArray()) { + if (c == '(') balance++; + if (c == ')') balance--; + if (balance < 0) return false; + } + return balance == 0; + } + + private boolean isNumber(String token) { + try { Integer.parseInt(token); return true; } + catch (NumberFormatException e) { return false; } + } +} From fee2ec55d565cddeb4617692dfb23549368bc837 Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:56:12 +0800 Subject: [PATCH 02/11] Update ExamSystem.java --- src/ExamSystem.java | 81 ++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/src/ExamSystem.java b/src/ExamSystem.java index f307a25..c87489a 100644 --- a/src/ExamSystem.java +++ b/src/ExamSystem.java @@ -1,7 +1,11 @@ import java.util.Scanner; +/** + * 系统界面 + */ public class ExamSystem { private final Scanner scanner = new Scanner(System.in); + public Users login() { Users users = null; while (users == null) { @@ -22,42 +26,57 @@ public class ExamSystem { public void generateProblems(Users users) { while (true) { String input = scanner.nextLine().trim(); - if (input.equals("-1")) { - break; - } + if (input.equals("-1")) break; - ProblemsGenerator generator = switch (users.getType()) { - case "小学" -> new PrimaryProblem(); - case "初中" -> new JuniorProblem(); - case "高中" -> new SeniorProblem(); - default -> null; - }; - - if (input.startsWith("切换为")) { - String target = input.replace("切换为", ""); - if (target.equals("小学") || target.equals("初中") || target.equals("高中")) { - users = new Users(users.getName(), users.getPassword(), target); - System.out.print("系统提示:准备生成" + users.getType() - + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); - } else { - System.out.println("请输入小学、初中和高中三个选项中的一个"); - } + Users newUsers = handleSwitchType(input, users); + if (newUsers != null) { + users = newUsers; continue; } - try { - int num = Integer.parseInt(input); - if (num >= 10 && num <= 30 && generator != null) { - Generator.generate(users, num, generator); - } else { - System.out.println("请输入 10-30 之间的数字"); - } - } catch (NumberFormatException e) { - System.out.println("请输入小学、初中和高中三个选项中的一个"); - } - - System.out.print("准备生成" + users.getType() + ProblemsGenerator generator = getGenerator(users.getType()); + handleGenerate(input, users, generator); + } + } + + private ProblemsGenerator getGenerator(String type) { + return switch (type) { + case "小学" -> new PrimaryProblem(); + case "初中" -> new JuniorProblem(); + case "高中" -> new SeniorProblem(); + default -> null; + }; + } + + private Users handleSwitchType(String input, Users users) { + if (!input.startsWith("切换为")) return null; + + String target = input.replace("切换为", ""); + if (target.equals("小学") || target.equals("初中") || target.equals("高中")) { + Users newUsers = new Users(users.getName(), users.getPassword(), target); + System.out.print("系统提示:准备生成" + newUsers.getType() + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); + return newUsers; + } else { + System.out.println("请输入小学、初中和高中三个选项中的一个"); + return null; } } + + private void handleGenerate(String input, Users users, ProblemsGenerator generator) { + try { + int num = Integer.parseInt(input); + if (num >= 10 && num <= 30 && generator != null) { + Generator.generate(users, num, generator); + } else { + System.out.println("请输入 10-30 之间的数字"); + } + } catch (NumberFormatException e) { + System.out.println("请输入小学、初中和高中三个选项中的一个"); + } + + System.out.print("准备生成" + users.getType() + + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); + } + } From 345f15cf6a6aae63f1d494335b5d9f350530c183 Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:56:57 +0800 Subject: [PATCH 03/11] ADD file via upload --- src/ExpressionBuilder.java | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/ExpressionBuilder.java diff --git a/src/ExpressionBuilder.java b/src/ExpressionBuilder.java new file mode 100644 index 0000000..c9b92e6 --- /dev/null +++ b/src/ExpressionBuilder.java @@ -0,0 +1,51 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class ExpressionBuilder { + private static final Random RANDOM = new Random(); + private static final String[] OPERATORS = {"+", "-", "*", "/"}; + + // 生成基础四则运算表达式 + public String generateBasicExpression(int count) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; i++) { + sb.append(RANDOM.nextInt(100) + 1); + if (i < count - 1) { + sb.append(" ").append(OPERATORS[RANDOM.nextInt(OPERATORS.length)]).append(" "); + } + } + return sb.toString(); + } + + // 获取表达式中数字的位置 + public List getNumberPositions(String expression) { + String[] tokens = expression.split(" "); + List positions = new ArrayList<>(); + for (int i = 0; i < tokens.length; i++) { + if (isNumber(tokens[i])) positions.add(i); + } + return positions; + } + + // 检查是否存在除零 + public boolean hasDivideByZero(String expression) { + String[] tokens = expression.split(" "); + for (int i = 0; i < tokens.length - 1; i++) { + if (tokens[i].equals("/")) { + try { + if (Integer.parseInt(tokens[i + 1]) == 0) return true; + } catch (NumberFormatException e) { + // + } + } + } + return false; + } + + //判断是否为数字位 + private boolean isNumber(String token) { + try { Integer.parseInt(token); return true; } + catch (NumberFormatException e) { return false; } + } +} From 4c0486861bd54fa8ce276adf06bda4a5f8286e8e Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:57:13 +0800 Subject: [PATCH 04/11] Update Generator.java --- src/Generator.java | 83 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/src/Generator.java b/src/Generator.java index e6bb1ef..a8a2fd1 100644 --- a/src/Generator.java +++ b/src/Generator.java @@ -1,31 +1,96 @@ +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.HashSet; +import java.util.Scanner; +import java.util.Set; +/** + * 题目生成器,支持历史查重和文件保存 + */ public class Generator { + + //生成题目并保存到用户文件夹 public static void generate(Users users, int count, ProblemsGenerator problemsGenerator) { + Set history = loadHistory(users); StringBuilder builder = new StringBuilder(); + for (int i = 1; i <= count; i++) { - builder.append(i).append(". ").append(problemsGenerator.generate()).append("\n\n"); + String problem; + int tries = 0; + do { + problem = problemsGenerator.generate(); + tries++; + if (tries >= 20) { + System.out.println("警告:尝试 20 次仍未生成新题目,可能题目库有限。"); + break; + } + } while (history.contains(problem)); + + history.add(problem); + builder.append(i).append(". ").append(problem).append("\n\n"); } + save(users, builder.toString()); System.out.println("题目生成完成。"); } + /** + * 读取用户历史题目 + */ + private static Set loadHistory(Users users) { + Set history = new HashSet<>(); + String safeName = users.getName().replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9_]", "_"); + String folder = "doc/" + safeName; + File dir = new File(folder); + if (!dir.exists()) return history; + + File[] files = dir.listFiles((d, name) -> name.endsWith(".txt")); + if (files != null) { + for (File f : files) { + try (Scanner sc = new Scanner(f)) { + while (sc.hasNextLine()) { + String line = sc.nextLine().trim(); + if (!line.isEmpty() && Character.isDigit(line.charAt(0))) { + int dot = line.indexOf('.'); + if (dot != -1) line = line.substring(dot + 1).trim(); + history.add(line); + } + } + } catch (IOException e) { + e.printStackTrace(); + System.out.println("读取历史题目失败:" + e.getMessage()); + } + } + } + + return history; + } + + /** + * 保存生成题目到文件 + */ private static void save(Users users, String content) { try { - String folder = "doc/" + users.getName(); - java.io.File dir = new java.io.File(folder); - if (!dir.exists()) { - dir.mkdirs(); + String safeName = users.getName().replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9_]", "_"); + String folder = "doc/" + safeName; + File dir = new File(folder); + if (!dir.exists() && !dir.mkdirs()) { + System.out.println("无法创建目录: " + folder); + return; } + String filename = LocalDateTime.now() - .format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss")) + ".txt"; - FileWriter writer = new FileWriter(folder + "/" + filename); - writer.write(content); - writer.close(); + .format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss")) + + "-" + (int) (Math.random() * 1000) + ".txt"; + + try (FileWriter writer = new FileWriter(folder + "/" + filename)) { + writer.write(content); + } } catch (IOException e) { + e.printStackTrace(); System.out.println("保存失败:" + e.getMessage()); } } From 04464953bf00a53d26179cb10718bdd1c47f81d9 Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:57:47 +0800 Subject: [PATCH 05/11] Update JuniorProblem.java --- src/JuniorProblem.java | 65 ++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/src/JuniorProblem.java b/src/JuniorProblem.java index 7ef49b1..c7fad26 100644 --- a/src/JuniorProblem.java +++ b/src/JuniorProblem.java @@ -1,51 +1,36 @@ +import java.util.List; import java.util.Random; +/** + * 生成初中题目 + */ public class JuniorProblem implements ProblemsGenerator { private static final Random RANDOM = new Random(); - private static final String[] OPERATORS = {"+", "-", "*", "/"}; - private static final String[] POW_OPERATORS = {"√", "^2"}; + private final BracketManager bracketManager = new BracketManager(); + private final PowerManager powerManager = new PowerManager(); + private final ExpressionBuilder expressionBuilder = new ExpressionBuilder(); @Override public String generate() { - String primaryExpr = generatePrimaryExpression(); - return addPowerOperators(primaryExpr); - } - - private String generatePrimaryExpression() { - int count = RANDOM.nextInt(4) + 2; - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < count; i++) { - sb.append(RANDOM.nextInt(100) + 1); - if (i < count - 1) { - sb.append(" ").append(OPERATORS[RANDOM.nextInt(OPERATORS.length)]).append(" "); - } - } - return sb.toString(); - } - - private String addPowerOperators(String expr) { - String[] parts = expr.split(" "); - boolean hasPower = false; - - for (int i = 0; i < parts.length; i++) { - if (parts[i].matches("\\d+") && (!hasPower || RANDOM.nextBoolean())) { - String op = POW_OPERATORS[RANDOM.nextInt(POW_OPERATORS.length)]; - parts[i] = op.equals("√") ? "√" + parts[i] : parts[i] + "^2"; - hasPower = true; - } - } - - if (!hasPower) { - for (int i = 0; i < parts.length; i++) { - if (parts[i].matches("\\d+")) { - String op = POW_OPERATORS[RANDOM.nextInt(POW_OPERATORS.length)]; - parts[i] = op.equals("√") ? "√" + parts[i] : parts[i] + "^2"; - break; + String expression; + boolean hasPower; + do { + int numCount = RANDOM.nextInt(5) + 1; + expression = expressionBuilder.generateBasicExpression(numCount); + List numPositions = expressionBuilder.getNumberPositions(expression); + + if (RANDOM.nextDouble() < 0.8) { + int pairs = bracketManager.decideParenthesesPairs(numCount); + if (pairs > 0) { + expression = bracketManager.addParentheses(expression, pairs, numPositions); } } - } + + // 添加幂运算并检查添加是否成功 + expression = powerManager.addPowerOperations(expression, numPositions); + hasPower = expression.contains("^2") || expression.contains("√"); + } while (expressionBuilder.hasDivideByZero(expression) || !hasPower); - return String.join(" ", parts); + return expression; } -} \ No newline at end of file +} From c9d6e7962e60db9c24737705cea00a8fb44a4fff Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:58:08 +0800 Subject: [PATCH 06/11] Update Main.java --- src/Main.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Main.java b/src/Main.java index 2cc2368..765eb2b 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,3 +1,6 @@ +/** + * 主程序 + */ public class Main { public static void main(String[] args) { ExamSystem system = new ExamSystem(); @@ -8,4 +11,4 @@ public class Main { system.generateProblems(users); } } -} \ No newline at end of file +} From a0a7968925e5e58597f8ead0e5bbf437f559e7fa Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:58:30 +0800 Subject: [PATCH 07/11] ADD file via upload --- src/PowerManager.java | 95 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/PowerManager.java diff --git a/src/PowerManager.java b/src/PowerManager.java new file mode 100644 index 0000000..b3ba370 --- /dev/null +++ b/src/PowerManager.java @@ -0,0 +1,95 @@ +import java.util.List; +import java.util.Random; + +/** + * 负责添加幂运算 + */ +public class PowerManager { + private static final Random RANDOM = new Random(); + + // 普通幂运算 + public String addPowerOperations(String expression, List numPositions) { + if (numPositions.isEmpty()) return expression; + + String[] tokens = expression.split(" "); + int targetIndex = chooseTargetIndex(tokens, numPositions, null); + + if (targetIndex != -1) { + tokens[targetIndex] = applyPower(tokens[targetIndex], tokens, targetIndex); + } + + return String.join(" ", tokens); + } + + // 避免加在 trig 已占用的位置,同时避免加在运算符右边 + public String addPowerOperationsAvoid(String expression, List numPositions, List trigPositions) { + if (numPositions.isEmpty()) return expression; + + String[] tokens = expression.split(" "); + int targetIndex = chooseTargetIndex(tokens, numPositions, trigPositions); + + if (targetIndex != -1) { + tokens[targetIndex] = applyPower(tokens[targetIndex], tokens, targetIndex); + } + + return String.join(" ", tokens); + } + + // 选择合适的位置加幂运算 + private int chooseTargetIndex(String[] tokens, List numPositions, List avoidPositions) { + for (int tries = 0; tries < 20; tries++) { + int idx = numPositions.get(RANDOM.nextInt(numPositions.size())); + + if ((avoidPositions == null || !avoidPositions.contains(idx)) && canApplyPower(tokens, idx)) { + return idx; + } + } + return -1; + } + + // 检查该位置是否可以加幂运算 + private boolean canApplyPower(String[] tokens, int index) { + if (!isNumber(tokens[index])) return false; + if (tokens[index].contains("^") || tokens[index].contains("√")) return false; // 避免重复幂运算 + + // 不能加在运算符右边 + if (index > 0) { + String prev = tokens[index - 1]; + if (prev.equals("/") || prev.equals("*") || prev.equals("+") || prev.equals("-")) { + return false; + } + } + return true; + } + + // 应用平方或开方(根号放左括号左侧,平方放右括号右侧) + private String applyPower(String token, String[] tokens, int index) { + boolean useSqrt = RANDOM.nextBoolean(); + + if (useSqrt) { + // 根号放在左括号左侧,如果前面是左括号,则放在括号左边 + if (index > 0 && tokens[index - 1].equals(")")) { + return "√" + token; // 特殊情况,仍然放数字前 + } + if (index > 0 && tokens[index - 1].equals("(")) { + return "√" + token; + } + return "√" + token; + } else { + // 平方放在右括号右侧,如果后面是右括号,则放在括号右边 + if (index < tokens.length - 1 && tokens[index + 1].equals(")")) { + return token + "^2"; + } + return token + "^2"; + } + } + + private boolean isNumber(String token) { + try { + Integer.parseInt(token); + return true; + } catch (NumberFormatException e) { + return false; + } + } +} From 28b0d645981d3718190e680196aafd5d76b842d4 Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:58:52 +0800 Subject: [PATCH 08/11] Update PrimaryProblem.java --- src/PrimaryProblem.java | 55 +++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/src/PrimaryProblem.java b/src/PrimaryProblem.java index 36601e7..a79a5a8 100644 --- a/src/PrimaryProblem.java +++ b/src/PrimaryProblem.java @@ -1,44 +1,29 @@ +import java.util.List; import java.util.Random; +/** + * 生成小学题目 + */ public class PrimaryProblem implements ProblemsGenerator { private static final Random RANDOM = new Random(); - private static final String[] OPERATORS = {"+", "-", "*", "/"}; + private final BracketManager bracketManager = new BracketManager(); + private final ExpressionBuilder expressionBuilder = new ExpressionBuilder(); @Override public String generate() { - int count = RANDOM.nextInt(4) + 2; - StringBuilder sb = new StringBuilder(); - - boolean addParentheses = count >= 3 && RANDOM.nextDouble() < 0.5; - if (addParentheses) { - int parenCount = RANDOM.nextInt(count - 2) + 2; - int startPos = RANDOM.nextInt(count - parenCount + 1); - - for (int i = 0; i < count; i++) { - if (i == startPos) { - sb.append("( "); - } - - int num = RANDOM.nextInt(100) + 1; - sb.append(num); - - if (i == startPos + parenCount - 1) { - sb.append(" )"); - } - - if (i < count - 1) { - sb.append(" ").append(OPERATORS[RANDOM.nextInt(OPERATORS.length)]).append(" "); - } - } - } else { - for (int i = 0; i < count; i++) { - int num = RANDOM.nextInt(100) + 1; - sb.append(num); - if (i < count - 1) { - sb.append(" ").append(OPERATORS[RANDOM.nextInt(OPERATORS.length)]).append(" "); - } + String expression; + do { + int numCount = 2 + RANDOM.nextInt(4); + expression = expressionBuilder.generateBasicExpression(numCount); + + List numPositions = expressionBuilder.getNumberPositions(expression); + int pairs = bracketManager.decideParenthesesPairs(numCount); + if (pairs > 0) { + expression = bracketManager.addParentheses(expression, pairs, numPositions); } - } - return sb.toString(); + + } while (expressionBuilder.hasDivideByZero(expression)); + + return expression; } -} \ No newline at end of file +} From 44062e673aa0c5daaae1fb3c0def430665707f7b Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:59:22 +0800 Subject: [PATCH 09/11] Update SeniorProblem.java --- src/SeniorProblem.java | 122 ++++++++++------------------------------- 1 file changed, 29 insertions(+), 93 deletions(-) diff --git a/src/SeniorProblem.java b/src/SeniorProblem.java index 72cae10..fe22fe5 100644 --- a/src/SeniorProblem.java +++ b/src/SeniorProblem.java @@ -1,107 +1,43 @@ +import java.util.List; import java.util.Random; +/** + * 生成高中题目 + */ public class SeniorProblem implements ProblemsGenerator { private static final Random RANDOM = new Random(); - private static final String[] OPERATORS = {"+", "-", "*", "/"}; - private static final String[] POW_OPERATORS = {"√", "^2"}; - private static final String[] TRIG_OPERATORS = {"sin", "cos", "tan"}; + private final BracketManager bracketManager = new BracketManager(); + private final PowerManager powerManager = new PowerManager(); + private final TrigManager trigManager = new TrigManager(); + private final ExpressionBuilder expressionBuilder = new ExpressionBuilder(); @Override public String generate() { - String primaryExpression = generatePrimaryExpression(); - - return addHighSchoolOperators(primaryExpression); - } - - private String generatePrimaryExpression() { - int count = RANDOM.nextInt(4) + 2; - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < count; i++) { - int num = RANDOM.nextInt(100) + 1; - sb.append(num); - if (i < count - 1) { - sb.append(" ").append(OPERATORS[RANDOM.nextInt(OPERATORS.length)]).append(" "); - } - } - return sb.toString(); - } - - private String addHighSchoolOperators(String primaryExpression) { - String[] parts = primaryExpression.split(" "); - StringBuilder result = new StringBuilder(); - boolean hasTrigonometry = false; - boolean hasAlgebra = false; - - for (int i = 0; i < parts.length; i++) { - String part = parts[i]; + String expression; + boolean hasTrig; + do { + int numCount = RANDOM.nextInt(5) + 1; + expression = expressionBuilder.generateBasicExpression(numCount); + List numPositions = expressionBuilder.getNumberPositions(expression); - if (isNumber(part)) { - if (!hasTrigonometry || RANDOM.nextDouble() < 0.6) { - part = applyTrigOperator(part); - hasTrigonometry = true; - } - else if (RANDOM.nextDouble() < 0.3) { - part = applyAlgebraOperator(part); - hasAlgebra = true; + if (RANDOM.nextDouble() < 0.8) { + int pairs = bracketManager.decideParenthesesPairs(numCount); + if (pairs > 0) { + expression = bracketManager.addParentheses(expression, pairs, numPositions); } } - result.append(part); - if (i < parts.length - 1) { - result.append(" "); - } - } - - if (!hasTrigonometry) { - return addTrigonometryForced(result.toString()); - } - - return result.toString(); - } - - private boolean isNumber(String str) { - try { - Integer.parseInt(str); - return true; - } catch (NumberFormatException e) { - return false; - } - } - - private String applyTrigOperator(String number) { - String operator = TRIG_OPERATORS[RANDOM.nextInt(TRIG_OPERATORS.length)]; - int num = Integer.parseInt(number); - int angle = generateValidAngle(operator); - return operator + angle + "°"; - } - - private String applyAlgebraOperator(String number) { - String operator = POW_OPERATORS[RANDOM.nextInt(POW_OPERATORS.length)]; - int num = Integer.parseInt(number); - return operator.equals("√") ? "√" + num : num + "^2"; - } - - private int generateValidAngle(String trigOp) { - int angle = RANDOM.nextInt(100) + 1; - if (trigOp.equals("tan")) { - while (angle == 90) { - angle = RANDOM.nextInt(100) + 1; - } - } - return angle; - } - - private String addTrigonometryForced(String expression) { - String[] parts = expression.split(" "); - - for (int i = 0; i < parts.length; i++) { - if (isNumber(parts[i])) { - parts[i] = applyTrigOperator(parts[i]); - break; + // 添加三角函数并检查是否存在 + expression = trigManager.addTrigOperations(expression, numPositions); + List trigPositions = expressionBuilder.getNumberPositions(expression); + hasTrig = expression.contains("sin") || expression.contains("cos") || expression.contains("tan"); + + // 40% 概率加幂运算,避免与 trig 重叠 + if (RANDOM.nextDouble() < 0.4) { + expression = powerManager.addPowerOperationsAvoid(expression, numPositions, trigPositions); } - } + } while (expressionBuilder.hasDivideByZero(expression) || !hasTrig); - return String.join(" ", parts); + return expression; } -} \ No newline at end of file +} From 5ff952dbedd2e5a4c503bf33c6eba101181d5e25 Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 00:59:39 +0800 Subject: [PATCH 10/11] ADD file via upload --- src/TrigManager.java | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/TrigManager.java diff --git a/src/TrigManager.java b/src/TrigManager.java new file mode 100644 index 0000000..f5fcc91 --- /dev/null +++ b/src/TrigManager.java @@ -0,0 +1,70 @@ +import java.util.List; +import java.util.Random; + +/** + * 负责添加三角函数 + */ +public class TrigManager { + private static final Random RANDOM = new Random(); + private static final String[] TRIG_FUNCTIONS = {"sin", "cos", "tan"}; + + //添加三角函数 + public String addTrigOperations(String expression, List numPositions) { + if (numPositions.isEmpty()) { + return expression; + } + + String[] tokens = expression.split(" "); + int targetIndex = chooseTargetIndex(numPositions, tokens); + if (targetIndex == -1) { + return expression; + } + + tokens[targetIndex] = applyTrig(tokens[targetIndex]); + return String.join(" ", tokens); + } + + //随机函数种类 + private int chooseTargetIndex(List numPositions, String[] tokens) { + for (int tries = 0; tries < 50; tries++) { + int idx = numPositions.get(RANDOM.nextInt(numPositions.size())); + if (canApplyTrig(tokens, idx)) { + return idx; + } + } + return -1; + } + + //检测三角函数是否合法 + private boolean canApplyTrig(String[] tokens, int index) { + if (!isNumber(tokens[index])) { + return false; + } + int value = Integer.parseInt(tokens[index]); + + // 防止 tan(90) + if (value == 90 && RANDOM.nextInt(3) == 2) { + return false; + } + // cos(90) 不加在除法右边 + if (index > 0 && tokens[index - 1].equals("/") && value == 90) { + return false; + } + return true; + } + + //添加操作 + private String applyTrig(String token) { + String func = TRIG_FUNCTIONS[RANDOM.nextInt(TRIG_FUNCTIONS.length)]; + return func + "(" + token + ")"; + } + + private boolean isNumber(String token) { + try { + Integer.parseInt(token); + return true; + } catch (NumberFormatException e) { + return false; + } + } +} From ccf30dd651480b07b43ffd559d3477c82052f19c Mon Sep 17 00:00:00 2001 From: hnu202326010305 <1405671544@qq.com> Date: Sun, 28 Sep 2025 01:00:12 +0800 Subject: [PATCH 11/11] Update Users.java --- src/Users.java | 89 ++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/src/Users.java b/src/Users.java index b77898d..1882ed6 100644 --- a/src/Users.java +++ b/src/Users.java @@ -1,44 +1,47 @@ -public class Users { - private final String name; - private final String password; - private final String type; - - private static final Users[] USERS = { - new Users("张三1", "123", "小学"), - new Users("张三2", "123", "小学"), - new Users("张三3", "123", "小学"), - new Users("李四1", "123", "初中"), - new Users("李四2", "123", "初中"), - new Users("李四3", "123", "初中"), - new Users("王五1", "123", "高中"), - new Users("王五2", "123", "高中"), - new Users("王五3", "123", "高中") - }; - - public Users(String name, String password, String type) { - this.name = name; - this.password = password; - this.type = type; - } - - public String getType() { - return type; - } - - public String getName() { - return name; - } - - public String getPassword() { - return password; - } - - public static Users login(String name, String password) { - for (Users users : USERS) { - if (users.getName().equals(name) && users.getPassword().equals(password)) { - return users; - } - } - return null; - } +/** + * 存储用户信息 + */ +public class Users { + private final String name; + private final String password; + private final String type; + + private static final Users[] USERS = { + new Users("张三1", "123", "小学"), + new Users("张三2", "123", "小学"), + new Users("张三3", "123", "小学"), + new Users("李四1", "123", "初中"), + new Users("李四2", "123", "初中"), + new Users("李四3", "123", "初中"), + new Users("王五1", "123", "高中"), + new Users("王五2", "123", "高中"), + new Users("王五3", "123", "高中") + }; + + public Users(String name, String password, String type) { + this.name = name; + this.password = password; + this.type = type; + } + + public String getType() { + return type; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public static Users login(String name, String password) { + for (Users users : USERS) { + if (users.getName().equals(name) && users.getPassword().equals(password)) { + return users; + } + } + return null; + } } \ No newline at end of file