diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f68d109..0000000 --- a/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -### 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 deleted file mode 100644 index 359bb53..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index ec4453f..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 6f29fee..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index d26ca7f..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index d843f34..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MathSystem.iml b/MathSystem.iml deleted file mode 100644 index c90834f..0000000 --- a/MathSystem.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file 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 + diff --git a/src/Main.java b/src/Main.java deleted file mode 100644 index 3b77df8..0000000 --- a/src/Main.java +++ /dev/null @@ -1,393 +0,0 @@ -//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