diff --git a/src/MathQuestion.java b/src/MathQuestion.java new file mode 100644 index 0000000..9b2bf62 --- /dev/null +++ b/src/MathQuestion.java @@ -0,0 +1,39 @@ +/** + * 数学题目类 + * 存储题目表达式和答案 + */ +public class MathQuestion { + private String expression; + private String answer; + + public MathQuestion(String expression, String answer) { + this.expression = expression; + this.answer = answer; + } + + public String getExpression() { + return expression; + } + + public String getAnswer() { + return answer; + } + + @Override + public String toString() { + return expression; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + MathQuestion that = (MathQuestion) obj; + return expression.equals(that.expression); + } + + @Override + public int hashCode() { + return expression.hashCode(); + } +} diff --git a/src/MathQuestionGenerator.java b/src/MathQuestionGenerator.java new file mode 100644 index 0000000..502bff8 --- /dev/null +++ b/src/MathQuestionGenerator.java @@ -0,0 +1,148 @@ +import java.util.*; + +/** + * 数学题目生成器 + * 根据不同难度要求生成数学题目 + */ +public class MathQuestionGenerator { + private Random random; + private String[] operators = {"+", "-", "*", "/"}; + private String[] trigFunctions = {"sin", "cos", "tan"}; + + public MathQuestionGenerator() { + this.random = new Random(); + } + + /** + * 根据账户类型生成题目 + * @param accountType 账户类型(小学、初中、高中) + * @param count 生成题目数量 + * @return 题目列表 + */ + public List generateQuestions(String accountType, int count) { + List questions = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + MathQuestion question; + switch (accountType) { + case "小学": + question = generateElementaryQuestion(); + break; + case "初中": + question = generateMiddleSchoolQuestion(); + break; + case "高中": + question = generateHighSchoolQuestion(); + break; + default: + question = generateElementaryQuestion(); + } + questions.add(question); + } + + return questions; + } + + /** + * 生成小学题目:只能有+、-、*、/和() + */ + private MathQuestion generateElementaryQuestion() { + int operatorCount = random.nextInt(4) + 1; // 1-4个操作符 + List numbers = new ArrayList<>(); + List ops = new ArrayList<>(); + + // 生成数字(1-100) + for (int i = 0; i <= operatorCount; i++) { + numbers.add(random.nextInt(100) + 1); + } + + // 生成操作符 + for (int i = 0; i < operatorCount; i++) { + ops.add(operators[random.nextInt(operators.length)]); + } + + // 构建表达式 + StringBuilder expression = new StringBuilder(); + expression.append(numbers.get(0)); + + for (int i = 0; i < operatorCount; i++) { + expression.append(" ").append(ops.get(i)).append(" ").append(numbers.get(i + 1)); + } + + // 可能添加括号 + if (operatorCount >= 2 && random.nextBoolean()) { + expression = addParentheses(expression.toString()); + } + + return new MathQuestion(expression.toString(), "计算结果"); + } + + /** + * 生成初中题目:至少有一个平方或开根号运算符 + */ + private MathQuestion generateMiddleSchoolQuestion() { + StringBuilder expression = new StringBuilder(); + + // 基础部分 + int num1 = random.nextInt(50) + 1; + String op = operators[random.nextInt(operators.length)]; + + expression.append(num1).append(" ").append(op).append(" "); + + // 添加平方或开根号 + if (random.nextBoolean()) { + // 添加平方 + int baseNum = random.nextInt(20) + 1; + expression.append(baseNum).append("²"); + } else { + // 添加开根号 + int sqrtNum = getRandomPerfectSquare(); + expression.append("√").append(sqrtNum); + } + + return new MathQuestion(expression.toString(), "计算结果"); + } + + /** + * 生成高中题目:至少有一个sin、cos或tan运算符 + */ + private MathQuestion generateHighSchoolQuestion() { + StringBuilder expression = new StringBuilder(); + + // 基础部分 + int num1 = random.nextInt(100) + 1; + String op = operators[random.nextInt(operators.length)]; + + // 添加三角函数 + String trigFunc = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = random.nextInt(360); // 0-359度 + + expression.append(num1).append(" ").append(op).append(" ").append(trigFunc).append("(").append(angle).append("°)"); + + return new MathQuestion(expression.toString(), "计算结果"); + } + + /** + * 为表达式添加括号 + */ + private StringBuilder addParentheses(String expression) { + String[] parts = expression.split(" "); + if (parts.length >= 5) { // 至少有3个数字和2个操作符 + StringBuilder result = new StringBuilder(); + result.append("(").append(parts[0]).append(" ").append(parts[1]).append(" ").append(parts[2]).append(")"); + for (int i = 3; i < parts.length; i++) { + result.append(" ").append(parts[i]); + } + return result; + } + return new StringBuilder(expression); + } + + /** + * 获取随机完全平方数 + */ + private int getRandomPerfectSquare() { + int[] perfectSquares = {1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400}; + return perfectSquares[random.nextInt(perfectSquares.length)]; + } +} diff --git a/src/MathTestGenerator.java b/src/MathTestGenerator.java new file mode 100644 index 0000000..ed274e5 --- /dev/null +++ b/src/MathTestGenerator.java @@ -0,0 +1,196 @@ +import java.util.*; + +/** + * 中小学数学卷子自动生成程序 - 主程序 + * 实现用户登录、题目生成、类型切换等功能 + */ +public class MathTestGenerator { + private UserManager userManager; + private MathQuestionGenerator questionGenerator; + private QuestionManager questionManager; + private Scanner scanner; + private User currentUser; + private String currentAccountType; + + public MathTestGenerator() { + this.userManager = new UserManager(); + this.questionGenerator = new MathQuestionGenerator(); + this.questionManager = new QuestionManager(); + this.scanner = new Scanner(System.in); + this.currentUser = null; + this.currentAccountType = null; + } + + /** + * 程序主入口 + */ + public void run() { + System.out.println("=== 中小学数学卷子自动生成程序 ==="); + + while (true) { + if (currentUser == null) { + // 未登录状态 + if (!login()) { + continue; // 登录失败,重新登录 + } + } else { + // 已登录状态 + handleLoggedInUser(); + } + } + } + + /** + * 处理用户登录 + * @return 登录是否成功 + */ + private boolean login() { + System.out.print("请输入用户名和密码(用空格隔开):"); + System.out.flush(); // 强制刷新输出缓冲区 + + String input = scanner.nextLine().trim(); + + if (input.isEmpty()) { + System.out.println("请输入正确的用户名、密码"); + return false; + } + + String[] credentials = input.split("\\s+"); + if (credentials.length != 2) { + System.out.println("请输入正确的用户名、密码"); + return false; + } + + String username = credentials[0]; + String password = credentials[1]; + + User user = userManager.authenticate(username, password); + if (user != null) { + currentUser = user; + currentAccountType = user.getAccountType(); + System.out.println("当前选择为" + currentAccountType + "出题"); + return true; + } else { + System.out.println("请输入正确的用户名、密码"); + return false; + } + } + + /** + * 处理已登录用户的操作 + */ + private void handleLoggedInUser() { + System.out.print("准备生成" + currentAccountType + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); + System.out.flush(); + + String input = scanner.nextLine().trim(); + + // 检查是否是切换类型命令 + if (input.startsWith("切换为")) { + handleAccountTypeSwitch(input); + return; + } + + try { + int count = Integer.parseInt(input); + + if (count == -1) { + // 退出当前用户 + currentUser = null; + currentAccountType = null; + System.out.println("已退出当前用户"); + return; + } + + if (count < 10 || count > 30) { + System.out.println("题目数量必须在10-30之间,请重新输入"); + return; + } + + // 生成题目 + generateAndSaveQuestions(count); + + } catch (NumberFormatException e) { + System.out.println("请输入有效的数字或切换命令"); + } + } + + /** + * 处理账户类型切换 + * @param input 用户输入 + */ + private void handleAccountTypeSwitch(String input) { + String newType = input.substring(3); // 去掉"切换为" + + if (!userManager.isValidAccountType(newType)) { + System.out.println("请输入小学、初中和高中三个选项中的一个"); + return; + } + + currentAccountType = newType; + System.out.print("准备生成" + currentAccountType + "数学题目,请输入生成题目数量:"); + System.out.flush(); + + String countInput = scanner.nextLine().trim(); + try { + int count = Integer.parseInt(countInput); + + if (count < 10 || count > 30) { + System.out.println("题目数量必须在10-30之间"); + return; + } + + generateAndSaveQuestions(count); + + } catch (NumberFormatException e) { + System.out.println("请输入有效的数字"); + } + } + + /** + * 生成并保存题目 + * @param count 题目数量 + */ + private void generateAndSaveQuestions(int count) { + System.out.println("正在生成" + count + "道" + currentAccountType + "数学题目..."); + + // 生成不重复的题目 + List questions = questionManager.generateUniqueQuestions( + currentAccountType, count, questionGenerator); + + if (questions.size() < count) { + System.out.println("注意:由于去重要求,实际生成了" + questions.size() + "道题目"); + } + + if (questions.isEmpty()) { + System.out.println("无法生成新的题目,可能所有题目都已存在"); + return; + } + + // 保存到文件 + String fileName = questionManager.saveQuestionsToFile(currentAccountType, questions); + if (fileName != null) { + System.out.println("题目已保存到文件:" + currentAccountType + "/" + fileName); + System.out.println("共生成" + questions.size() + "道题目"); + + // 显示前几道题目作为预览 + System.out.println("\n题目预览:"); + for (int i = 0; i < Math.min(3, questions.size()); i++) { + System.out.println((i + 1) + ". " + questions.get(i).getExpression()); + } + if (questions.size() > 3) { + System.out.println("..."); + } + } else { + System.out.println("保存文件失败"); + } + } + + /** + * 程序入口点 + */ + public static void main(String[] args) { + MathTestGenerator generator = new MathTestGenerator(); + generator.run(); + } +} diff --git a/src/QuestionManager.java b/src/QuestionManager.java new file mode 100644 index 0000000..ad3c8f7 --- /dev/null +++ b/src/QuestionManager.java @@ -0,0 +1,162 @@ +import java.io.*; +import java.nio.file.*; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * 题目管理器 + * 负责题目重复检查和文件保存 + */ +public class QuestionManager { + private Map> userQuestions; // 存储每个用户的历史题目 + + public QuestionManager() { + this.userQuestions = new HashMap<>(); + loadExistingQuestions(); + } + + /** + * 加载已存在的题目文件,用于重复检查 + */ + private void loadExistingQuestions() { + try { + // 为每个用户类型创建目录 + createDirectoryIfNotExists("小学"); + createDirectoryIfNotExists("初中"); + createDirectoryIfNotExists("高中"); + + // 扫描已存在的文件并加载题目 + scanExistingFiles("小学"); + scanExistingFiles("初中"); + scanExistingFiles("高中"); + } catch (Exception e) { + System.err.println("加载历史题目时出错: " + e.getMessage()); + } + } + + /** + * 创建目录 + */ + private void createDirectoryIfNotExists(String accountType) throws IOException { + Path path = Paths.get(accountType); + if (!Files.exists(path)) { + Files.createDirectories(path); + } + } + + /** + * 扫描已存在的文件 + */ + private void scanExistingFiles(String accountType) { + try { + Path accountDir = Paths.get(accountType); + if (Files.exists(accountDir)) { + Files.walk(accountDir) + .filter(Files::isRegularFile) + .filter(path -> path.toString().endsWith(".txt")) + .forEach(this::loadQuestionsFromFile); + } + } catch (IOException e) { + System.err.println("扫描文件时出错: " + e.getMessage()); + } + } + + /** + * 从文件加载题目 + */ + private void loadQuestionsFromFile(Path filePath) { + try { + String accountType = filePath.getParent().getFileName().toString(); + Set questions = userQuestions.computeIfAbsent(accountType, k -> new HashSet<>()); + + List lines = Files.readAllLines(filePath); + for (String line : lines) { + line = line.trim(); + if (line.matches("\\d+\\..*")) { // 题号格式:1. 题目内容 + String question = line.substring(line.indexOf('.') + 1).trim(); + questions.add(question); + } + } + } catch (IOException e) { + System.err.println("读取文件时出错: " + e.getMessage()); + } + } + + /** + * 检查题目是否重复 + * @param accountType 账户类型 + * @param newQuestions 新题目列表 + * @return 去重后的题目列表 + */ + public List checkAndRemoveDuplicates(String accountType, List newQuestions) { + Set existingQuestions = userQuestions.computeIfAbsent(accountType, k -> new HashSet<>()); + List uniqueQuestions = new ArrayList<>(); + + for (MathQuestion question : newQuestions) { + if (!existingQuestions.contains(question.getExpression())) { + uniqueQuestions.add(question); + existingQuestions.add(question.getExpression()); + } + } + + return uniqueQuestions; + } + + /** + * 保存题目到文件 + * @param accountType 账户类型 + * @param questions 题目列表 + * @return 保存的文件名 + */ + public String saveQuestionsToFile(String accountType, List questions) { + try { + // 生成文件名:年-月-日-时-分-秒.txt + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"); + String fileName = now.format(formatter) + ".txt"; + + // 创建文件路径 + Path accountDir = Paths.get(accountType); + Path filePath = accountDir.resolve(fileName); + + // 写入文件 + try (BufferedWriter writer = Files.newBufferedWriter(filePath)) { + for (int i = 0; i < questions.size(); i++) { + writer.write((i + 1) + ". " + questions.get(i).getExpression()); + writer.newLine(); + if (i < questions.size() - 1) { + writer.newLine(); // 题目之间空一行 + } + } + } + + return fileName; + } catch (IOException e) { + System.err.println("保存文件时出错: " + e.getMessage()); + return null; + } + } + + /** + * 生成指定数量的不重复题目 + * @param accountType 账户类型 + * @param requestedCount 请求的题目数量 + * @param generator 题目生成器 + * @return 实际生成的题目列表 + */ + public List generateUniqueQuestions(String accountType, int requestedCount, MathQuestionGenerator generator) { + List allQuestions = new ArrayList<>(); + int maxAttempts = requestedCount * 3; // 最多尝试3倍数量 + int attempts = 0; + + while (allQuestions.size() < requestedCount && attempts < maxAttempts) { + List newQuestions = generator.generateQuestions(accountType, requestedCount - allQuestions.size()); + List uniqueQuestions = checkAndRemoveDuplicates(accountType, newQuestions); + allQuestions.addAll(uniqueQuestions); + attempts++; + } + + return allQuestions; + } +} diff --git a/src/SimpleMathTestGenerator.java b/src/SimpleMathTestGenerator.java new file mode 100644 index 0000000..b4c612f --- /dev/null +++ b/src/SimpleMathTestGenerator.java @@ -0,0 +1,200 @@ +import java.util.*; +import java.io.*; + +/** + * 简化版中小学数学卷子自动生成程序 + * 更好的中文支持和用户交互 + */ +public class SimpleMathTestGenerator { + private UserManager userManager; + private MathQuestionGenerator questionGenerator; + private QuestionManager questionManager; + private BufferedReader reader; + private User currentUser; + private String currentAccountType; + + public SimpleMathTestGenerator() { + this.userManager = new UserManager(); + this.questionGenerator = new MathQuestionGenerator(); + this.questionManager = new QuestionManager(); + this.reader = new BufferedReader(new InputStreamReader(System.in)); + this.currentUser = null; + this.currentAccountType = null; + } + + /** + * 程序主入口 + */ + public void run() { + System.out.println("=== 中小学数学卷子自动生成程序 ==="); + System.out.println("预设账户:"); + System.out.println("小学:张三1/张三2/张三3,密码:123"); + System.out.println("初中:李四1/李四2/李四3,密码:123"); + System.out.println("高中:王五1/王五2/王五3,密码:123"); + System.out.println(); + + try { + while (true) { + if (currentUser == null) { + if (!login()) { + continue; + } + } else { + handleLoggedInUser(); + } + } + } catch (IOException e) { + System.out.println("程序输入输出错误:" + e.getMessage()); + } + } + + /** + * 处理用户登录 + */ + private boolean login() throws IOException { + System.out.print("请输入用户名和密码(用空格隔开):"); + String input = reader.readLine(); + + if (input == null || input.trim().isEmpty()) { + System.out.println("请输入正确的用户名、密码"); + return false; + } + + input = input.trim(); + String[] credentials = input.split("\\s+"); + if (credentials.length != 2) { + System.out.println("请输入正确的用户名、密码"); + return false; + } + + String username = credentials[0]; + String password = credentials[1]; + + User user = userManager.authenticate(username, password); + if (user != null) { + currentUser = user; + currentAccountType = user.getAccountType(); + System.out.println("当前选择为" + currentAccountType + "出题"); + return true; + } else { + System.out.println("请输入正确的用户名、密码"); + return false; + } + } + + /** + * 处理已登录用户的操作 + */ + private void handleLoggedInUser() throws IOException { + System.out.print("准备生成" + currentAccountType + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录):"); + String input = reader.readLine(); + + if (input == null) { + return; + } + + input = input.trim(); + + // 检查是否是切换类型命令 + if (input.startsWith("切换为")) { + handleAccountTypeSwitch(input); + return; + } + + try { + int count = Integer.parseInt(input); + + if (count == -1) { + currentUser = null; + currentAccountType = null; + System.out.println("已退出当前用户"); + return; + } + + if (count < 10 || count > 30) { + System.out.println("题目数量必须在10-30之间,请重新输入"); + return; + } + + generateAndSaveQuestions(count); + + } catch (NumberFormatException e) { + System.out.println("请输入有效的数字或切换命令"); + } + } + + /** + * 处理账户类型切换 + */ + private void handleAccountTypeSwitch(String input) throws IOException { + String newType = input.substring(3); + + if (!userManager.isValidAccountType(newType)) { + System.out.println("请输入小学、初中和高中三个选项中的一个"); + return; + } + + currentAccountType = newType; + System.out.print("准备生成" + currentAccountType + "数学题目,请输入生成题目数量:"); + String countInput = reader.readLine(); + + if (countInput == null) { + return; + } + + try { + int count = Integer.parseInt(countInput.trim()); + + if (count < 10 || count > 30) { + System.out.println("题目数量必须在10-30之间"); + return; + } + + generateAndSaveQuestions(count); + + } catch (NumberFormatException e) { + System.out.println("请输入有效的数字"); + } + } + + /** + * 生成并保存题目 + */ + private void generateAndSaveQuestions(int count) { + System.out.println("正在生成" + count + "道" + currentAccountType + "数学题目..."); + + List questions = questionManager.generateUniqueQuestions( + currentAccountType, count, questionGenerator); + + if (questions.size() < count) { + System.out.println("注意:由于去重要求,实际生成了" + questions.size() + "道题目"); + } + + if (questions.isEmpty()) { + System.out.println("无法生成新的题目,可能所有题目都已存在"); + return; + } + + String fileName = questionManager.saveQuestionsToFile(currentAccountType, questions); + if (fileName != null) { + System.out.println("题目已保存到文件:" + currentAccountType + "/" + fileName); + System.out.println("共生成" + questions.size() + "道题目"); + + System.out.println("\n题目预览:"); + for (int i = 0; i < Math.min(3, questions.size()); i++) { + System.out.println((i + 1) + ". " + questions.get(i).getExpression()); + } + if (questions.size() > 3) { + System.out.println("..."); + } + System.out.println(); + } else { + System.out.println("保存文件失败"); + } + } + + public static void main(String[] args) { + SimpleMathTestGenerator generator = new SimpleMathTestGenerator(); + generator.run(); + } +} diff --git a/src/User.java b/src/User.java new file mode 100644 index 0000000..82b8208 --- /dev/null +++ b/src/User.java @@ -0,0 +1,35 @@ +/** + * 用户账户类 + * 存储用户信息和账户类型 + */ +public class User { + private String username; + private String password; + private String accountType; // 小学、初中、高中 + + public User(String username, String password, String accountType) { + this.username = username; + this.password = password; + this.accountType = accountType; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getAccountType() { + return accountType; + } + + @Override + public String toString() { + return "User{" + + "username='" + username + '\'' + + ", accountType='" + accountType + '\'' + + '}'; + } +} diff --git a/src/UserManager.java b/src/UserManager.java new file mode 100644 index 0000000..9ed4031 --- /dev/null +++ b/src/UserManager.java @@ -0,0 +1,59 @@ +import java.util.HashMap; +import java.util.Map; + +/** + * 用户管理器 + * 负责用户认证和管理预设账户 + */ +public class UserManager { + private Map users; + + public UserManager() { + users = new HashMap<>(); + initializeUsers(); + } + + /** + * 初始化预设账户 + * 根据附表1:小学、初中、高中各3个账户 + */ + private void initializeUsers() { + // 小学账户 + users.put("张三1", new User("张三1", "123", "小学")); + users.put("张三2", new User("张三2", "123", "小学")); + users.put("张三3", new User("张三3", "123", "小学")); + + // 初中账户 + users.put("李四1", new User("李四1", "123", "初中")); + users.put("李四2", new User("李四2", "123", "初中")); + users.put("李四3", new User("李四3", "123", "初中")); + + // 高中账户 + users.put("王五1", new User("王五1", "123", "高中")); + users.put("王五2", new User("王五2", "123", "高中")); + users.put("王五3", new User("王五3", "123", "高中")); + } + + /** + * 验证用户登录 + * @param username 用户名 + * @param password 密码 + * @return 验证成功返回User对象,失败返回null + */ + public User authenticate(String username, String password) { + User user = users.get(username); + if (user != null && user.getPassword().equals(password)) { + return user; + } + return null; + } + + /** + * 检查账户类型是否有效 + * @param accountType 账户类型 + * @return 是否有效 + */ + public boolean isValidAccountType(String accountType) { + return "小学".equals(accountType) || "初中".equals(accountType) || "高中".equals(accountType); + } +}