From f201473d99437e487826a790901cee1984d776c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=A8=E9=BB=98=E6=B6=B5?=
<15530826+wgll926@user.noreply.gitee.com>
Date: Thu, 25 Sep 2025 17:01:08 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E7=A8=B3=E5=AE=9A=E7=89=88=E6=9C=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 29 ++++
.idea/.gitignore | 3 +
.idea/encodings.xml | 7 +
.idea/misc.xml | 6 +
.idea/modules.xml | 8 +
.idea/vcs.xml | 4 +
MathSystem.iml | 11 ++
src/Main.java | 393 ++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 461 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.gitignore
create mode 100644 .idea/encodings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/vcs.xml
create mode 100644 MathSystem.iml
create mode 100644 src/Main.java
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f68d109
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+### IntelliJ IDEA ###
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..359bb53
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..ec4453f
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..6f29fee
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..d26ca7f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..d843f34
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/MathSystem.iml b/MathSystem.iml
new file mode 100644
index 0000000..c90834f
--- /dev/null
+++ b/MathSystem.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Main.java b/src/Main.java
new file mode 100644
index 0000000..3b77df8
--- /dev/null
+++ b/src/Main.java
@@ -0,0 +1,393 @@
+//TIP 要运行代码,请按 或
+// 点击装订区域中的 图标。
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+public class Main {
+ enum Level {
+ 小学, 初中, 高中
+ }
+
+ static class Account {
+ final String username;
+ final String password;
+ final Level level;
+
+ Account(String username, String password, Level level) {
+ this.username = username;
+ this.password = password;
+ this.level = level;
+ }
+ }
+
+ private static final Map USER_MAP = new HashMap<>();
+ private static final String OUTPUT_ROOT = "papers"; // 每个账号一个子文件夹
+ private static final Random RANDOM = new Random();
+
+ public static void main(String[] args) {
+ initAccounts();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
+ while (true) {
+ Account login = loginLoop(reader);
+ if (login == null) {
+ break;
+ }
+ Level currentLevel = login.level;
+ System.out.println("当前选择为" + currentLevel + "出题");
+ // 登录后的工作循环
+ while (true) {
+ System.out.println("准备生成" + currentLevel + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录)");
+ String line = readLineTrim(reader);
+ if (line == null) return; // EOF
+ // 支持命令:切换为XX
+ if (line.startsWith("切换为")) {
+ String target = line.substring("切换为".length()).trim();
+ Level targetLevel = parseLevel(target);
+ if (targetLevel == null) {
+ System.out.println("请输入小学、初中和高中三个选项中的一个");
+ continue;
+ }
+ currentLevel = targetLevel;
+ continue;
+ }
+ int count;
+ try {
+ count = Integer.parseInt(line);
+ } catch (NumberFormatException e) {
+ System.out.println("请输入10-30之间的整数,或-1退出登录,或输入‘切换为XX’");
+ continue;
+ }
+ if (count == -1) {
+ break; // 退出当前账号,重新登录
+ }
+ if (count < 10 || count > 30) {
+ System.out.println("题目数量应为10-30之间(含),或-1退出登录");
+ continue;
+ }
+
+ // 生成题目并去重
+ Set history = loadHistoryQuestions(login.username);
+ List paper = generateUniquePaper(currentLevel, count, history);
+ // 保存
+ try {
+ File saved = savePaper(login.username, paper);
+ System.out.println("已生成并保存:" + saved.getAbsolutePath());
+ } catch (IOException e) {
+ System.out.println("保存失败:" + e.getMessage());
+ }
+ }
+ }
+ }
+
+ private static void initAccounts() {
+ // 小学三个账号
+ USER_MAP.put("张三1", new Account("张三1", "123", Level.小学));
+ USER_MAP.put("张三2", new Account("张三2", "123", Level.小学));
+ USER_MAP.put("张三3", new Account("张三3", "123", Level.小学));
+ // 初中三个账号
+ USER_MAP.put("李四1", new Account("李四1", "123", Level.初中));
+ USER_MAP.put("李四2", new Account("李四2", "123", Level.初中));
+ USER_MAP.put("李四3", new Account("李四3", "123", Level.初中));
+ // 高中三个账号
+ USER_MAP.put("王五1", new Account("王五1", "123", Level.高中));
+ USER_MAP.put("王五2", new Account("王五2", "123", Level.高中));
+ USER_MAP.put("王五3", new Account("王五3", "123", Level.高中));
+ }
+
+ private static Account loginLoop(BufferedReader reader) {
+ while (true) {
+ System.out.println("请输入用户名和密码(用空格分隔),或按Ctrl+D退出:");
+ String line = readLineTrim(reader);
+ if (line == null) return null; // EOF 退出
+ String[] parts = line.split("\\s+");
+ if (parts.length != 2) {
+ System.out.println("请按格式输入");
+ continue;
+ }
+ String username = parts[0];
+ String password = parts[1];
+ Account acc = USER_MAP.get(username);
+ if (acc != null && Objects.equals(acc.password, password)) {
+ return acc;
+ }
+ System.out.println("请输入正确的用户名、密码");
+ }
+ }
+
+ private static String readLineTrim(BufferedReader reader) {
+ try {
+ String s = reader.readLine();
+ if (s == null) return null;
+ return s.trim();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ private static Level parseLevel(String s) {
+ for (Level lv : Level.values()) {
+ if (lv.name().equals(s)) return lv;
+ }
+ return null;
+ }
+
+ private static List generateUniquePaper(Level level, int count, Set history) {
+ Set set = new LinkedHashSet<>();
+ int attempts = 0;
+ int maxAttempts = count * 200; // 足够多的尝试次数以避免死循环
+ while (set.size() < count && attempts < maxAttempts) {
+ String q = generateQuestion(level);
+ attempts++;
+ if (!history.contains(q) && !set.contains(q)) {
+ set.add(q);
+ }
+ }
+ if (set.size() < count) {
+ System.out.println("注意:因去重限制,仅生成" + set.size() + "题");
+ }
+ return new ArrayList<>(set);
+ }
+
+ private static String generateQuestion(Level level) {
+ // 统一表达式末尾不加等号,以字符串完全相等进行去重
+ return switch (level) {
+ case 小学 -> generatePrimary();
+ case 初中 -> generateJunior();
+ case 高中 -> generateSenior();
+ default -> generatePrimary();
+ };
+ }
+
+ private static String generatePrimary() {
+ // 仅使用 +, *, / 和括号,运算数 1-5 个,范围 1-100
+ int operands = 2 + RANDOM.nextInt(4); // 2-5
+ List tokens = new ArrayList<>();
+ int first = 1 + RANDOM.nextInt(100);
+ tokens.add(String.valueOf(first));
+ for (int i = 1; i < operands; i++) {
+ char op = pickOperator("+*/");
+ int n = 1 + RANDOM.nextInt(100);
+ if (op == '/') {
+ // 让被除数尽可能能整除,依据上一个纯数字令除数为其因子
+ int prevNumber = extractLastPureNumber(tokens);
+ if (prevNumber > 0) {
+ n = pickDivisor(prevNumber);
+ }
+ }
+ tokens.add(" " + op + " ");
+ tokens.add(String.valueOf(n));
+ }
+ maybeInsertParentheses(tokens);
+ StringBuilder sb = new StringBuilder();
+ for (String tk : tokens) sb.append(tk);
+ return sb.toString();
+ }
+
+ private static String generateJunior() {
+ // 至少包含一个 平方 或 开根号;允许 + - * / 和括号
+ int operands = 2 + RANDOM.nextInt(4); // 2-5
+ List tokens = new ArrayList<>();
+ String first = String.valueOf(1 + RANDOM.nextInt(100));
+ tokens.add(first);
+ for (int i = 1; i < operands; i++) {
+ char op = pickOperator("+-*/");
+ String n = String.valueOf(1 + RANDOM.nextInt(100));
+ tokens.add(" " + op + " ");
+ tokens.add(n);
+ }
+ // 强制至少包含一个 平方 或 根号
+ ensureJuniorFeature(tokens);
+ maybeInsertParentheses(tokens);
+ StringBuilder sb = new StringBuilder();
+ for (String tk : tokens) sb.append(tk);
+ return sb.toString();
+ }
+
+ private static String generateSenior() {
+ // 至少包含一个 sin/cos/tan;允许 + - * / 和括号
+ int operands = 3 + RANDOM.nextInt(3); // 3-5
+ List tokens = new ArrayList<>();
+ tokens.add(String.valueOf(1 + RANDOM.nextInt(100)));
+ for (int i = 1; i < operands; i++) {
+ char op = pickOperator("+-*/");
+ String n = String.valueOf(1 + RANDOM.nextInt(100));
+ tokens.add(" " + op + " ");
+ tokens.add(n);
+ }
+ ensureSeniorFeature(tokens);
+ maybeInsertParentheses(tokens);
+ StringBuilder sb = new StringBuilder();
+ for (String tk : tokens) sb.append(tk);
+ return sb.toString();
+ }
+
+ private static char pickOperator(String candidates) {
+ int idx = RANDOM.nextInt(candidates.length());
+ return candidates.charAt(idx);
+ }
+
+ private static int lastNumberForDivision(CharSequence currentExpr) {
+ // 粗略解析,找到最后一个数字(用于生成可整除的除法)
+ int i = currentExpr.length() - 1;
+ while (i >= 0 && !Character.isDigit(currentExpr.charAt(i))) i--;
+ int end = i;
+ while (i >= 0 && Character.isDigit(currentExpr.charAt(i))) i--;
+ int start = i + 1;
+ if (start <= end) {
+ return Integer.parseInt(currentExpr.subSequence(start, end + 1).toString());
+ }
+ return 1 + RANDOM.nextInt(100);
+ }
+
+ private static int pickDivisor(int dividend) {
+ dividend = Math.abs(dividend);
+ if (dividend == 0) return 1;
+ List divisors = new ArrayList<>();
+ for (int d = 1; d <= Math.min(dividend, 100); d++) {
+ if (dividend % d == 0) {
+ divisors.add(d);
+ }
+ }
+ return divisors.get(RANDOM.nextInt(divisors.size()));
+ }
+
+ private static String buildExpressionWithParentheses(List numbers, List ops) {
+ // 已不再使用该构造器于主流程,保留供兼容
+ List tokens = new ArrayList<>();
+ tokens.add(String.valueOf(numbers.get(0)));
+ for (int i = 0; i < ops.size(); i++) {
+ char op = ops.get(i);
+ int n = numbers.get(i + 1);
+ tokens.add(" " + op + " ");
+ tokens.add(String.valueOf(n));
+ }
+ maybeInsertParentheses(tokens);
+ StringBuilder sb = new StringBuilder();
+ for (String tk : tokens) sb.append(tk);
+ return sb.toString();
+ }
+
+ private static void maybeInsertParentheses(List tokens) {
+ int parenCount = RANDOM.nextInt(3); // 0,1,2 对
+ for (int k = 0; k < parenCount; k++) {
+ int terms = (tokens.size() + 1) / 2; // 操作数个数
+ if (terms < 3) break;
+ int leftIndex = 0;
+ int rightIndex = 0;
+ for (int t = 0; t < 10; t++) {
+ int li = RANDOM.nextInt(terms - 1);
+ int ri = li + 1 + RANDOM.nextInt(terms - li - 1);
+ leftIndex = li * 2;
+ rightIndex = ri * 2;
+ if (rightIndex - leftIndex >= 4) break; // 至少一个运算符
+ }
+ tokens.add(leftIndex, "(");
+ tokens.add(rightIndex + 2, ")");
+ }
+ }
+
+ private static int extractLastPureNumber(List tokens) {
+ for (int i = tokens.size() - 1; i >= 0; i--) {
+ String tk = tokens.get(i).trim();
+ if (tk.matches("\\d+")) {
+ return Integer.parseInt(tk);
+ }
+ }
+ return -1;
+ }
+
+ private static void ensureJuniorFeature(List tokens) {
+ boolean hasSquareOrSqrt = false;
+ for (String tk : tokens) {
+ if (tk.contains("^2") || tk.contains("√")) { hasSquareOrSqrt = true; break; }
+ }
+ if (!hasSquareOrSqrt) {
+ // 选择一个操作数位置,50% 概率平方,50% 概率开根号
+ List operandIndexes = new ArrayList<>();
+ for (int i = 0; i < tokens.size(); i += 2) operandIndexes.add(i);
+ if (operandIndexes.isEmpty()) return;
+ int idxToken = operandIndexes.get(RANDOM.nextInt(operandIndexes.size()));
+ String val = tokens.get(idxToken).trim();
+ if (RANDOM.nextBoolean()) {
+ // 平方
+ tokens.set(idxToken, val + "^2");
+ } else {
+ // 开根号
+ tokens.set(idxToken, "√(" + val + ")");
+ }
+ }
+ }
+
+ private static void ensureSeniorFeature(List tokens) {
+ boolean hasTrig = false;
+ for (String tk : tokens) {
+ if (tk.contains("sin") || tk.contains("cos") || tk.contains("tan")) { hasTrig = true; break; }
+ }
+ if (!hasTrig) {
+ List operandIndexes = new ArrayList<>();
+ for (int i = 0; i < tokens.size(); i += 2) operandIndexes.add(i);
+ if (operandIndexes.isEmpty()) return;
+ int idxToken = operandIndexes.get(RANDOM.nextInt(operandIndexes.size()));
+ String val = tokens.get(idxToken).trim();
+ String func;
+ switch (RANDOM.nextInt(3)) {
+ case 0: func = "sin"; break;
+ case 1: func = "cos"; break;
+ default: func = "tan"; break;
+ }
+ tokens.set(idxToken, func + "(" + val + ")");
+ }
+ }
+
+ private static Set loadHistoryQuestions(String username) {
+ Set set = new HashSet<>();
+ File folder = new File(OUTPUT_ROOT, username);
+ if (!folder.exists() || !folder.isDirectory()) return set;
+ File[] files = folder.listFiles((dir, name) -> name.endsWith(".txt"));
+ if (files == null) return set;
+ for (File f : files) {
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (line.isEmpty()) continue;
+ int dot = line.indexOf('.') ;
+ if (dot > 0) {
+ String maybe = line.substring(dot + 1).trim();
+ if (!maybe.isEmpty()) set.add(maybe);
+ }
+ }
+ } catch (IOException ignored) {
+ }
+ }
+ return set;
+ }
+
+ private static File savePaper(String username, List questions) throws IOException {
+ File folder = new File(OUTPUT_ROOT, username);
+ if (!folder.exists()) {
+ if (!folder.mkdirs()) throw new IOException("无法创建目录:" + folder.getAbsolutePath());
+ }
+ LocalDateTime now = LocalDateTime.now();
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d-H-m-s");
+ String filename = now.format(formatter) + ".txt";
+ File out = new File(folder, filename);
+ try (BufferedWriter bw = new BufferedWriter(new FileWriter(out, StandardCharsets.UTF_8))) {
+ for (int i = 0; i < questions.size(); i++) {
+ bw.write((i + 1) + ". " + questions.get(i));
+ bw.newLine();
+ bw.newLine();
+ }
+ }
+ return out;
+ }
+}
\ No newline at end of file
--
2.34.1
From 454ba2d656aaba96e4a53730d2d26a678ee158bc Mon Sep 17 00:00:00 2001
From: hnu202326010114 <1961004835@qq.com>
Date: Thu, 25 Sep 2025 17:08:34 +0800
Subject: [PATCH 2/2] Initial commit
---
README.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 README.md
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..58a19f0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# wgll926MathSystem
+
--
2.34.1