重构项目结构:符合接口优先设计原则

- 新增interfaces包,定义QuestionInterface、LoginSystemInterface、FileManagerInterface
- 新增services包,实现具体业务逻辑类
- 新增models包,存放数据模型
- 新增factories包,实现服务工厂
- 修改Main.java使用接口编程
- 完善.gitignore文件
- 符合'先定义接口类'的评分标准
develop
imok 4 days ago
parent df33ab2555
commit 6cc655468a

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -0,0 +1,29 @@
1. 58 =
2. 19 / 81 =
3. 77 - 20 =
4. (66 + 65 + 35 / 57) =
5. 29 / 37 =
6. (64 / 31) - 27 * 64 - 69 =
7. ((97) * 83 * 39 + 23) =
8. 72 - 85 =
9. 30 - 79 + 63 + 82 =
10. 95 - 26 =
11. 13 - 98 =
12. 36 - 55 =
13. (((94 + 72) * 1) * 13) / 90 =
14. 36 * 69 =
15. (68 + 60) * 65 / 33 =

@ -0,0 +1,31 @@
1. 69 =
2. (4 + 49 - 36 + 79) =
3. 17 =
4. ((83 + 61 - 26) + 24 * 93) =
5. 65 =
6. 16 / 66 =
7. 5 / 93 =
8. 33 / 11 =
9. 91 =
10. (22 - 13) + 70 + 40 / 59 =
11. 88 =
12. ((87) + 89) - 55 * 76 =
13. 63 + 18 + 6 - 25 =
14. 44 / 37 - 45 - 87 =
15. ((74) + 53) / 31 / 54 =
16. 91 / 9 + 55 * 38 =

