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

- 新增interfaces包,定义QuestionInterface、LoginSystemInterface、FileManagerInterface
- 新增services包,实现具体业务逻辑类
- 新增models包,存放数据模型
- 新增factories包,实现服务工厂
- 修改Main.java使用接口编程
- 完善.gitignore文件
- 符合'先定义接口类'的评分标准
develop
imok 2 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;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
LoginSystem loginSystem = new LoginSystem();
LoginSystemInterface loginSystem = ServiceFactory.createLoginSystem();
QuestionGenerator generator = new QuestionGenerator();
FileManager fileManager = new FileManager();
FileManagerInterface fileManager = ServiceFactory.createFileManager();
while (true) {
// 登录阶段
User currentUser = loginSystem.login(scanner);
System.out.print("请输入用户名和密码(用空格隔开):");
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) {
System.out.println("请输入正确的用户名、密码");
continue;
}
System.out.println("当前选择为" + currentUser.getLevel().getDisplayName() + "出题");
// 主循环
while (true) {
System.out.println("准备生成" + currentUser.getLevel().getDisplayName() +
"数学题目,请输入生成题目数量(输入-1将退出当前用户重新登录");
String input = scanner.nextLine().trim();
String command = scanner.nextLine().trim();
// 检查切换命令
if (input.startsWith("切换为")) {
String levelName = input.substring(3).trim();
if (command.startsWith("切换为")) {
String levelName = command.substring(3).trim();
DifficultyLevel newLevel = loginSystem.switchLevel(levelName);
if (newLevel != null) {
currentUser.setLevel(newLevel);
@ -35,21 +49,18 @@ public class Main {
}
}
// 检查退出命令
if (input.equals("-1")) {
if (command.equals("-1")) {
System.out.println("退出当前用户,重新登录...");
break;
}
// 生成题目
try {
int count = Integer.parseInt(input);
int count = Integer.parseInt(command);
if (count < 10 || count > 30) {
System.out.println("题目数量应在10-30之间");
continue;
}
// 生成题目并检查重复
String[] questions = generator.generateQuestions(currentUser.getLevel(), count,
currentUser.getUsername());
if (questions == null) {
@ -57,7 +68,6 @@ public class Main {
continue;
}
// 保存文件
boolean success = fileManager.saveQuestions(currentUser, questions);
if (success) {
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 {
PRIMARY("小学"),
JUNIOR("初中"),
SENIOR("高中");
private final String displayName;
DifficultyLevel(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
public static DifficultyLevel fromString(String text) {
for (DifficultyLevel level : DifficultyLevel.values()) {
if (level.displayName.equals(text)) {
return level;
}
}
return null;
}
package models;
public enum DifficultyLevel {
PRIMARY("小学"),
JUNIOR("初中"),
SENIOR("高中");
private final String displayName;
DifficultyLevel(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
public static DifficultyLevel fromString(String text) {
for (DifficultyLevel level : DifficultyLevel.values()) {
if (level.displayName.equals(text)) {
return level;
}
}
return null;
}
}

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

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

@ -1,62 +1,48 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class LoginSystem {
private Map<String, User> users;
public LoginSystem() {
initializeUsers();
}
private void initializeUsers() {
users = new HashMap<>();
// 小学账户
users.put("张三1", new User("张三1", "123", DifficultyLevel.PRIMARY));
users.put("张三2", new User("张三2", "123", DifficultyLevel.PRIMARY));
users.put("张三3", new User("张三3", "123", DifficultyLevel.PRIMARY));
// 初中账户
users.put("李四1", new User("李四1", "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("王五2", new User("王五2", "123", DifficultyLevel.SENIOR));
users.put("王五3", new User("王五3", "123", DifficultyLevel.SENIOR));
}
public User login(Scanner scanner) {
while (true) {
System.out.print("请输入用户名和密码(用空格隔开):");
String input = scanner.nextLine().trim();
String[] parts = input.split("\\s+");
if (parts.length != 2) {
System.out.println("请输入正确的用户名、密码");
continue;
}
String username = parts[0];
String password = parts[1];
User user = users.get(username);
if (user != null && user.getPassword().equals(password)) {
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;
}
package services;
import interfaces.LoginSystemInterface;
import models.User;
import models.DifficultyLevel;
import java.util.HashMap;
import java.util.Map;
public class LoginSystem implements LoginSystemInterface {
private Map<String, User> users;
public LoginSystem() {
initializeUsers();
}
private void initializeUsers() {
users = new HashMap<>();
users.put("张三1", new User("张三1", "123", DifficultyLevel.PRIMARY));
users.put("张三2", new User("张三2", "123", DifficultyLevel.PRIMARY));
users.put("张三3", new User("张三3", "123", DifficultyLevel.PRIMARY));
users.put("李四1", new User("李四1", "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("王五2", new User("王五2", "123", DifficultyLevel.SENIOR));
users.put("王五3", new User("王五3", "123", DifficultyLevel.SENIOR));
}
@Override
public User login(String username, String password) {
User user = users.get(username);
if (user != null && user.getPassword().equals(password)) {
return user;
}
return null;
}
@Override
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;
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++) {
String question;
int attempts = 0;
do {
question = generateSingleQuestion(level, i + 1);
attempts++;
if (attempts > 100) {
return null; // 避免无限循环
}
} while (existingQuestions.contains(question) || newQuestions.contains(question));
newQuestions.add(question);
questions[i] = question;
}
return questions;
}
private String generateSingleQuestion(DifficultyLevel level, int questionNumber) {
int operandCount = random.nextInt(5) + 1; // 1-5个操作数
StringBuilder question = new StringBuilder(questionNumber + ". ");
switch (level) {
case PRIMARY:
question.append(generatePrimaryQuestion(operandCount));
break;
case JUNIOR:
question.append(generateJuniorQuestion(operandCount));
break;
case SENIOR:
question.append(generateSeniorQuestion(operandCount));
break;
}
question.append(" = ");
return question.toString();
}
private String generatePrimaryQuestion(int operandCount) {
String[] operators = {"+", "-", "*", "/"};
StringBuilder question = new StringBuilder();
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
question.append(" ").append(operators[random.nextInt(operators.length)]).append(" ");
}
question.append(random.nextInt(100) + 1);
// 随机添加括号(小学难度)
if (operandCount > 2 && random.nextDouble() < 0.3) {
question.insert(0, "(").append(")");
}
}
return question.toString();
}
private String generateJuniorQuestion(int operandCount) {
String question = generatePrimaryQuestion(operandCount);
// 确保至少有一个平方或开根号
if (random.nextBoolean()) {
return "√" + (random.nextInt(100) + 1) + " + " + question;
} else {
return "(" + (random.nextInt(10) + 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;
}
package services;
import interfaces.QuestionInterface;
import models.DifficultyLevel;
import java.util.Random;
public class MathQuestion implements QuestionInterface {
private String questionText;
private DifficultyLevel difficulty;
private Random random;
public MathQuestion(DifficultyLevel difficulty) {
this.difficulty = difficulty;
this.random = new Random();
this.questionText = generateQuestion();
}
@Override
public String generateQuestion() {
int operandCount = random.nextInt(5) + 1;
StringBuilder question = new StringBuilder();
switch (difficulty) {
case PRIMARY:
question.append(generatePrimaryQuestion(operandCount));
break;
case JUNIOR:
question.append(generateJuniorQuestion(operandCount));
break;
case SENIOR:
question.append(generateSeniorQuestion(operandCount));
break;
}
question.append(" = ");
return question.toString();
}
@Override
public boolean isValid() {
return questionText != null && !questionText.trim().isEmpty();
}
@Override
public String getQuestionText() {
return questionText;
}
@Override
public DifficultyLevel getDifficulty() {
return difficulty;
}
private String generatePrimaryQuestion(int operandCount) {
String[] operators = {"+", "-", "*", "/"};
StringBuilder question = new StringBuilder();
for (int i = 0; i < operandCount; i++) {
if (i > 0) {
question.append(" ").append(operators[random.nextInt(operators.length)]).append(" ");
}
question.append(random.nextInt(100) + 1);
if (operandCount > 2 && random.nextDouble() < 0.3) {
question.insert(0, "(").append(")");
}
}
return question.toString();
}
private String generateJuniorQuestion(int operandCount) {
String question = generatePrimaryQuestion(operandCount);
if (random.nextBoolean()) {
return "√" + (random.nextInt(100) + 1) + " + " + question;
} else {
return "(" + (random.nextInt(10) + 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