allQuestions;
+ private int[] userSelections;
+ private int currentDisplayIndex; // 当前显示的题目索引
+
+ public QuizFrame(String level, int questionCount, LevelSelectionFrame parent) {
+ this.parentFrame = parent;
+ this.level = level;
+ this.totalQuestions = questionCount;
+ this.questionController = new QuestionController();
+ this.questionController.startNewQuiz(level, questionCount);
+
+ // 获取所有题目
+ this.allQuestions = questionController.getCurrentQuestions();
+ this.userSelections = new int[questionCount];
+ this.currentDisplayIndex = 0;
+
+ // 初始化选择为-1(未选择)
+ for (int i = 0; i < userSelections.length; i++) {
+ userSelections[i] = -1;
+ }
+
+ initializeUI();
+ showCurrentQuestion();
+ }
+
+ private void initializeUI() {
+ setTitle("数学答题 - " + level);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setSize(700, 550);
+ setLocationRelativeTo(null);
+ setResizable(false);
+
+ JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+
+ // 进度条
+ progressBar = new JProgressBar(0, totalQuestions);
+ progressBar.setValue(0);
+ progressBar.setStringPainted(true);
+ progressBar.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
+ mainPanel.add(progressBar, BorderLayout.NORTH);
+
+ // 问题面板
+ JPanel questionPanel = new JPanel(new BorderLayout(10, 20));
+ questionPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+
+ questionNumberLabel = new JLabel("", JLabel.CENTER);
+ questionNumberLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
+ questionNumberLabel.setForeground(new Color(0, 100, 200));
+ questionPanel.add(questionNumberLabel, BorderLayout.NORTH);
+
+ questionTextLabel = new JLabel("", JLabel.CENTER);
+ questionTextLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 20));
+ questionTextLabel.setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10));
+ questionPanel.add(questionTextLabel, BorderLayout.CENTER);
+
+ mainPanel.add(questionPanel, BorderLayout.CENTER);
+
+ // 选项面板
+ JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 10, 10));
+ optionsPanel.setBorder(
+ BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY), "请选择答案"));
+
+ optionButtons = new JRadioButton[4];
+ buttonGroup = new ButtonGroup();
+
+ for (int i = 0; i < 4; i++) {
+ optionButtons[i] = new JRadioButton();
+ optionButtons[i].setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
+ optionButtons[i].setBackground(Color.WHITE);
+ optionButtons[i].setFocusPainted(false);
+ optionButtons[i].setPreferredSize(new Dimension(400, 40));
+
+ final int index = i;
+ optionButtons[i].addActionListener(
+ e -> {
+ // 保存当前选择
+ userSelections[currentDisplayIndex] = index;
+ System.out.println("用户选择: 第" + (currentDisplayIndex + 1) + "题 -> 选项" + index);
+ });
+
+ buttonGroup.add(optionButtons[i]);
+ optionsPanel.add(optionButtons[i]);
+ }
+
+ JPanel optionsContainer = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ optionsContainer.add(optionsPanel);
+ mainPanel.add(optionsContainer, BorderLayout.SOUTH);
+
+ // 控制面板
+ JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
+
+ previousButton = new JButton("上一题");
+ previousButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
+ previousButton.setBackground(new Color(169, 169, 169));
+ previousButton.setForeground(Color.WHITE);
+ previousButton.setFocusPainted(false);
+ previousButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
+ previousButton.setEnabled(false); // 第一题时禁用
+
+ nextButton = new JButton("下一题");
+ nextButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
+ nextButton.setBackground(new Color(70, 130, 180));
+ nextButton.setForeground(Color.WHITE);
+ nextButton.setFocusPainted(false);
+ nextButton.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
+
+ controlPanel.add(previousButton);
+ controlPanel.add(nextButton);
+
+ JPanel southPanel = new JPanel(new BorderLayout());
+ southPanel.add(optionsContainer, BorderLayout.CENTER);
+ southPanel.add(controlPanel, BorderLayout.SOUTH);
+ mainPanel.add(southPanel, BorderLayout.SOUTH);
+
+ // 添加事件监听器
+ previousButton.addActionListener(new PreviousQuestionAction());
+ nextButton.addActionListener(new NextQuestionAction());
+ // 添加顶部退出答题按钮
+ JPanel topPanel = new JPanel(new BorderLayout());
+
+ JButton exitButton = new JButton("退出答题");
+ exitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
+ exitButton.setBackground(new Color(220, 100, 100));
+ exitButton.setForeground(Color.WHITE);
+ exitButton.addActionListener(e -> exitQuiz());
+
+ progressBar = new JProgressBar(0, totalQuestions);
+ progressBar.setValue(0);
+ progressBar.setStringPainted(true);
+ progressBar.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
+
+ topPanel.add(exitButton, BorderLayout.WEST);
+ topPanel.add(progressBar, BorderLayout.CENTER);
+ mainPanel.add(topPanel, BorderLayout.NORTH);
+ add(mainPanel);
+ }
+
+ private void showCurrentQuestion() {
+ if (currentDisplayIndex >= allQuestions.size()) {
+ finishQuiz();
+ return;
+ }
+ Question currentQuestion = allQuestions.get(currentDisplayIndex);
+ questionNumberLabel.setText(
+ String.format("第 %d 题 / 共 %d 题", currentDisplayIndex + 1, totalQuestions));
+ questionTextLabel.setText(
+ ""
+ + currentQuestion.getQuestionText()
+ + "
");
+ String[] options = currentQuestion.getOptions();
+ for (int i = 0; i < 4; i++) {
+ String optionText =
+ String.format(
+ "%c. %s
", (char) ('A' + i), options[i]);
+ optionButtons[i].setText(optionText);
+ }
+ buttonGroup.clearSelection(); // 清除当前选择状态
+ // 恢复之前的选择(如果有)
+ if (userSelections[currentDisplayIndex] != -1) {
+ int previousSelection = userSelections[currentDisplayIndex];
+ if (previousSelection >= 0 && previousSelection < 4) {
+ optionButtons[previousSelection].setSelected(true);
+ }
+ }
+ // 更新进度条
+ progressBar.setValue(currentDisplayIndex);
+ progressBar.setString(
+ String.format(
+ "%d/%d (%.0f%%)",
+ currentDisplayIndex,
+ totalQuestions,
+ ((double) currentDisplayIndex / totalQuestions) * 100));
+ updateButtonStates(); // 更新按钮状态
+ }
+
+ private void exitQuiz() {
+ int result =
+ JOptionPane.showConfirmDialog(this, "确定要退出答题吗?所有进度将丢失。", "退出确认", JOptionPane.YES_NO_OPTION);
+ if (result == JOptionPane.YES_OPTION) {
+ parentFrame.setVisible(true);
+ this.dispose();
+ }
+ }
+
+ private void updateButtonStates() {
+ // 更新上一题按钮状态
+ previousButton.setEnabled(currentDisplayIndex > 0);
+
+ // 更新下一题按钮文本
+ if (currentDisplayIndex == totalQuestions - 1) {
+ nextButton.setText("完成答题");
+ } else {
+ nextButton.setText("下一题");
+ }
+ }
+
+ private class PreviousQuestionAction implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (currentDisplayIndex > 0) {
+ currentDisplayIndex--;
+ showCurrentQuestion();
+ }
+ }
+ }
+
+ private class NextQuestionAction implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // 检查是否选择了答案
+ int selectedIndex = -1;
+ for (int i = 0; i < 4; i++) {
+ if (optionButtons[i].isSelected()) {
+ selectedIndex = i;
+ break;
+ }
+ }
+ userSelections[currentDisplayIndex] = selectedIndex; // 保存当前选择
+ // 如果没有选择答案,提示用户但允许继续(除了最后一题)
+ if (selectedIndex == -1) {
+ int result =
+ JOptionPane.showConfirmDialog(
+ QuizFrame.this, "您还没有选择答案,确定要继续下一题吗?", "确认", JOptionPane.YES_NO_OPTION);
+ if (result != JOptionPane.YES_OPTION) {
+ return;
+ }
+ }
+ // 前进到下一题或完成
+ if (currentDisplayIndex < totalQuestions - 1) {
+ currentDisplayIndex++;
+ showCurrentQuestion();
+ } else {
+ submitAllAnswers(); // 完成所有题目,提交答案并显示分数
+ finishQuiz();
+ }
+ }
+ }
+
+ private void submitAllAnswers() { // 直接在本地计算分数
+ final int calculatedScore = calculateLocalScore(); // 使用final
+ // 创建一个新的QuestionController来显示正确分数
+ questionController =
+ new QuestionController() {
+ @Override
+ public int getScore() {
+ return calculatedScore; // 现在可以访问了
+ }
+
+ @Override
+ public int getTotalQuestions() {
+ return totalQuestions;
+ }
+
+ @Override
+ public double getPercentage() {
+ return (double) calculatedScore / totalQuestions * 100;
+ }
+
+ @Override
+ public int[] getUserAnswers() {
+ return userSelections;
+ }
+
+ @Override
+ public java.util.List getCurrentQuestions() {
+ return allQuestions;
+ }
+ };
+ }
+
+ private int calculateLocalScore() {
+ int score = 0;
+ for (int i = 0; i < totalQuestions; i++) {
+ if (userSelections[i] != -1 && allQuestions.get(i).isCorrect(userSelections[i])) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ private void finishQuiz() {
+ ScoreFrame scoreFrame =
+ new ScoreFrame(questionController, userSelections, allQuestions, parentFrame);
+ scoreFrame.setVisible(true);
+ this.dispose();
+ }
+}
diff --git a/src/com/mathlearning/view/RegisterFrame.java b/src/com/mathlearning/view/RegisterFrame.java
new file mode 100644
index 0000000..c5006db
--- /dev/null
+++ b/src/com/mathlearning/view/RegisterFrame.java
@@ -0,0 +1,279 @@
+package com.mathlearning.view;
+
+import com.mathlearning.controller.AuthController;
+import com.mathlearning.service.EmailService;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+public class RegisterFrame extends JFrame {
+ private AuthController authController;
+ private JTextField emailField;
+ private JLabel resultLabel;
+ private JButton registerButton;
+ private Timer countdownTimer;
+ private int remainingTime = 0;
+ private JTextField codeField;
+ private JButton submitButton;
+ private String currentEmail; // 存储当前正在注册的邮箱
+
+ public RegisterFrame() {
+ this.authController = new AuthController();
+ initializeUI();
+ }
+
+ private void initializeUI() {
+ setTitle("数学学习软件 - 注册");
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ setSize(500, 300); // 保持原有宽度以显示更长的提示信息
+ setLocationRelativeTo(null);
+ setResizable(false);
+
+ JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+
+ // 添加顶部返回按钮
+ JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ JButton backButton = new JButton("← 返回登录");
+ backButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
+ backButton.setBackground(new Color(200, 250, 190));
+ backButton.addActionListener(e -> backToLogin());
+ topPanel.add(backButton);
+ mainPanel.add(topPanel, BorderLayout.NORTH);
+
+ JLabel titleLabel = new JLabel("用户注册", JLabel.CENTER);
+ titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
+ mainPanel.add(titleLabel, BorderLayout.CENTER);
+
+ JPanel formPanel = new JPanel(new GridLayout(3, 2, 10, 10));
+ formPanel.setLayout(null);
+ JLabel emailLabel = new JLabel("邮箱地址:");
+ emailLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+ emailLabel.setBounds(20, 20, 100, 20);
+ emailField = new JTextField();
+ emailField.setBounds(100, 20, 180, 30);
+ // 添加邮箱输入框的焦点监听器,实现实时验证
+ emailField.addFocusListener(
+ new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ // 获得焦点时不清除内容
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ // 失去焦点时验证邮箱格式
+ validateEmailInRealTime();
+ }
+ });
+
+ // 添加输入监听器,实现输入时实时验证
+ emailField
+ .getDocument()
+ .addDocumentListener(
+ new javax.swing.event.DocumentListener() {
+ public void insertUpdate(javax.swing.event.DocumentEvent e) {
+ validateEmailInRealTime();
+ }
+
+ public void removeUpdate(javax.swing.event.DocumentEvent e) {
+ validateEmailInRealTime();
+ }
+
+ public void changedUpdate(javax.swing.event.DocumentEvent e) {
+ validateEmailInRealTime();
+ }
+ });
+
+ registerButton = new JButton("获取注册码");
+ registerButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+ registerButton.setBounds(285, 20, 140, 30);
+ registerButton.setEnabled(false); // 初始时禁用
+ JLabel codeLabel = new JLabel("注册码:");
+ codeLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+ codeLabel.setBounds(20, 60, 100, 20);
+ codeField = new JTextField();
+ codeField.setBounds(100, 60, 180, 30);
+ codeField.setEnabled(false); // 初始时禁用
+
+ submitButton = new JButton("注册");
+ submitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+ submitButton.setBounds(285, 60, 140, 30);
+ submitButton.setEnabled(false); // 初始时禁用
+
+ formPanel.add(emailLabel);
+ formPanel.add(emailField);
+ formPanel.add(new JLabel());
+ formPanel.add(registerButton);
+ formPanel.add(codeLabel);
+ formPanel.add(codeField);
+ formPanel.add(submitButton);
+
+ resultLabel = new JLabel("请输入有效的邮箱地址", JLabel.CENTER);
+ resultLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
+ resultLabel.setForeground(Color.BLUE);
+
+ mainPanel.add(formPanel, BorderLayout.CENTER);
+ mainPanel.add(resultLabel, BorderLayout.SOUTH);
+ registerButton.addActionListener(new RegisterAction());
+ submitButton.addActionListener(new SubmitAction());
+ countdownTimer = new Timer(1000, new CountdownAction());
+
+ add(mainPanel);
+ }
+
+ // 实时验证邮箱格式
+ private void validateEmailInRealTime() {
+ try {
+ String email = emailField.getText().trim();
+
+ if (email.isEmpty()) {
+ resultLabel.setText("请输入邮箱地址");
+ resultLabel.setForeground(Color.BLUE);
+ registerButton.setEnabled(false);
+ return;
+ }
+
+ String validationMessage = authController.getEmailValidationMessage(email);
+
+ if (validationMessage.equals("邮箱格式正确")) {
+ resultLabel.setText("✓ 邮箱格式正确");
+ resultLabel.setForeground(new Color(0, 150, 0)); // 绿色
+ registerButton.setEnabled(true);
+ } else {
+ resultLabel.setText("✗ " + validationMessage);
+ resultLabel.setForeground(Color.RED);
+ registerButton.setEnabled(false);
+ }
+ } catch (Exception e) {
+ resultLabel.setText("✗ 邮箱验证服务暂时不可用");
+ resultLabel.setForeground(Color.RED);
+ registerButton.setEnabled(false);
+ }
+ }
+
+ private class RegisterAction implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (EmailService.isNetworkAvailable()) {
+ String email = emailField.getText().trim();
+ if (email.isEmpty()) {
+ resultLabel.setText("请输入邮箱地址");
+ resultLabel.setForeground(Color.RED);
+ return;
+ }
+ String validationMessage = authController.getEmailValidationMessage(email); // 再次验证邮箱格式
+ if (!validationMessage.equals("邮箱格式正确")) {
+ resultLabel.setText("✗ " + validationMessage);
+ resultLabel.setForeground(Color.RED);
+ return;
+ }
+ String result = authController.register(email);
+ resultLabel.setText(result);
+ if (result.contains("发送")) {
+ resultLabel.setForeground(Color.BLUE);
+ currentEmail = email; // 保存当前邮箱
+ remainingTime = 120; // 开始倒计时
+ registerButton.setEnabled(false);
+ codeField.setEnabled(true); // 启用验证码输入框
+ submitButton.setEnabled(true); // 启用注册按钮
+ updateRegisterButtonText();
+ countdownTimer.start();
+ } else {
+ resultLabel.setForeground(Color.RED);
+ }
+ } else {
+ showDialog();
+ }
+ }
+ }
+
+ private class SubmitAction implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String code = codeField.getText().trim();
+
+ if (code.isEmpty()) {
+ resultLabel.setText("请输入验证码");
+ resultLabel.setForeground(Color.RED);
+ return;
+ }
+
+ if (currentEmail == null) {
+ resultLabel.setText("请先获取验证码");
+ resultLabel.setForeground(Color.RED);
+ return;
+ }
+
+ // 使用AuthController验证验证码
+ if (authController.isCodeRegistered(currentEmail, code)) {
+ countdownTimer.stop();
+ resultLabel.setText("验证码正确,正在跳转...");
+ resultLabel.setForeground(new Color(0, 150, 0));
+
+ // 延迟跳转到密码设置界面
+ Timer openTimer =
+ new Timer(
+ 1000,
+ evt -> {
+ openPasswordSetupFrame(currentEmail, code);
+ });
+ openTimer.setRepeats(false);
+ openTimer.start();
+ } else {
+ resultLabel.setText("验证码错误或已过期,请重新输入");
+ resultLabel.setForeground(Color.RED);
+ }
+ }
+ }
+
+ private class CountdownAction implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ remainingTime--;
+ updateRegisterButtonText();
+
+ if (remainingTime <= 0) {
+ countdownTimer.stop();
+ registerButton.setEnabled(true);
+ registerButton.setText("获取注册码");
+ codeField.setEnabled(false);
+ submitButton.setEnabled(false);
+ resultLabel.setText("验证码已过期,请重新获取");
+ resultLabel.setForeground(Color.RED);
+ }
+ }
+ }
+
+ private void updateRegisterButtonText() {
+ registerButton.setText(String.format("重新发送(%ds)", remainingTime));
+ }
+
+ private void backToLogin() {
+ if (countdownTimer != null && countdownTimer.isRunning()) {
+ countdownTimer.stop();
+ }
+ LoginFrame loginFrame = new LoginFrame();
+ loginFrame.setVisible(true);
+ this.dispose();
+ }
+
+ private void openPasswordSetupFrame(String email, String code) {
+ try {
+ PasswordSetupFrame passwordFrame = new PasswordSetupFrame(email, code, authController);
+ passwordFrame.setVisible(true);
+ this.dispose();
+ } catch (Exception e) {
+ System.out.println("打开密码设置界面时发生异常: " + e.getMessage());
+ JOptionPane.showMessageDialog(this, "打开密码设置界面失败,请重试", "错误", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private void showDialog() {
+ JOptionPane.showMessageDialog(this, "网络连接失败,请稍后再试", "错误", JOptionPane.ERROR_MESSAGE);
+ }
+}
diff --git a/src/com/mathlearning/view/ScoreFrame.java b/src/com/mathlearning/view/ScoreFrame.java
new file mode 100644
index 0000000..9e93212
--- /dev/null
+++ b/src/com/mathlearning/view/ScoreFrame.java
@@ -0,0 +1,111 @@
+package com.mathlearning.view;
+
+import com.mathlearning.controller.QuestionController;
+import com.mathlearning.model.Question;
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+public class ScoreFrame extends JFrame {
+ private QuestionController questionController;
+ private int[] userSelections;
+ private List allQuestions;
+ private LevelSelectionFrame parentFrame;
+
+ public ScoreFrame(
+ QuestionController questionController,
+ int[] userSelections,
+ List allQuestions,
+ LevelSelectionFrame parent) {
+ this.parentFrame = parent;
+ this.questionController = questionController;
+ this.userSelections = userSelections;
+ this.allQuestions = allQuestions;
+ initializeUI();
+ }
+
+ private void initializeUI() {
+ setTitle("答题结果");
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ setSize(500, 400);
+ setLocationRelativeTo(null);
+ setResizable(false);
+
+ JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+
+ // Score summary
+ int score = questionController.getScore();
+ int total = questionController.getTotalQuestions();
+ double percentage = questionController.getPercentage();
+
+ JLabel scoreLabel =
+ new JLabel(String.format("得分: %d/%d (%.1f%%)", score, total, percentage), JLabel.CENTER);
+ scoreLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 24));
+
+ Color color;
+ if (percentage >= 80) color = Color.GREEN;
+ else if (percentage >= 60) color = Color.ORANGE;
+ else color = Color.RED;
+
+ scoreLabel.setForeground(color);
+ mainPanel.add(scoreLabel, BorderLayout.NORTH);
+
+ // Detailed results - 使用传递过来的题目和用户选择
+ JTextArea detailsArea = new JTextArea();
+ detailsArea.setEditable(false);
+ detailsArea.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
+
+ StringBuilder details = new StringBuilder();
+ details.append("答题详情:\n\n");
+
+ for (int i = 0; i < allQuestions.size(); i++) {
+ Question q = allQuestions.get(i);
+ int userAnswer = userSelections[i];
+ boolean isCorrect = (userAnswer != -1) && q.isCorrect(userAnswer);
+
+ details.append(String.format("第%d题: %s\n", i + 1, q.getQuestionText()));
+ details.append(
+ String.format(
+ "你的答案: %s\n",
+ userAnswer == -1
+ ? "未作答"
+ : (char) ('A' + userAnswer) + ". " + q.getOptions()[userAnswer]));
+ details.append(
+ String.format(
+ "正确答案: %s\n",
+ (char) ('A' + q.getCorrectAnswerIndex())
+ + ". "
+ + q.getOptions()[q.getCorrectAnswerIndex()]));
+ details.append(isCorrect ? "✓ 正确\n" : "✗ 错误\n");
+ details.append("--------------------\n");
+ }
+
+ detailsArea.setText(details.toString());
+ JScrollPane scrollPane = new JScrollPane(detailsArea);
+ mainPanel.add(scrollPane, BorderLayout.CENTER);
+
+ // Buttons
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ JButton restartButton = new JButton("重新开始");
+ JButton exitButton = new JButton("退出");
+
+ restartButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+ exitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+
+ buttonPanel.add(restartButton);
+ buttonPanel.add(exitButton);
+
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+
+ restartButton.addActionListener(e -> restartToLevelSelection());
+ exitButton.addActionListener(e -> System.exit(0));
+
+ add(mainPanel);
+ }
+
+ private void restartToLevelSelection() {
+ parentFrame.setVisible(true);
+ this.dispose();
+ }
+}