diff --git a/README.md b/README.md deleted file mode 100644 index 187e736..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# 数学试卷生成器 -## 软件2302刘欣睿 - diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000..4670cec --- /dev/null +++ b/doc/README.md @@ -0,0 +1,17 @@ +# 数学卷子生成器 + +## 项目结构 +MathExanGenerater/ +├─ doc/ +│ └─ README.md +└── src/ + ├─ Generator/ +   ├─ QuestionGenerator +   ├─ PrimaryGenerator +   ├─ middleGenerator +   └── highGenerator + ├─ Account + ├─ FileManager + └── Main + + diff --git a/src/Account.java b/src/Account.java new file mode 100644 index 0000000..06a58a9 --- /dev/null +++ b/src/Account.java @@ -0,0 +1,23 @@ +// 账户信息类 +public class Account { + private String username; + private String password; + private String type; // 小学、初中、高中 + + public Account(String username, String password, String type) { + this.username = username; + this.password = password; + this.type = type; + } + + // getters + public String getUsername() { + return username; + } + public String getPassword() { + return password; + } + public String getType() { + return type; + } +} diff --git a/src/FileManager.java b/src/FileManager.java new file mode 100644 index 0000000..ff9417e --- /dev/null +++ b/src/FileManager.java @@ -0,0 +1,78 @@ +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Scanner; + +// 文件管理器类 +public class FileManager { + private String baseDir = "exam_papers"; + + public FileManager() { + // 创建基础目录 + File dir = new File(baseDir); + if ( !dir.exists() ) { + dir.mkdir(); + } + } + + // 为用户创建文件夹 + private String getUserDir(String username) { + String userDir = baseDir + File.separator + username; + File dir = new File(userDir); + if ( !dir.exists() ) { + dir.mkdir(); + } + return userDir; + } + + // 生成文件名 + private String generateFileName() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); + return sdf.format( new Date() ) + ".txt"; + } + + // 保存题目到文件 + public void saveQuestions(String username, List questions) throws IOException { + String userDir = getUserDir(username); + String fileName = generateFileName(); + String filePath = userDir + File.separator + fileName; + + try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) { + for (int i = 0; i < questions.size(); i++) { + writer.println((i + 1) + ". " + questions.get(i)); + if (i < questions.size() - 1) { + writer.println(); // 题目之间空一行 + } + } + } + + System.out.println("题目已保存到: " + filePath); + } + + // 检查题目是否重复(简化版,实际应该更复杂的比较) + public boolean isQuestionDuplicate(String username, String question) { + String userDir = getUserDir(username); + File dir = new File(userDir); + File[] files = dir.listFiles(); + + if (files == null) return false; + + for (File file : files) { + try (Scanner scanner = new Scanner(file)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.contains(question)) { + return true; + } + } + } catch (IOException e) { + // 忽略读取错误 + } + } + return false; + } +} diff --git a/src/Generator/PrimaryGenerator.java b/src/Generator/PrimaryGenerator.java new file mode 100644 index 0000000..c33beb9 --- /dev/null +++ b/src/Generator/PrimaryGenerator.java @@ -0,0 +1,22 @@ +package Generator; + +public class PrimaryGenerator extends QuestionGenerator{ + public PrimaryGenerator() { + super("小学"); + } + + @Override + public String generateQuestion() { + + int operandCount = random.nextInt(4) + 2; + + // 生成操作数 + int[] operands = new int[operandCount]; + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } + + String question = preForOper(operands); + return addParen(question); + } +} diff --git a/src/Generator/QuestionGenerator.java b/src/Generator/QuestionGenerator.java new file mode 100644 index 0000000..a42134b --- /dev/null +++ b/src/Generator/QuestionGenerator.java @@ -0,0 +1,142 @@ +package Generator; + +import java.util.Random; + +public abstract class QuestionGenerator{ + protected Random random = new Random(); + public abstract String generateQuestion() ; + protected String type; + + public String getType() { + return type; + } + + QuestionGenerator() { + type = "无"; + } + + QuestionGenerator(String Type) { + type = Type; + } + + protected String preForOper(int[] operands) { + StringBuilder question = new StringBuilder(); + String[] operators = {"+", "-", "×", "÷"}; + question.append(operands[0]); + + for (int i = 1; i < operands.length; i++) { + String op = operators[ random.nextInt (operators.length)]; + question.append(" ").append(op).append(" ").append(operands[i]); + } + return question.toString(); + + } + + protected boolean Check_num(String expression) { + if(!(expression.equals("+") || expression.equals("-") || expression.equals("×") || expression.equals("÷"))) { + return true; + } + else{ + return false; + } + } + + protected String addParen(String expression) { + String[] parts = expression.split(" "); + StringBuilder result = new StringBuilder(); + boolean r_paren_needed = false; + + for (int i = 0; i < parts.length; i++) { + if(Check_num ( parts [i]) ) { + if( !r_paren_needed ) { + if(i <= parts.length -3 ) + { + if( random.nextBoolean() ) + { result.append("(");r_paren_needed = true;} + } + result.append(parts[i]); + } else { + result.append( parts [i]); + if( !random.nextBoolean()) { + result.append(")");r_paren_needed = false; + } + } + } else { + result.append( parts [i] ); + } + if( i < parts.length -1 ) { + result.append(" "); + } + } + + if( r_paren_needed ){ + result.append(")");r_paren_needed = false; + } + return result.toString(); + } + + protected String add_squs(String expression) { + String[] parts = expression.split(" "); + StringBuilder result = new StringBuilder(); + boolean has_squs = false; + + for (int i = 0; i < parts.length; i++) { + if( Check_num( parts [i] )) { + double Thres = 0.3; + if( !has_squs){ + Thres = 0.7; + } + if ( random.nextDouble() < Thres ||(i == parts.length -1 && !has_squs)) { + if ( random.nextBoolean() ) { + result.append(parts[i]); + result.append("²"); + has_squs = true; + } else { + result.append("√"); + result.append(parts[i]); + has_squs = true; + } + } else { + result.append(parts[i]); + } + } else { + result.append(parts[i]); + } + if( i < parts.length -1 ) { + result.append(" "); + } + } + return result.toString(); + } + + protected String add_sins(String expression) { + String[] parts = expression.split(" "); + StringBuilder result = new StringBuilder(); + String[] functions = {"sin", "cos", "tan", "log"}; + boolean has_func = false; + + for (int i = 0; i < parts.length; i++) { + double Thres = 0.4; + if(!has_func){Thres = 0.8;} + if(Check_num(parts[i])) + { + if ( random.nextDouble() < Thres ||(i == parts.length-1 && !has_func) ) { + String func = functions[random.nextInt(functions.length)]; + result.append(func).append("(").append(parts[i]).append(")"); + } else { + result.append(parts[i]); + } + } else { + result.append(parts[i]); + } + if( i < parts.length-1 ) { + result.append(" "); + } + + } + + return result.toString(); + } +} + + diff --git a/src/Generator/highGenerator.java b/src/Generator/highGenerator.java new file mode 100644 index 0000000..5718229 --- /dev/null +++ b/src/Generator/highGenerator.java @@ -0,0 +1,24 @@ +package Generator; + +public class highGenerator extends QuestionGenerator{ + + public highGenerator() { + super("高中"); + } + + @Override + public String generateQuestion() { + int operandCount = random.nextInt(4) + 2; + + // 生成操作数 + int[] operands = new int[ operandCount ]; + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } + + String question = preForOper( operands ); + question = add_squs( question ); + question = add_sins( question ); + return addParen( question ); + } +} diff --git a/src/Generator/middleGenerator.java b/src/Generator/middleGenerator.java new file mode 100644 index 0000000..ec89ca7 --- /dev/null +++ b/src/Generator/middleGenerator.java @@ -0,0 +1,23 @@ +package Generator; + +public class middleGenerator extends QuestionGenerator{ + + public middleGenerator() { + super("初中"); + } + + @Override + public String generateQuestion() { + int operandCount = random.nextInt(4) + 2; + + // 生成操作数 + int[] operands = new int [ operandCount ]; + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } + + String question = preForOper(operands); + question = add_squs(question); + return addParen(question); + } +} \ No newline at end of file diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..ed9c30b --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: MathExamGenerator + diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..5992bed --- /dev/null +++ b/src/Main.java @@ -0,0 +1,181 @@ +import java.io.IOException; +import java.util.*; +import java.util.regex.Pattern; +import Generator.*; + +class MathExamGenerator { + private static List accounts = new ArrayList<>(); + private static Scanner scanner = new Scanner(System.in); + private static QuestionGenerator QuestionGenerator = new PrimaryGenerator(); + private static FileManager fileManager = new FileManager(); + private static Account currentAccount = null; + + // 初始化账户数据 + static { + // 小学账户 + accounts.add(new Account("张三1", "123", "小学")); + accounts.add(new Account("张三2", "123", "小学")); + accounts.add(new Account("张三3", "123", "小学")); + + // 初中账户 + accounts.add(new Account("李四1", "123", "初中")); + accounts.add(new Account("李四2", "123", "初中")); + accounts.add(new Account("李四3", "123", "初中")); + + // 高中账户 + accounts.add(new Account("王五1", "123", "高中")); + accounts.add(new Account("王五2", "123", "高中")); + accounts.add(new Account("王五3", "123", "高中")); + } + + public static void main(String[] args) { + System.out.println("=== 中小学数学卷子自动生成程序 ==="); + + while (true) { + if (currentAccount == null) { + login(); + } else { + generateExam(); + } + } + } + + // 登录功能 + private static void login() { + while (true) { + System.out.print("请输入用户名和密码(用空格隔开,输入exit退出程序): "); + String input = scanner.nextLine().trim(); + + if (input.equalsIgnoreCase("exit")) { + System.exit(0); + } + + String[] credentials = input.split(" "); + if (credentials.length != 2) { + System.out.println("请输入正确的用户名、密码格式(用户名 密码)"); + continue; + } + + String username = credentials[0]; + String password = credentials[1]; + + for (Account account : accounts) { + if (account.getUsername().equals(username) && account.getPassword().equals(password)) { + currentAccount = account; + if( account.getType().equals("小学") ) { + QuestionGenerator = new PrimaryGenerator(); + } + else if( account.getType().equals("初中") ) { + QuestionGenerator = new middleGenerator(); + } + else if( account.getType().equals("高中") ) { + QuestionGenerator = new highGenerator(); + } + + // QuestionGenerator = new QuestionGenerator(account.getType()); + System.out.println("当前选择为 " + QuestionGenerator.getType() + " 出题"); + return; + } + } + + System.out.println("请输入正确的用户名、密码"); + } + } + + // 生成试卷功能 + private static void generateExam() { + while (true) { + System.out.print("准备生成 " + QuestionGenerator.getType() + + " 数学题目,请输入生成题目数量(10-30,输入-1退出当前用户,输入'switch'切换类型): "); + String input = scanner.nextLine().trim(); + + if ( input.equals("-1") ) { + currentAccount = null; + return; + } + + if ( input.startsWith("切换为") ) { + handleSwitchType(input); + continue; + } + + if ( input.equalsIgnoreCase("switch" )) { + System.out.print("请输入要切换的类型(小学/初中/高中): "); + String typeInput = scanner.nextLine().trim(); + handleSwitchType("切换为 " + typeInput); + continue; + } + + try { + int count = Integer.parseInt(input); + if (count >= 10 && count <= 30) { + generateQuestions(count); + } else { + System.out.println("题目数量必须在10-30之间"); + } + } catch (NumberFormatException e) { + System.out.println("请输入有效的数字(10-30)或-1退出"); + } + } + } + + // 处理类型切换 + private static void handleSwitchType(String input) { + Pattern pattern = Pattern.compile("切换为\\s*(小学|初中|高中)"); + var matcher = pattern.matcher(input); + + if ( matcher.matches() ) { + String newType = matcher.group(1); + if( newType.equals("小学") ) { + QuestionGenerator = new PrimaryGenerator(); + } + else if( newType.equals("初中") ) { + QuestionGenerator = new middleGenerator(); + } + else if( newType.equals("高中") ) { + QuestionGenerator = new highGenerator(); + } + //else{ QuestionGenerator = new highGenerator();} + // QuestionGenerator.setType(newType); + // currentAccount.SetType(newType); + System.out.println("已切换为 " + QuestionGenerator.getType() + " 出题"); + //System.out.print("准备生成 " + newType + " 数学题目,请输入生成题目数量: "); + } else { + System.out.println("请输入小学、初中和高中三个选项中的一个"); + } + } + + // 生成题目 + private static void generateQuestions(int count) { + List questions = new ArrayList<>(); + Set generatedQuestions = new HashSet<>(); + + for (int i = 0; i < count; i++) { + String question; + int attempt = 0; + + // 尝试生成不重复的题目 + do { + question = QuestionGenerator.generateQuestion(); + attempt++; + + // 防止无限循环 + if ( attempt > 100 ) { + System.out.println("警告:无法生成足够的不重复题目,可能重复率较高"); + break; + } + } while ( generatedQuestions.contains(question ) || + fileManager.isQuestionDuplicate(currentAccount.getUsername(), question)); + + generatedQuestions.add(question); + questions.add(question); + } + + try { + fileManager.saveQuestions(currentAccount.getUsername(), questions); + System.out.println("成功生成 " + count + " 道题目"); + } catch ( IOException e ) { + System.out.println("保存文件时出错: " + e.getMessage()); + } + } +}