@ -1,31 +1,45 @@
import interfaces.LoginSystemInterface;
import interfaces.FileManagerInterface;
import models.User;
import models.DifficultyLevel;
import factories.ServiceFactory;
import services.QuestionGenerator;
import java.util.Scanner; import java.util.Scanner;
public class Main { public class Main {
public static void main(String[] args) { public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); Scanner scanner = new Scanner(System.in);
LoginSystem loginSystem = new LoginSystem();
LoginSystemInterface loginSystem = ServiceFactory.createLoginSystem();
QuestionGenerator generator = new QuestionGenerator(); QuestionGenerator generator = new QuestionGenerator();
FileManager fileManager = new FileManager(); FileManagerInterface fileManager = ServiceFactory.createFileManager();
while (true) { while (true) {
// 登录阶段 System.out.print("请输入用户名和密码(用空格隔开):");
User currentUser = loginSystem.login(scanner); String input = scanner.nextLine().trim();
String[] parts = input.split("\\s+");
if (parts.length != 2) {
System.out.println("请输入正确的用户名、密码");
continue;
}
User currentUser = loginSystem.login(parts[0], parts[1]);
if (currentUser == null) { if (currentUser == null) {
System.out.println("请输入正确的用户名、密码");
continue; continue;
} }
System.out.println("当前选择为" + currentUser.getLevel().getDisplayName() + "出题"); System.out.println("当前选择为" + currentUser.getLevel().getDisplayName() + "出题");
// 主循环
while (true) { while (true) {
System.out.println("准备生成" + currentUser.getLevel().getDisplayName() + System.out.println("准备生成" + currentUser.getLevel().getDisplayName() +
"数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录"); "数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
String input = scanner.nextLine().trim(); String command = scanner.nextLine().trim();
// 检查切换命令 if (command.startsWith("切换为")) {
if (input.startsWith("切换为")) { String levelName = command.substring(3).trim();
String levelName = input.substring(3).trim();
DifficultyLevel newLevel = loginSystem.switchLevel(levelName); DifficultyLevel newLevel = loginSystem.switchLevel(levelName);
if (newLevel != null) { if (newLevel != null) {
currentUser.setLevel(newLevel); currentUser.setLevel(newLevel);
@ -35,21 +49,18 @@ public class Main {
} }
} }
// 检查退出命令 if (command.equals("-1")) {
if (input.equals("-1")) {
System.out.println("退出当前用户,重新登录..."); System.out.println("退出当前用户,重新登录...");
break; break;
} }
// 生成题目
try { try {
int count = Integer.parseInt(input); int count = Integer.parseInt(command);
if (count < 10 || count > 30) { if (count < 10 || count > 30) {
System.out.println("题目数量应在10-30之间"); System.out.println("题目数量应在10-30之间");
continue; continue;
} }
// 生成题目并检查重复
String[] questions = generator.generateQuestions(currentUser.getLevel(), count, String[] questions = generator.generateQuestions(currentUser.getLevel(), count,
currentUser.getUsername()); currentUser.getUsername());
if (questions == null) { if (questions == null) {
@ -57,7 +68,6 @@ public class Main {
continue; continue;
} }
// 保存文件
boolean success = fileManager.saveQuestions(currentUser, questions); boolean success = fileManager.saveQuestions(currentUser, questions);
if (success) { if (success) {
System.out.println("题目生成成功!"); System.out.println("题目生成成功!");

@ -1,4 +0,0 @@
public interface Question {
String generateQuestion();
boolean isValid();
}

@ -0,0 +1,16 @@
package factories;
import interfaces.LoginSystemInterface;
import interfaces.FileManagerInterface;
import services.LoginSystem;
import services.FileManager;
public class ServiceFactory {
public static LoginSystemInterface createLoginSystem() {
return new LoginSystem();
}
public static FileManagerInterface createFileManager() {
return new FileManager();
}
}

@ -0,0 +1,9 @@
package interfaces;
import models.User;
import java.util.Set;
public interface FileManagerInterface {
boolean saveQuestions(User user, String[] questions);
Set<String> loadExistingQuestions(String username);
}

@ -0,0 +1,9 @@
package interfaces;
import models.User;
import models.DifficultyLevel;
public interface LoginSystemInterface {
User login(String username, String password);
DifficultyLevel switchLevel(String levelName);
}

@ -0,0 +1,10 @@
package interfaces;
import models.DifficultyLevel;
public interface QuestionInterface {
String generateQuestion();
boolean isValid();
String getQuestionText();
DifficultyLevel getDifficulty();
}

@ -1,24 +1,26 @@
public enum DifficultyLevel { package models;
PRIMARY("小学"),
JUNIOR("初中"), public enum DifficultyLevel {
SENIOR("高中"); PRIMARY("小学"),
JUNIOR("初中"),
private final String displayName; SENIOR("高中");
DifficultyLevel(String displayName) { private final String displayName;
this.displayName = displayName;
} DifficultyLevel(String displayName) {
this.displayName = displayName;
public String getDisplayName() { }
return displayName;
} public String getDisplayName() {
return displayName;
public static DifficultyLevel fromString(String text) { }
for (DifficultyLevel level : DifficultyLevel.values()) {
if (level.displayName.equals(text)) { public static DifficultyLevel fromString(String text) {
return level; for (DifficultyLevel level : DifficultyLevel.values()) {
} if (level.displayName.equals(text)) {
} return level;
return null; }
} }
return null;
}
} }

@ -1,17 +1,18 @@
public class User { package models;
private String username;
private String password; public class User {
private DifficultyLevel level; private String username;
private String password;
public User(String username, String password, DifficultyLevel level) { private DifficultyLevel level;
this.username = username;
this.password = password; public User(String username, String password, DifficultyLevel level) {
this.level = level; this.username = username;
} this.password = password;
this.level = level;
// Getter 和 Setter 方法 }
public String getUsername() { return username; }
public String getPassword() { return password; } public String getUsername() { return username; }
public DifficultyLevel getLevel() { return level; } public String getPassword() { return password; }
public void setLevel(DifficultyLevel level) { this.level = level; } public DifficultyLevel getLevel() { return level; }
public void setLevel(DifficultyLevel level) { this.level = level; }
} }

@ -1,66 +1,68 @@
import java.io.*; package services;
import java.nio.file.*;
import java.text.SimpleDateFormat; import interfaces.FileManagerInterface;
import java.util.Date; import models.User;
import java.util.HashSet; import java.io.*;
import java.util.Set; import java.nio.file.*;
import java.text.SimpleDateFormat;
public class FileManager { import java.util.Date;
private static final String BASE_DIR = "exams"; import java.util.HashSet;
import java.util.Set;
public boolean saveQuestions(User user, String[] questions) {
try { public class FileManager implements FileManagerInterface {
// 创建用户目录 private static final String BASE_DIR = "exams";
Path userDir = Paths.get(BASE_DIR, user.getUsername());
Files.createDirectories(userDir); @Override
public boolean saveQuestions(User user, String[] questions) {
// 生成文件名 try {
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); Path userDir = Paths.get(BASE_DIR, user.getUsername());
Path filePath = userDir.resolve(timestamp + ".txt"); Files.createDirectories(userDir);
// 写入文件 String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(filePath))) { Path filePath = userDir.resolve(timestamp + ".txt");
for (int i = 0; i < questions.length; i++) {
writer.println(questions[i]); try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(filePath))) {
if (i < questions.length - 1) { for (int i = 0; i < questions.length; i++) {
writer.println(); // 题目之间空一行 writer.println(questions[i]);
} if (i < questions.length - 1) {
} writer.println();
} }
}
return true; }
} catch (IOException e) {
e.printStackTrace(); return true;
return false; } catch (IOException e) {
} e.printStackTrace();
} return false;
}
public Set<String> loadExistingQuestions(String username) { }
Set<String> questions = new HashSet<>();
Path userDir = Paths.get(BASE_DIR, username); @Override
public Set<String> loadExistingQuestions(String username) {
if (!Files.exists(userDir)) { Set<String> questions = new HashSet<>();
return questions; Path userDir = Paths.get(BASE_DIR, username);
}
if (!Files.exists(userDir)) {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(userDir, "*.txt")) { return questions;
for (Path filePath : stream) { }
try (BufferedReader reader = Files.newBufferedReader(filePath)) {
String line; try (DirectoryStream<Path> stream = Files.newDirectoryStream(userDir, "*.txt")) {
while ((line = reader.readLine()) != null) { for (Path filePath : stream) {
if (line.trim().isEmpty() || !line.contains(".")) { try (BufferedReader reader = Files.newBufferedReader(filePath)) {
continue; String line;
} while ((line = reader.readLine()) != null) {
// 提取题目内容(去掉题号) if (line.trim().isEmpty() || !line.contains(".")) {
String question = line.substring(line.indexOf(".") + 1).trim(); continue;
questions.add(question); }
} String question = line.substring(line.indexOf(".") + 1).trim();
} questions.add(question);
} }
} catch (IOException e) { }
e.printStackTrace(); }
} } catch (IOException e) {
e.printStackTrace();
return questions; }
}
return questions;
}
} }

@ -1,62 +1,48 @@
import java.util.HashMap; package services;
import java.util.Map;
import java.util.Scanner; import interfaces.LoginSystemInterface;
import models.User;
public class LoginSystem { import models.DifficultyLevel;
private Map<String, User> users; import java.util.HashMap;
import java.util.Map;
public LoginSystem() {
initializeUsers(); public class LoginSystem implements LoginSystemInterface {
} private Map<String, User> users;
private void initializeUsers() { public LoginSystem() {
users = new HashMap<>(); initializeUsers();
}
// 小学账户
users.put("张三1", new User("张三1", "123", DifficultyLevel.PRIMARY)); private void initializeUsers() {
users.put("张三2", new User("张三2", "123", DifficultyLevel.PRIMARY)); users = new HashMap<>();
users.put("张三3", new User("张三3", "123", DifficultyLevel.PRIMARY));
users.put("张三1", new User("张三1", "123", DifficultyLevel.PRIMARY));
// 初中账户 users.put("张三2", new User("张三2", "123", DifficultyLevel.PRIMARY));
users.put("李四1", new User("李四1", "123", DifficultyLevel.JUNIOR)); users.put("张三3", new User("张三3", "123", DifficultyLevel.PRIMARY));
users.put("李四2", new User("李四2", "123", DifficultyLevel.JUNIOR)); users.put("李四1", new User("李四1", "123", DifficultyLevel.JUNIOR));
users.put("李四3", new User("李四3", "123", DifficultyLevel.JUNIOR)); users.put("李四2", new User("李四2", "123", DifficultyLevel.JUNIOR));
users.put("李四3", new User("李四3", "123", DifficultyLevel.JUNIOR));
// 高中账户 users.put("王五1", new User("王五1", "123", DifficultyLevel.SENIOR));
users.put("王五1", new User("王五1", "123", DifficultyLevel.SENIOR)); users.put("王五2", new User("王五2", "123", DifficultyLevel.SENIOR));
users.put("王五2", new User("王五2", "123", DifficultyLevel.SENIOR)); users.put("王五3", new User("王五3", "123", DifficultyLevel.SENIOR));
users.put("王五3", new User("王五3", "123", DifficultyLevel.SENIOR)); }
}
@Override
public User login(Scanner scanner) { public User login(String username, String password) {
while (true) { User user = users.get(username);
System.out.print("请输入用户名和密码(用空格隔开):"); if (user != null && user.getPassword().equals(password)) {
String input = scanner.nextLine().trim(); return user;
String[] parts = input.split("\\s+"); }
return null;
if (parts.length != 2) { }
System.out.println("请输入正确的用户名、密码");
continue; @Override
} public DifficultyLevel switchLevel(String levelName) {
DifficultyLevel newLevel = DifficultyLevel.fromString(levelName);
String username = parts[0]; if (newLevel == null) {
String password = parts[1]; System.out.println("请输入小学、初中和高中三个选项中的一个");
return null;
User user = users.get(username); }
if (user != null && user.getPassword().equals(password)) { return newLevel;
return user; }
} else {
System.out.println("请输入正确的用户名、密码");
}
}
}
public DifficultyLevel switchLevel(String levelName) {
DifficultyLevel newLevel = DifficultyLevel.fromString(levelName);
if (newLevel == null) {
System.out.println("请输入小学、初中和高中三个选项中的一个");
return null;
}
return newLevel;
}
} }

@ -1,96 +1,86 @@
import java.util.HashSet; package services;
import java.util.Random;
import java.util.Set; import interfaces.QuestionInterface;
import models.DifficultyLevel;
public class QuestionGenerator { import java.util.Random;
private Random random;
private FileManager fileManager; public class MathQuestion implements QuestionInterface {
private String questionText;
public QuestionGenerator() { private DifficultyLevel difficulty;
random = new Random(); private Random random;
fileManager = new FileManager();
} public MathQuestion(DifficultyLevel difficulty) {
this.difficulty = difficulty;
public String[] generateQuestions(DifficultyLevel level, int count, String username) { this.random = new Random();
Set<String> existingQuestions = fileManager.loadExistingQuestions(username); this.questionText = generateQuestion();
Set<String> newQuestions = new HashSet<>(); }
String[] questions = new String[count];
@Override
for (int i = 0; i < count; i++) { public String generateQuestion() {
String question; int operandCount = random.nextInt(5) + 1;
int attempts = 0; StringBuilder question = new StringBuilder();
do { switch (difficulty) {
question = generateSingleQuestion(level, i + 1); case PRIMARY:
attempts++; question.append(generatePrimaryQuestion(operandCount));
if (attempts > 100) { break;
return null; // 避免无限循环 case JUNIOR:
} question.append(generateJuniorQuestion(operandCount));
} while (existingQuestions.contains(question) || newQuestions.contains(question)); break;
case SENIOR:
newQuestions.add(question); question.append(generateSeniorQuestion(operandCount));
questions[i] = question; break;
} }
return questions; question.append(" = ");
} return question.toString();
}
private String generateSingleQuestion(DifficultyLevel level, int questionNumber) {
int operandCount = random.nextInt(5) + 1; // 1-5个操作数 @Override
StringBuilder question = new StringBuilder(questionNumber + ". "); public boolean isValid() {
return questionText != null && !questionText.trim().isEmpty();
switch (level) { }
case PRIMARY:
question.append(generatePrimaryQuestion(operandCount)); @Override
break; public String getQuestionText() {
case JUNIOR: return questionText;
question.append(generateJuniorQuestion(operandCount)); }
break;
case SENIOR: @Override
question.append(generateSeniorQuestion(operandCount)); public DifficultyLevel getDifficulty() {
break; return difficulty;
} }
question.append(" = "); private String generatePrimaryQuestion(int operandCount) {
return question.toString(); String[] operators = {"+", "-", "*", "/"};
} StringBuilder question = new StringBuilder();
private String generatePrimaryQuestion(int operandCount) { for (int i = 0; i < operandCount; i++) {
String[] operators = {"+", "-", "*", "/"}; if (i > 0) {
StringBuilder question = new StringBuilder(); question.append(" ").append(operators[random.nextInt(operators.length)]).append(" ");
}
for (int i = 0; i < operandCount; i++) { question.append(random.nextInt(100) + 1);
if (i > 0) {
question.append(" ").append(operators[random.nextInt(operators.length)]).append(" "); if (operandCount > 2 && random.nextDouble() < 0.3) {
} question.insert(0, "(").append(")");
question.append(random.nextInt(100) + 1); }
}
// 随机添加括号(小学难度) return question.toString();
if (operandCount > 2 && random.nextDouble() < 0.3) { }
question.insert(0, "(").append(")");
} private String generateJuniorQuestion(int operandCount) {
} String question = generatePrimaryQuestion(operandCount);
if (random.nextBoolean()) {
return question.toString(); return "√" + (random.nextInt(100) + 1) + " + " + question;
} } else {
return "(" + (random.nextInt(10) + 1) + ")² + " + question;
private String generateJuniorQuestion(int operandCount) { }
String question = generatePrimaryQuestion(operandCount); }
// 确保至少有一个平方或开根号 private String generateSeniorQuestion(int operandCount) {
if (random.nextBoolean()) { String question = generatePrimaryQuestion(operandCount);
return "√" + (random.nextInt(100) + 1) + " + " + question; String[] trigFunctions = {"sin", "cos", "tan"};
} else { return trigFunctions[random.nextInt(trigFunctions.length)] +
return "(" + (random.nextInt(10) + 1) + ")² + " + question; "(" + (random.nextInt(90) + 1) + "°) + " + question;
} }
}
private String generateSeniorQuestion(int operandCount) {
String question = generatePrimaryQuestion(operandCount);
String[] trigFunctions = {"sin", "cos", "tan"};
// 确保至少有一个三角函数
return trigFunctions[random.nextInt(trigFunctions.length)] +
"(" + (random.nextInt(90) + 1) + "°) + " + question;
}
} }

@ -0,0 +1,42 @@
package services;
import interfaces.QuestionInterface;
import models.DifficultyLevel;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class QuestionGenerator {
private Random random;
private FileManager fileManager;
public QuestionGenerator() {
random = new Random();
fileManager = new FileManager();
}
public String[] generateQuestions(DifficultyLevel level, int count, String username) {
Set<String> existingQuestions = fileManager.loadExistingQuestions(username);
Set<String> newQuestions = new HashSet<>();
String[] questions = new String[count];
for (int i = 0; i < count; i++) {
QuestionInterface question;
int attempts = 0;
do {
question = new MathQuestion(level);
attempts++;
if (attempts > 100) {
return null;
}
} while (existingQuestions.contains(question.getQuestionText()) ||
newQuestions.contains(question.getQuestionText()));
newQuestions.add(question.getQuestionText());
questions[i] = (i + 1) + ". " + question.getQuestionText();
}
return questions;
}
}
Loading…
Cancel
Save