diff --git a/src/AccountManager.class b/src/AccountManager.class new file mode 100644 index 0000000..e2ad10f Binary files /dev/null and b/src/AccountManager.class differ diff --git a/src/AccountManager.java b/src/AccountManager.java new file mode 100644 index 0000000..cb26a91 --- /dev/null +++ b/src/AccountManager.java @@ -0,0 +1,40 @@ +import java.util.HashMap; +import java.util.Map; + + +public class AccountManager { + private Map users; + + public AccountManager() { + initializeUsers(); + } + + private void initializeUsers() { + users = new HashMap<>(); + + addUser("张三1", "123", UserType.PRIMARY); + addUser("张三2", "123", UserType.PRIMARY); + addUser("张三3", "123", UserType.PRIMARY); + + addUser("李四1", "123", UserType.JUNIOR); + addUser("李四2", "123", UserType.JUNIOR); + addUser("李四3", "123", UserType.JUNIOR); + + addUser("王五1", "123", UserType.SENIOR); + addUser("王五2", "123", UserType.SENIOR); + addUser("王五3", "123", UserType.SENIOR); + } + + private void addUser(String username, String password, UserType type) { + users.put(username + ":" + password, new User(username, password, type)); + } + + public User authenticate(String username, String password) { + String key = username + ":" + password; + return users.get(key); + } + + public boolean isValidUserType(String typeName) { + return UserType.fromChineseName(typeName) != null; + } +} \ No newline at end of file diff --git a/src/Filemanager.class b/src/Filemanager.class new file mode 100644 index 0000000..b6f639b Binary files /dev/null and b/src/Filemanager.class differ diff --git a/src/Filemanager.java b/src/Filemanager.java new file mode 100644 index 0000000..c1e0461 --- /dev/null +++ b/src/Filemanager.java @@ -0,0 +1,91 @@ +import java.io.*; +import java.nio.file.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + + +public class Filemanager { + private static final String BASE_DIR = "数学试卷"; + + public Filemanager() { + createBaseDirectory(); + } + + private void createBaseDirectory() { + File baseDir = new File(BASE_DIR); + if (!baseDir.exists()) { + baseDir.mkdir(); + } + } + + public void savePaper(String username, String[] questions) throws IOException { + String userDirPath = BASE_DIR + File.separator + username; + File userDir = new File(userDirPath); + if (!userDir.exists()) { + userDir.mkdir(); + } + + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String fileName = timestamp + ".txt"; + String filePath = userDirPath + File.separator + fileName; + + try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) { + for (int i = 0; i < questions.length; i++) { + writer.println(questions[i]); + if (i < questions.length - 1) { + writer.println(); + } + } + } + + System.out.println("试卷已保存到: " + new File(filePath).getAbsolutePath()); + } + + public Set loadAllQuestions(String username) { + Set allQuestions = new HashSet<>(); + String userDirPath = BASE_DIR + File.separator + username; + File userDir = new File(userDirPath); + + if (!userDir.exists() || !userDir.isDirectory()) { + return allQuestions; + } + + File[] files = userDir.listFiles((dir, name) -> name.endsWith(".txt")); + if (files == null) { + return allQuestions; + } + + for (File file : files) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + String line; + StringBuilder question = new StringBuilder(); + boolean inQuestion = false; + + while ((line = reader.readLine()) != null) { + if (line.matches("^\\d+\\.\\s.*")) { + if (inQuestion) { + allQuestions.add(question.toString().trim()); + question.setLength(0); + } + String questionContent = line.substring(line.indexOf(". ") + 2); + question.append(questionContent); + inQuestion = true; + } else if (inQuestion && !line.trim().isEmpty()) { + question.append(" ").append(line.trim()); + } + } + + if (inQuestion && question.length() > 0) { + allQuestions.add(question.toString().trim()); + } + + } catch (IOException e) { + System.err.println("读取文件失败: " + file.getName()); + } + } + + return allQuestions; + } +} \ No newline at end of file diff --git a/src/IQuestionGenerator.class b/src/IQuestionGenerator.class new file mode 100644 index 0000000..84dabe7 Binary files /dev/null and b/src/IQuestionGenerator.class differ diff --git a/src/JuniorQuestionGenerator.class b/src/JuniorQuestionGenerator.class new file mode 100644 index 0000000..4a8443e Binary files /dev/null and b/src/JuniorQuestionGenerator.class differ diff --git a/src/Main.class b/src/Main.class new file mode 100644 index 0000000..d9c434d Binary files /dev/null and b/src/Main.class differ diff --git a/src/Main.java b/src/Main.java new file mode 100644 index 0000000..bad3bb0 --- /dev/null +++ b/src/Main.java @@ -0,0 +1,124 @@ +import java.util.Scanner; + + +public class Main { + private AccountManager accountManager; + private PaperGenerator paperGenerator; + private Filemanager fileManager; + private User currentUser; + private Scanner scanner; + + public Main() { + this.accountManager = new AccountManager(); + this.fileManager = new Filemanager(); + this.scanner = new Scanner(System.in); + } + + public void run() { + System.out.println("=== 中小学数学卷子自动生成程序 ==="); + + while (true) { + if (currentUser == null) { + login(); + } else { + generatePaperProcess(); + } + } + } + + private void login() { + while (true) { + System.out.print("请输入用户名和密码(用空格隔开): "); + String input = scanner.nextLine().trim(); + + if (input.equalsIgnoreCase("exit")) { + System.exit(0); + } + + String[] parts = input.split("\\s+"); + if (parts.length != 2) { + System.out.println("请输入正确的用户名、密码格式(用户名 密码)"); + continue; + } + + String username = parts[0]; + String password = parts[1]; + + currentUser = accountManager.authenticate(username, password); + if (currentUser != null) { + paperGenerator = new PaperGenerator(currentUser); + System.out.println("当前选择为 " + currentUser.getUserType().getChineseName() + " 出题"); + break; + } else { + System.out.println("请输入正确的用户名、密码"); + } + } + } + + private void generatePaperProcess() { + UserType currentType = currentUser.getUserType(); + + while (true) { + System.out.print("准备生成 " + currentType.getChineseName() + + " 数学题目,请输入生成题目数量(10-30,输入-1将退出当前用户,重新登录): "); + String input = scanner.nextLine().trim(); + + if (input.equals("-1")) { + currentUser = null; + paperGenerator = null; + System.out.println("已退出当前用户,请重新登录。"); + return; + } + + if (input.startsWith("切换为")) { + handleTypeSwitch(input); + currentType = currentUser.getUserType(); + continue; + } + + try { + int questionCount = Integer.parseInt(input); + + if (questionCount < 10 || questionCount > 30) { + System.out.println("题目数量必须在10-30之间"); + continue; + } + + String[] questions = paperGenerator.generatePaper(questionCount, fileManager); + fileManager.savePaper(currentUser.getUsername(), questions); + + } catch (NumberFormatException e) { + System.out.println("请输入有效的数字(10-30或-1)"); + } catch (Exception e) { + System.out.println("生成试卷时出错: " + e.getMessage()); + } + } + } + + private void handleTypeSwitch(String input) { + String typeName = input.substring(3).trim(); + + if (!accountManager.isValidUserType(typeName)) { + System.out.println("请输入小学、初中和高中三个选项中的一个"); + return; + } + + UserType newType = UserType.fromChineseName(typeName); + paperGenerator.setUserType(newType); + + User tempUser = new User(currentUser.getUsername(), currentUser.getPassword(), newType); + currentUser = tempUser; + + System.out.println("已切换为 " + typeName + " 出题"); + } + + public static void main(String[] args) { + try { + Main app = new Main(); + app.run(); + } catch (Exception e) { + System.err.println("程序出现异常: " + e.getMessage()); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/PaperGenerator.class b/src/PaperGenerator.class new file mode 100644 index 0000000..d4e43a7 Binary files /dev/null and b/src/PaperGenerator.class differ diff --git a/src/PaperGenerator.java b/src/PaperGenerator.java new file mode 100644 index 0000000..604c6da --- /dev/null +++ b/src/PaperGenerator.java @@ -0,0 +1,48 @@ +import java.util.HashSet; +import java.util.Set; + + +public class PaperGenerator { + private IQuestionGenerator questionGenerator; + private Set generatedQuestions; + private User currentUser; + + public PaperGenerator(User user) { + this.currentUser = user; + this.questionGenerator = QuestionGeneratorFactory.createGenerator(user.getUserType()); + this.generatedQuestions = new HashSet<>(); + } + + public void setUserType(UserType userType) { + this.questionGenerator = QuestionGeneratorFactory.createGenerator(userType); + } + + public String[] generatePaper(int questionCount, Filemanager fileManager) { + if (questionCount < 10 || questionCount > 30) { + throw new IllegalArgumentException("题目数量必须在10-30之间"); + } + + String[] questions = new String[questionCount]; + Set allHistoryQuestions = fileManager.loadAllQuestions(currentUser.getUsername()); + generatedQuestions.addAll(allHistoryQuestions); + + for (int i = 0; i < questionCount; i++) { + String question; + int attempt = 0; + int maxAttempts = 100; + + do { + question = questionGenerator.generateQuestion(); + attempt++; + if (attempt >= maxAttempts) { + throw new RuntimeException("无法生成不重复的题目,请尝试清理历史文件"); + } + } while (generatedQuestions.contains(question) || !questionGenerator.isValidQuestion(question)); + + generatedQuestions.add(question); + questions[i] = (i + 1) + ". " + question; + } + + return questions; + } +} \ No newline at end of file diff --git a/src/PrimaryQuestionGenerator.class b/src/PrimaryQuestionGenerator.class new file mode 100644 index 0000000..764a687 Binary files /dev/null and b/src/PrimaryQuestionGenerator.class differ diff --git a/src/QuestionGenerator.java b/src/QuestionGenerator.java new file mode 100644 index 0000000..b24762d --- /dev/null +++ b/src/QuestionGenerator.java @@ -0,0 +1,185 @@ +import java.util.Random; + + +interface IQuestionGenerator { + String generateQuestion(); + boolean isValidQuestion(String question); +} + + +class PrimaryQuestionGenerator implements IQuestionGenerator { + private Random random = new Random(); + private String[] operators = {"+", "-", "*", "/"}; + + @Override + public String generateQuestion() { + int operandCount = random.nextInt(3) + 2; + StringBuilder question = new StringBuilder(); + + question.append(random.nextInt(100) + 1); + + for (int i = 1; i < operandCount; i++) { + String operator = operators[random.nextInt(operators.length)]; + int operand = random.nextInt(100) + 1; + + if (random.nextBoolean() && i < operandCount - 1) { + question.append(" ").append(operator).append(" (").append(operand); + if (random.nextBoolean()) { + question.append(" ").append(operators[random.nextInt(operators.length)]) + .append(" ").append(random.nextInt(100) + 1).append(")"); + i++; + } + } else { + question.append(" ").append(operator).append(" ").append(operand); + } + } + + String result = question.toString(); + int openCount = countChar(result, '('); + int closeCount = countChar(result, ')'); + while (openCount > closeCount) { + result += ")"; + closeCount++; + } + + return result + " = "; + } + + @Override + public boolean isValidQuestion(String question) { + return question.matches("^[0-9+\\-*/().\\s]+=$") && + !question.contains("²") && !question.contains("√") && + !question.contains("sin") && !question.contains("cos") && !question.contains("tan"); + } + + private int countChar(String str, char ch) { + int count = 0; + for (char c : str.toCharArray()) { + if (c == ch) count++; + } + return count; + } +} + + +class JuniorQuestionGenerator implements IQuestionGenerator { + private Random random = new Random(); + private String[] operators = {"+", "-", "*", "/"}; + + @Override + public String generateQuestion() { + StringBuilder question = new StringBuilder(); + int operandCount = random.nextInt(3) + 2; + boolean hasSpecialOperator = false; + + question.append(random.nextInt(100) + 1); + + for (int i = 1; i < operandCount; i++) { + String operator; + if (!hasSpecialOperator && random.nextDouble() < 0.4) { + if (random.nextBoolean()) { + operator = "²"; + hasSpecialOperator = true; + } else { + operator = "√"; + hasSpecialOperator = true; + } + } else { + operator = operators[random.nextInt(operators.length)]; + } + + int operand = random.nextInt(100) + 1; + + if (operator.equals("²")) { + question.append("²"); + } else if (operator.equals("√")) { + question.append(" ").append(operator).append(operand); + } else { + question.append(" ").append(operator).append(" ").append(operand); + } + } + + if (!hasSpecialOperator) { + if (random.nextBoolean()) { + question.append("²"); + } else { + question.append(" √").append(random.nextInt(100) + 1); + } + } + + return question.toString() + " = "; + } + + @Override + public boolean isValidQuestion(String question) { + return (question.contains("²") || question.contains("√")) && + !question.contains("sin") && !question.contains("cos") && !question.contains("tan"); + } +} + + +class SeniorQuestionGenerator implements IQuestionGenerator { + private Random random = new Random(); + private String[] operators = {"+", "-", "*", "/"}; + private String[] trigFunctions = {"sin", "cos", "tan"}; + + @Override + public String generateQuestion() { + StringBuilder question = new StringBuilder(); + int operandCount = random.nextInt(3) + 2; + boolean hasTrigFunction = false; + + if (random.nextDouble() < 0.6) { + String trigFunc = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = random.nextInt(360) + 1; + question.append(trigFunc).append("(").append(angle).append("°)"); + hasTrigFunction = true; + } else { + question.append(random.nextInt(100) + 1); + } + + for (int i = 1; i < operandCount; i++) { + String operator = operators[random.nextInt(operators.length)]; + + if (!hasTrigFunction && random.nextDouble() < 0.5) { + String trigFunc = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = random.nextInt(360) + 1; + question.append(" ").append(operator).append(" ").append(trigFunc).append("(").append(angle).append("°)"); + hasTrigFunction = true; + } else { + int operand = random.nextInt(100) + 1; + question.append(" ").append(operator).append(" ").append(operand); + } + } + + if (!hasTrigFunction) { + String trigFunc = trigFunctions[random.nextInt(trigFunctions.length)]; + int angle = random.nextInt(360) + 1; + question.append(" ").append(operators[random.nextInt(operators.length)]) + .append(" ").append(trigFunc).append("(").append(angle).append("°)"); + } + + return question.toString() + " = "; + } + + @Override + public boolean isValidQuestion(String question) { + return question.contains("sin") || question.contains("cos") || question.contains("tan"); + } +} + + +class QuestionGeneratorFactory { + public static IQuestionGenerator createGenerator(UserType userType) { + switch (userType) { + case PRIMARY: + return new PrimaryQuestionGenerator(); + case JUNIOR: + return new JuniorQuestionGenerator(); + case SENIOR: + return new SeniorQuestionGenerator(); + default: + throw new IllegalArgumentException("不支持的题目类型"); + } + } +} \ No newline at end of file diff --git a/src/QuestionGeneratorFactory$1.class b/src/QuestionGeneratorFactory$1.class new file mode 100644 index 0000000..d199ebe Binary files /dev/null and b/src/QuestionGeneratorFactory$1.class differ diff --git a/src/QuestionGeneratorFactory.class b/src/QuestionGeneratorFactory.class new file mode 100644 index 0000000..14e3b32 Binary files /dev/null and b/src/QuestionGeneratorFactory.class differ diff --git a/src/SeniorQuestionGenerator.class b/src/SeniorQuestionGenerator.class new file mode 100644 index 0000000..c66ecd0 Binary files /dev/null and b/src/SeniorQuestionGenerator.class differ diff --git a/src/User.class b/src/User.class new file mode 100644 index 0000000..aa0783d Binary files /dev/null and b/src/User.class differ diff --git a/src/User.java b/src/User.java new file mode 100644 index 0000000..a4df58d --- /dev/null +++ b/src/User.java @@ -0,0 +1,55 @@ + +public class User { + private String username; + private String password; + private UserType userType; + + public User(String username, String password, UserType userType) { + this.username = username; + this.password = password; + this.userType = userType; + } + + public String getUsername() { return username; } + public String getPassword() { return password; } + public UserType getUserType() { return userType; } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + User user = (User) obj; + return username.equals(user.username) && password.equals(user.password); + } + + @Override + public int hashCode() { + return username.hashCode() + password.hashCode(); + } +} + + +enum UserType { + PRIMARY("小学"), + JUNIOR("初中"), + SENIOR("高中"); + + private final String chineseName; + + UserType(String chineseName) { + this.chineseName = chineseName; + } + + public String getChineseName() { + return chineseName; + } + + public static UserType fromChineseName(String name) { + for (UserType type : values()) { + if (type.chineseName.equals(name)) { + return type; + } + } + return null; + } +} \ No newline at end of file diff --git a/src/UserType.class b/src/UserType.class new file mode 100644 index 0000000..0c9eae2 Binary files /dev/null and b/src/UserType.class differ