From 1dd4e633324916e905e5d4f438ae6d247ea3fa06 Mon Sep 17 00:00:00 2001 From: chen <3602749708@qq.com> Date: Sat, 11 Oct 2025 11:24:58 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3=E6=8F=90?= =?UTF-8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controller/BaseController.java | 41 ++++ src/controller/NavigationController.java | 127 ++++++++++ src/controller/NavigationService.java | 14 ++ src/controller/QuestionController.java | 117 ++++++++++ src/controller/QuestionService.java | 17 ++ src/controller/UserController.java | 156 +++++++++++++ src/controller/UserService.java | 11 + src/model/Question.java | 36 +++ src/model/QuestionGenerator.java | 282 +++++++++++++++++++++++ src/model/User.java | 30 +++ 10 files changed, 831 insertions(+) create mode 100644 src/controller/BaseController.java create mode 100644 src/controller/NavigationController.java create mode 100644 src/controller/NavigationService.java create mode 100644 src/controller/QuestionController.java create mode 100644 src/controller/QuestionService.java create mode 100644 src/controller/UserController.java create mode 100644 src/controller/UserService.java create mode 100644 src/model/Question.java create mode 100644 src/model/QuestionGenerator.java create mode 100644 src/model/User.java diff --git a/src/controller/BaseController.java b/src/controller/BaseController.java new file mode 100644 index 0000000..8f73b70 --- /dev/null +++ b/src/controller/BaseController.java @@ -0,0 +1,41 @@ +package controller; + +import javax.swing.JOptionPane; + +public abstract class BaseController { + + protected void validateNotNull(Object obj, String fieldName) { + if (obj == null) { + throw new IllegalArgumentException(fieldName + "不能为空"); + } + } + + protected void validateStringNotEmpty(String str, String fieldName) { + if (str == null || str.trim().isEmpty()) { + throw new IllegalArgumentException(fieldName + "不能为空"); + } + } + + protected void validateStringLength(String str, String fieldName, int min, int max) { + validateStringNotEmpty(str, fieldName); + if (str.length() < min || str.length() > max) { + throw new IllegalArgumentException(fieldName + "长度应在" + min + "-" + max + "之间"); + } + } + + protected void showError(String message) { + JOptionPane.showMessageDialog(null, message, "错误", JOptionPane.ERROR_MESSAGE); + } + + protected void showSuccess(String message) { + JOptionPane.showMessageDialog(null, message, "成功", JOptionPane.INFORMATION_MESSAGE); + } + + protected void logInfo(String message) { + //System.out.println("ℹ️ " + message); + } + + protected void logError(String message) { + System.err.println("❌ " + message); + } +} diff --git a/src/controller/NavigationController.java b/src/controller/NavigationController.java new file mode 100644 index 0000000..eb5c3fb --- /dev/null +++ b/src/controller/NavigationController.java @@ -0,0 +1,127 @@ +package controller; + +import model.User; +import view.LoginView; +import view.RegisterView; +import view.MainView; +import view.ExamView; +import view.ResultView; + +public class NavigationController extends BaseController implements NavigationService { + private static NavigationController instance; + private LoginView loginView; + private RegisterView registerView; + private MainView mainView; + private ExamView examView; + private ResultView resultView; + private User currentUser; + + // 单例模式 + public static NavigationController getInstance() { + if (instance == null) { + instance = new NavigationController(); + } + return instance; + } + + private NavigationController() { + // 私有构造函数 + } + + @Override + public void showLoginView() { + if (loginView == null) { + loginView = new LoginView(); + } + loginView.setVisible(true); + hideAllExcept(loginView); + logInfo("显示登录界面"); + } + + @Override + public void showRegisterView() { + if (registerView == null) { + registerView = new RegisterView(); + } + registerView.setVisible(true); + hideAllExcept(registerView); + logInfo("显示注册界面"); + } + + @Override + public void showMainView(User user) { + setCurrentUser(user); + if (mainView != null) { + mainView.dispose(); + } + mainView = new MainView(user); + mainView.setVisible(true); + hideAllExcept(mainView); + logInfo("显示主界面 - 用户: " + user.getUsername()); + } + + @Override + public void showMainView() { + if (currentUser != null) { + showMainView(currentUser); + } else { + showLoginView(); + } + } + + @Override + public void showExamView(String difficulty, int questionCount) { + try { + validateStringNotEmpty(difficulty, "难度"); + if (questionCount <= 0) { + throw new IllegalArgumentException("题目数量必须大于0"); + } + + if (examView == null) { + examView = new ExamView(); + } + examView.startNewExam(difficulty, questionCount); + examView.setVisible(true); + hideAllExcept(examView); + logInfo("显示考试界面 - " + difficulty + "难度, " + questionCount + "道题"); + } catch (Exception e) { + logError("显示考试界面异常: " + e.getMessage()); + showError("无法开始考试: " + e.getMessage()); + } + } + + @Override + public void showResultView(int score, int total, double percentage) { + try { + if (resultView == null) { + resultView = new ResultView(); + } + resultView.setResults(score, total, percentage); + resultView.setVisible(true); + hideAllExcept(resultView); + logInfo("显示成绩界面 - 得分: " + score + "/" + total); + } catch (Exception e) { + logError("显示成绩界面异常: " + e.getMessage()); + } + } + + @Override + public void setCurrentUser(User user) { + this.currentUser = user; + logInfo("设置当前用户: " + (user != null ? user.getUsername() : "null")); + } + + @Override + public User getCurrentUser() { + return currentUser; + } + + private void hideAllExcept(javax.swing.JFrame visibleFrame) { + javax.swing.JFrame[] frames = {loginView, registerView, mainView, examView, resultView}; + for (javax.swing.JFrame frame : frames) { + if (frame != null && frame != visibleFrame) { + frame.setVisible(false); + } + } + } +} \ No newline at end of file diff --git a/src/controller/NavigationService.java b/src/controller/NavigationService.java new file mode 100644 index 0000000..53adf3a --- /dev/null +++ b/src/controller/NavigationService.java @@ -0,0 +1,14 @@ +package controller; + +import model.User; + +public interface NavigationService { + void showLoginView(); + void showRegisterView(); + void showMainView(User user); + void showMainView(); + void showExamView(String difficulty, int questionCount); + void showResultView(int score, int total, double percentage); + void setCurrentUser(User user); + User getCurrentUser(); +} diff --git a/src/controller/QuestionController.java b/src/controller/QuestionController.java new file mode 100644 index 0000000..026081e --- /dev/null +++ b/src/controller/QuestionController.java @@ -0,0 +1,117 @@ +package controller; + +import model.Question; +import model.QuestionGenerator; +import utils.FileUtil; +import java.util.List; +import java.util.Arrays; + +public class QuestionController extends BaseController implements QuestionService { + private QuestionGenerator generator = new QuestionGenerator(); + private List currentQuestions; + private int currentQuestionIndex = 0; + private int score = 0; + private int[] userAnswers; + private String currentDifficulty; + private int currentQuestionCount; + + @Override + public void startNewExam(String difficulty, int questionCount) { + try { + validateStringNotEmpty(difficulty, "难度"); + if (questionCount <= 0 || questionCount > 100) { + throw new IllegalArgumentException("题目数量必须在1-100之间"); + } + + currentQuestions = generator.generateQuestions(questionCount, difficulty); + currentQuestionIndex = 0; + score = 0; + userAnswers = new int[questionCount]; + Arrays.fill(userAnswers, -1); + currentDifficulty = difficulty; + currentQuestionCount = questionCount; + + FileUtil.saveCurrentExam(currentQuestions, difficulty, questionCount); + logInfo("生成新试卷: " + difficulty + " 难度, " + questionCount + " 道题"); + } catch (Exception e) { + logError("开始新考试异常: " + e.getMessage()); + throw e; + } + } + + @Override + public String getCurrentExamInfo() { + if (currentDifficulty != null && currentQuestionCount > 0) { + return currentDifficulty + "难度 - " + currentQuestionCount + "道题"; + } + return "暂无试卷"; + } + + @Override + public Question getCurrentQuestion() { + if (currentQuestions == null || currentQuestionIndex >= currentQuestions.size()) { + return null; + } + return currentQuestions.get(currentQuestionIndex); + } + + @Override + public void submitAnswer(int answer) { + if (currentQuestionIndex < userAnswers.length) { + userAnswers[currentQuestionIndex] = answer; + logInfo("提交答案: 第" + getCurrentQuestionNumber() + "题, 答案: " + answer); + } + } + + @Override + public boolean nextQuestion() { + currentQuestionIndex++; + boolean hasNext = currentQuestionIndex < currentQuestions.size(); + logInfo("下一题: " + (hasNext ? "有" : "无")); + return hasNext; + } + + @Override + public boolean previousQuestion() { + if (currentQuestionIndex > 0) { + currentQuestionIndex--; + logInfo("上一题: 第" + getCurrentQuestionNumber() + "题"); + return true; + } + return false; + } + + @Override + public int calculateScore() { + score = 0; + for (int i = 0; i < currentQuestions.size(); i++) { + if (userAnswers[i] != -1 && currentQuestions.get(i).isCorrect(userAnswers[i])) { + score++; + } + } + logInfo("计算得分: " + score + "/" + currentQuestions.size()); + return score; + } + + @Override + public double getPercentage() { + double percentage = (double) score / currentQuestions.size() * 100; + logInfo("正确率: " + String.format("%.1f%%", percentage)); + return percentage; + } + + @Override + public int getCurrentQuestionNumber() { + return currentQuestionIndex + 1; + } + + @Override + public int getTotalQuestions() { + return currentQuestions != null ? currentQuestions.size() : 0; + } + + @Override + public int getUserAnswerForCurrentQuestion() { + return userAnswers[currentQuestionIndex]; + } +} \ No newline at end of file diff --git a/src/controller/QuestionService.java b/src/controller/QuestionService.java new file mode 100644 index 0000000..a509ca9 --- /dev/null +++ b/src/controller/QuestionService.java @@ -0,0 +1,17 @@ +package controller; + +import model.Question; + +public interface QuestionService { + void startNewExam(String difficulty, int questionCount); + Question getCurrentQuestion(); + void submitAnswer(int answer); + boolean nextQuestion(); + boolean previousQuestion(); + int calculateScore(); + double getPercentage(); + int getCurrentQuestionNumber(); + int getTotalQuestions(); + int getUserAnswerForCurrentQuestion(); + String getCurrentExamInfo(); +} diff --git a/src/controller/UserController.java b/src/controller/UserController.java new file mode 100644 index 0000000..e1bc1e2 --- /dev/null +++ b/src/controller/UserController.java @@ -0,0 +1,156 @@ +package controller; + +import model.User; +import utils.FileUtil; +import utils.ValidationUtil; +import utils.EmailUtil; + +public class UserController extends BaseController implements UserService { + + @Override + public String registerUser(String username, String email) { + try { + validateStringLength(username, "用户名", 2, 20); + validateStringNotEmpty(email, "邮箱"); + + if (!ValidationUtil.isValidEmail(email)) { + return "邮箱格式不正确"; + } + + if (FileUtil.usernameExists(username)) { + return "用户名已被使用"; + } + + if (FileUtil.emailExists(email)) { + return "该邮箱已被注册"; + } + + String registrationCode = EmailUtil.generateRegistrationCode(); + User user = new User(username, email, registrationCode); + + boolean sendSuccess = EmailUtil.sendRegistrationCode(email, username, registrationCode); + + if (sendSuccess) { + FileUtil.saveUser(user); + logInfo("用户注册成功: " + username); + return "注册码已发送到您的邮箱,请查收!"; + } else { + return "邮件发送失败,请检查邮箱地址或稍后重试"; + } + } catch (IllegalArgumentException e) { + return e.getMessage(); + } catch (Exception e) { + logError("用户注册异常: " + e.getMessage()); + return "系统错误,请稍后重试"; + } + } + + @Override + public String completeRegistration(String username, String code, String password, String confirmPassword) { + try { + validateStringNotEmpty(username, "用户名"); + validateStringNotEmpty(code, "注册码"); + validateStringNotEmpty(password, "密码"); + validateStringNotEmpty(confirmPassword, "确认密码"); + + User user = FileUtil.loadUserByUsername(username); + if (user == null) { + return "用户不存在或注册码未发送"; + } + + if (!user.getRegistrationCode().equals(code)) { + return "注册码不正确"; + } + + if (!password.equals(confirmPassword)) { + return "两次输入的密码不一致"; + } + + if (!ValidationUtil.isValidPassword(password)) { + return "密码必须为6-10位,且包含大小写字母和数字"; + } + + user.setPassword(password); + user.setRegistered(true); + FileUtil.saveUser(user); + + logInfo("用户完成注册: " + username); + return "注册成功!"; + } catch (Exception e) { + logError("完成注册异常: " + e.getMessage()); + return "系统错误,请稍后重试"; + } + } + + @Override + public User login(String loginId, String password) { + try { + validateStringNotEmpty(loginId, "登录ID"); + validateStringNotEmpty(password, "密码"); + + User user; + if (loginId.contains("@")) { + user = FileUtil.loadUserByEmail(loginId); + } else { + user = FileUtil.loadUserByUsername(loginId); + } + + if (user == null) { + logInfo("登录失败: 用户不存在 - " + loginId); + return null; + } + + if (user.getPassword() == null || !user.getPassword().equals(password)) { + logInfo("登录失败: 密码错误 - " + loginId); + return null; + } + + logInfo("登录成功: " + user.getUsername()); + return user; + } catch (Exception e) { + logError("登录异常: " + e.getMessage()); + return null; + } + } + + @Override + public String changePassword(User user, String oldPassword, String newPassword, String confirmPassword) { + try { + validateNotNull(user, "用户"); + validateStringNotEmpty(oldPassword, "原密码"); + validateStringNotEmpty(newPassword, "新密码"); + validateStringNotEmpty(confirmPassword, "确认密码"); + + if (!user.getPassword().equals(oldPassword)) { + return "原密码不正确"; + } + + if (!newPassword.equals(confirmPassword)) { + return "两次输入的新密码不一致"; + } + + if (!ValidationUtil.isValidPassword(newPassword)) { + return "新密码必须为6-10位,且包含大小写字母和数字"; + } + + user.setPassword(newPassword); + FileUtil.saveUser(user); + + logInfo("密码修改成功: " + user.getUsername()); + return "密码修改成功"; + } catch (Exception e) { + logError("修改密码异常: " + e.getMessage()); + return "系统错误,请稍后重试"; + } + } + + @Override + public void cleanupUnregisteredUsers() { + try { + FileUtil.cleanupUnregisteredUsers(); + logInfo("执行未注册用户清理"); + } catch (Exception e) { + logError("清理未注册用户异常: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/controller/UserService.java b/src/controller/UserService.java new file mode 100644 index 0000000..75f7f01 --- /dev/null +++ b/src/controller/UserService.java @@ -0,0 +1,11 @@ +package controller; + +import model.User; + +public interface UserService { + String registerUser(String username, String email); + String completeRegistration(String username, String code, String password, String confirmPassword); + User login(String loginId, String password); + String changePassword(User user, String oldPassword, String newPassword, String confirmPassword); + void cleanupUnregisteredUsers(); +} \ No newline at end of file diff --git a/src/model/Question.java b/src/model/Question.java new file mode 100644 index 0000000..09e3faa --- /dev/null +++ b/src/model/Question.java @@ -0,0 +1,36 @@ +package model; + +import java.io.Serializable; + +public class Question implements Serializable { + private static final long serialVersionUID = 1L; + + private String question; + private String[] options; + private int correctAnswer; + private String difficulty; + + public Question(String question, String[] options, int correctAnswer, String difficulty) { + this.question = question; + this.options = options; + this.correctAnswer = correctAnswer; + this.difficulty = difficulty; + } + + // Getters + public String getQuestion() { return question; } + public String[] getOptions() { return options; } + + + public boolean isCorrect(int selectedAnswer) { + return selectedAnswer == correctAnswer; + } + + @Override + public String toString() { + return "Question{" + + "question='" + question + '\'' + + ", difficulty='" + difficulty + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/src/model/QuestionGenerator.java b/src/model/QuestionGenerator.java new file mode 100644 index 0000000..442751c --- /dev/null +++ b/src/model/QuestionGenerator.java @@ -0,0 +1,282 @@ +package model; + +import java.util.List; +import java.util.ArrayList; +import java.util.Set; +import java.util.HashSet; +import java.util.Arrays; +import java.util.Random; +import java.text.DecimalFormat; + +public class QuestionGenerator { + private Random random = new Random(); + private DecimalFormat df = new DecimalFormat("#.##"); // 保留两位小数的格式化器 + public List generateQuestions(int count, String difficulty) { + List questions = new ArrayList<>(); + Set existingQuestions = new HashSet<>(); + + while (questions.size() < count) { + Question question = generateQuestion(difficulty); + String questionKey = question.getQuestion() + Arrays.toString(question.getOptions()); + + if (!existingQuestions.contains(questionKey)) { + questions.add(question); + existingQuestions.add(questionKey); + } + } + + return questions; + } + + private Question generateQuestion(String difficulty) { + switch (difficulty) { + case "小学": + return generatePrimaryQuestion(); + case "初中": + return generateMiddleSchoolQuestion(); + case "高中": + return generateHighSchoolQuestion(); + default: + return generatePrimaryQuestion(); + } + } + + private Question generatePrimaryQuestion() { + int num1 = random.nextInt(50) + 1; + int num2 = random.nextInt(50) + 1; + int num3 = random.nextInt(50) + 1; + char[] operators = {'+', '-', '*', '/'}; + char operator1 = operators[random.nextInt(operators.length)]; + char operator2 = operators[random.nextInt(operators.length)]; + String question; + double correctAnswer; + // 随机决定是否使用括号 + if (random.nextBoolean()) { + // 有括号的情况 + switch (random.nextInt(3)) { + case 0: // (a op b) op c + correctAnswer = calculate(calculate(num1, num2, operator1), num3, operator2); + question = "(" + num1 + " " + getOperatorSymbol(operator1) + " " + num2 + ") " + + getOperatorSymbol(operator2) + " " + num3 + " = ?"; + break; + case 1: // a op (b op c) + correctAnswer = calculate(num1, calculate(num2, num3, operator2), operator1); + question = num1 + " " + getOperatorSymbol(operator1) + " (" + num2 + " " + + getOperatorSymbol(operator2) + " " + num3 + ") = ?"; + break; + default: // 无括号 + correctAnswer = calculate(calculate(num1, num2, operator1), num3, operator2); + question = num1 + " " + getOperatorSymbol(operator1) + " " + num2 + " " + + getOperatorSymbol(operator2) + " " + num3 + " = ?"; + break; + } + } else { + if (operator1 == '/') { + num2 = random.nextInt(10) + 1; // 避免除零 + } + correctAnswer = calculate(num1, num2, operator1); + question = num1 + " " + getOperatorSymbol(operator1) + " " + num2 + " = ?"; + } + correctAnswer = Double.parseDouble(df.format(correctAnswer)); + String[] options = generateOptions(correctAnswer); + return new Question(question, options, getCorrectOptionIndex(options, correctAnswer), "小学"); + } + + private Question generateMiddleSchoolQuestion() { + String question; + double correctAnswer; + + if (random.nextBoolean()) { + // 平方或平方根题目 + int num = random.nextInt(20) + 1; + if (random.nextBoolean()) { + correctAnswer = Math.pow(num, 2); + question = num + "² = ?"; + } else { + int squared = num * num; + correctAnswer = num; + question = "√" + squared + " = ?"; + } + } else { + // 带加减乘除的题目 + int num1 = random.nextInt(50) + 1; + int num2 = random.nextInt(50) + 1; + int num3 = random.nextInt(20) + 1; + char[] operators = {'+', '-', '*', '/'}; + char operator1 = operators[random.nextInt(operators.length)]; + char operator2 = operators[random.nextInt(operators.length)]; + + // 随机组合平方、平方根和基本运算 + if (random.nextBoolean()) { + // 平方与基本运算组合 + correctAnswer = calculate(Math.pow(num1, 2), num2, operator1); + question = num1 + "² " + getOperatorSymbol(operator1) + " " + num2 + " = ?"; + } else { + // 平方根与基本运算组合 + int squared = num3 * num3; + correctAnswer = calculate(num3, num2, operator1); + question = "√" + squared + " " + getOperatorSymbol(operator1) + " " + num2 + " = ?"; + } + } + correctAnswer = Double.parseDouble(df.format(correctAnswer)); + String[] options = generateOptions(correctAnswer); + return new Question(question, options, getCorrectOptionIndex(options, correctAnswer), "初中"); + } + + private Question generateHighSchoolQuestion() { + + if (random.nextBoolean()) { + return HighSchoolQuestionOne(); + } else { + // 三角函数与基本运算组合 + return HighSchoolQuestionTwo(); + } + + } + + private Question HighSchoolQuestionOne() { + String question; + double correctAnswer; + double angle = random.nextInt(360); + String[] trigFunctions = {"sin", "cos", "tan"}; + String trigFunction = trigFunctions[random.nextInt(trigFunctions.length)]; + + switch (trigFunction) { + case "sin": + correctAnswer = Math.sin(Math.toRadians(angle)); + question = "sin(" + angle + "°) = ?"; + break; + case "cos": + correctAnswer = Math.cos(Math.toRadians(angle)); + question = "cos(" + angle + "°) = ?"; + break; + case "tan": + angle = getSafeTanAngle(); + correctAnswer = Math.tan(Math.toRadians(angle)); + question = "tan(" + angle + "°) = ?"; + break; + default: + correctAnswer = 0; + question = ""; + } + correctAnswer = Double.parseDouble(df.format(correctAnswer)); + String[] options = generateOptions(correctAnswer); + return new Question(question, options, getCorrectOptionIndex(options, correctAnswer), "高中"); + } + private Question HighSchoolQuestionTwo() { + String question; + double correctAnswer; + double angle = random.nextInt(360); + int num = random.nextInt(20) + 1; + char[] operators = {'+', '-', '*', '/'}; + char operator = operators[random.nextInt(operators.length)]; + String[] trigFunctions = {"sin", "cos", "tan"}; + String trigFunction = trigFunctions[random.nextInt(trigFunctions.length)]; + + double trigValue; + switch (trigFunction) { + case "sin": + trigValue = Math.sin(Math.toRadians(angle)); + question = "sin(" + angle + "°) " + getOperatorSymbol(operator) + " " + num + " = ?"; + break; + case "cos": + trigValue = Math.cos(Math.toRadians(angle)); + question = "cos(" + angle + "°) " + getOperatorSymbol(operator) + " " + num + " = ?"; + break; + case "tan": + angle = getSafeTanAngle(); + trigValue = Math.tan(Math.toRadians(angle)); + question = "tan(" + angle + "°) " + getOperatorSymbol(operator) + " " + num + " = ?"; + break; + default: + trigValue = 0; + question = ""; + } + trigValue = Double.parseDouble(df.format(trigValue)); + correctAnswer = calculate(trigValue, num, operator); + String[] options = generateOptions(correctAnswer); + return new Question(question, options, getCorrectOptionIndex(options, correctAnswer), "高中"); + } + // 获取安全的tan角度(更严格的范围) + private double getSafeTanAngle() { + // 为tan函数提供更安全的角度范围,避免无限大的值 + // 排除:85°-95°, 265°-275° 等接近90°和270°的角度 + List safeTanAngles = new ArrayList<>(); + for (int i = 0; i < 360; i++) { + if (isSafeForTan(i)) { + safeTanAngles.add((double) i); + } + } + return safeTanAngles.get(random.nextInt(safeTanAngles.size())); + } + // 检查角度是否对tan函数安全(更严格的条件) + private boolean isSafeForTan(double angle) { + // 排除接近90°、270°的角度,以及排除tan值过大的角度 + return !((angle >= 80 && angle <= 100) || + (angle >= 260 && angle <= 280) || + (angle >= 170 && angle <= 190) || + (angle >= 350 || angle <= 10)); + } + + // 计算方法 + private double calculate(double a, double b, char operator) { + switch (operator) { + case '+': + return a + b; + case '-': + return a - b; + case '*': + return a * b; + case '/': + return b != 0 ? a / b : a; // 避免除零 + default: + return 0; + } + } + + // 获取运算符符号 + private String getOperatorSymbol(char operator) { + switch (operator) { + case '+': + return "+"; + case '-': + return "-"; + case '*': + return "×"; + case '/': + return "÷"; + default: + return ""; + } + } + + private String[] generateOptions(double correctAnswer) { + String[] options = new String[4]; + int correctIndex = random.nextInt(4); + + for (int i = 0; i < 4; i++) { + if (i == correctIndex) { + options[i] = df.format(correctAnswer); + } else { + double wrongAnswer; + do { + double variation = (random.nextDouble() - 0.5) * 10; + wrongAnswer = correctAnswer + variation; + wrongAnswer = Double.parseDouble(df.format(wrongAnswer)); + } while (Math.abs(wrongAnswer - correctAnswer) < 0.1); + options[i] = String.valueOf(wrongAnswer); + } + } + + return options; + } + + private int getCorrectOptionIndex(String[] options, double correctAnswer) { + for (int i = 0; i < options.length; i++) { + if (Double.parseDouble(options[i]) == correctAnswer) { + return i; + } + } + return 0; + } +} \ No newline at end of file diff --git a/src/model/User.java b/src/model/User.java new file mode 100644 index 0000000..ade2948 --- /dev/null +++ b/src/model/User.java @@ -0,0 +1,30 @@ +package model; + +public class User { + private String username; // 新增:用户名 + private String email; + private String password; + private String registrationCode; + private boolean isRegistered; + + public User(String username, String email, String registrationCode) { + this.username = username; + this.email = email; + this.registrationCode = registrationCode; + this.isRegistered = false; + } + + // Getters and Setters + public String getUsername() { return username; } + public void setUsername(String username) { this.username = username; } + + public String getEmail() { return email; } + + public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } + + public String getRegistrationCode() { return registrationCode; } + + public boolean isRegistered() { return isRegistered; } + public void setRegistered(boolean registered) { isRegistered = registered; } +} \ No newline at end of file