hnu202326010114 4 days ago
commit 99d571f24b

@ -0,0 +1,20 @@
1. (19( * 18 * 80)) / 1
2. 25 / 5
3. (58 / 29 / 1 + 98)
4. 34 * (47 / 1 * 59)
5. (48 + 5 + 57) / 3 / 1
6. (16( * 100 / 2))
7. 53 / 1
8. ((81 * 41 / 1))
9. 84 / 2
10. (65 * 11 + 75)

@ -0,0 +1,20 @@
1. 66 / 33 =
2. 98 + 55 =
3. 2 + 88 =
4. ((56 * 80 + 77)) =
5. (80 / 5 + 56) + 60 * 62 =
6. 47 * 62 + 85 * 66 / 1 =
7. 69 / (3 / 1 / 1 + 48) =
8. ((42 + 51 / 51 * )27) =
9. 20 / 1 + 21 / 21 + 27 =
10. 33 * 75 / (1 + 64 + 95) =

@ -33,6 +33,13 @@ public class Main {
private static final String OUTPUT_ROOT = "papers"; // 每个账号一个子文件夹
private static final Random RANDOM = new Random();
// 常量定义
private static final int MIN_QUESTIONS = 10;
private static final int MAX_QUESTIONS = 30;
private static final int MAX_ATTEMPTS_MULTIPLIER = 200;
private static final int MAX_OPERAND_VALUE = 100;
private static final int MIN_OPERAND_VALUE = 1;
public static void main(String[] args) {
initAccounts();
Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8.name());
@ -44,8 +51,8 @@ public class Main {
Level currentLevel = login.level;
System.out.println("当前选择为" + currentLevel + "出题");
// 登录后的工作循环
while (true) {
System.out.println("准备生成" + currentLevel + "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
while (true) {
String line = readLineTrim(scanner);
if (line == null) return; // EOF
// 支持命令切换为XX
@ -57,6 +64,7 @@ public class Main {
continue;
}
currentLevel = targetLevel;
System.out.println("准备生成" + currentLevel + "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
continue;
}
int count;
@ -138,10 +146,15 @@ public class Main {
return null;
}
// 通用的输入验证方法
private static boolean isValidQuestionCount(int count) {
return count >= MIN_QUESTIONS && count <= MAX_QUESTIONS;
}
private static List<String> generateUniquePaper(Level level, int count, Set<String> history) {
Set<String> set = new LinkedHashSet<>();
int attempts = 0;
int maxAttempts = count * 200; // 足够多的尝试次数以避免死循环
int maxAttempts = count * MAX_ATTEMPTS_MULTIPLIER; // 足够多的尝试次数以避免死循环
while (set.size() < count && attempts < maxAttempts) {
String q = generateQuestion(level);
attempts++;
@ -155,27 +168,29 @@ public class Main {
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
//==================== 面向接口的题目生成器 ====================
interface QuestionGenerator {
String generate();
}
// 通用字符串拼接方法,避免重复代码
private static String buildExpression(List<String> tokens) {
StringBuilder sb = new StringBuilder();
for (String tk : tokens) sb.append(tk);
sb.append(" =");
return sb.toString();
}
// 通用的基础表达式生成逻辑
private static List<String> generateBaseExpression(int minOperands, int maxOperands, String operators) {
int operands = minOperands + RANDOM.nextInt(maxOperands - minOperands + 1);
List<String> tokens = new ArrayList<>();
int first = 1 + RANDOM.nextInt(100);
int first = MIN_OPERAND_VALUE + RANDOM.nextInt(MAX_OPERAND_VALUE);
tokens.add(String.valueOf(first));
for (int i = 1; i < operands; i++) {
char op = pickOperator("+*/");
int n = 1 + RANDOM.nextInt(100);
char op = pickOperator(operators);
int n = MIN_OPERAND_VALUE + RANDOM.nextInt(MAX_OPERAND_VALUE);
if (op == '/') {
// 让被除数尽可能能整除,依据上一个纯数字令除数为其因子
int prevNumber = extractLastPureNumber(tokens);
if (prevNumber > 0) {
n = pickDivisor(prevNumber);
@ -184,73 +199,63 @@ public class Main {
tokens.add(" " + op + " ");
tokens.add(String.valueOf(n));
}
maybeInsertParentheses(tokens);
StringBuilder sb = new StringBuilder();
for (String tk : tokens) sb.append(tk);
return sb.toString();
return tokens;
}
private static String generateJunior() {
// 至少包含一个 平方 或 开根号;允许 + - * / 和括号
int operands = 2 + RANDOM.nextInt(4); // 2-5
List<String> 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);
static class PrimaryQuestionGenerator implements QuestionGenerator {
@Override
public String generate() {
List<String> tokens = generateBaseExpression(2, 5, "+*/");
maybeInsertParentheses(tokens);
return buildExpression(tokens);
}
}
// 强制至少包含一个 平方 或 根号
static class JuniorQuestionGenerator implements QuestionGenerator {
@Override
public String generate() {
List<String> tokens = generateBaseExpression(2, 5, "+-*/");
ensureJuniorFeature(tokens);
maybeInsertParentheses(tokens);
StringBuilder sb = new StringBuilder();
for (String tk : tokens) sb.append(tk);
return sb.toString();
return buildExpression(tokens);
}
private static String generateSenior() {
// 至少包含一个 sin/cos/tan允许 + - * / 和括号
int operands = 3 + RANDOM.nextInt(3); // 3-5
List<String> 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);
}
static class SeniorQuestionGenerator implements QuestionGenerator {
@Override
public String generate() {
List<String> tokens = generateBaseExpression(3, 5, "+-*/");
ensureSeniorFeature(tokens);
maybeInsertParentheses(tokens);
StringBuilder sb = new StringBuilder();
for (String tk : tokens) sb.append(tk);
return sb.toString();
return buildExpression(tokens);
}
}
private static char pickOperator(String candidates) {
int idx = RANDOM.nextInt(candidates.length());
return candidates.charAt(idx);
private static final Map<Level, QuestionGenerator> GENERATOR_MAP = new EnumMap<>(Level.class);
static {
GENERATOR_MAP.put(Level., new PrimaryQuestionGenerator());
GENERATOR_MAP.put(Level., new JuniorQuestionGenerator());
GENERATOR_MAP.put(Level., new SeniorQuestionGenerator());
}
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());
private static String generateQuestion(Level level) {
QuestionGenerator generator = GENERATOR_MAP.get(level);
if (generator == null) generator = GENERATOR_MAP.get(Level.);
return generator.generate();
}
return 1 + RANDOM.nextInt(100);
// 生成器实现已迁移到各具体类
private static char pickOperator(String candidates) {
int idx = RANDOM.nextInt(candidates.length());
return candidates.charAt(idx);
}
private static int pickDivisor(int dividend) {
dividend = Math.abs(dividend);
if (dividend == 0) return 1;
List<Integer> divisors = new ArrayList<>();
for (int d = 1; d <= Math.min(dividend, 100); d++) {
for (int d = 1; d <= Math.min(dividend, MAX_OPERAND_VALUE); d++) {
if (dividend % d == 0) {
divisors.add(d);
}
@ -258,21 +263,7 @@ public class Main {
return divisors.get(RANDOM.nextInt(divisors.size()));
}
private static String buildExpressionWithParentheses(List<Integer> numbers, List<Character> ops) {
// 已不再使用该构造器于主流程,保留供兼容
List<String> 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<String> tokens) {
int parenCount = RANDOM.nextInt(3); // 0,1,2 对
@ -353,7 +344,8 @@ public class Main {
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))) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
line = line.trim();

Loading…
Cancel
Save