You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Human Benchmark式数值记忆测试程序数字随机化问题求助

数值记忆测试程序问题修复方案

核心问题定位

你的程序存在两个关键问题:

  1. 数据残留堆叠:每次新测试时,number列表和string缓冲区未清空,导致旧数字持续累加,最终显示的是所有历史数字的堆叠结果
  2. Swing线程冲突:直接在构造方法中使用Thread.sleep会阻塞Swing事件派发线程(EDT),导致界面卡顿、逻辑异常

分步修复代码

1. 重置数据容器

每次测试循环开始前,清空存储数字的容器,避免旧数据残留:

wait = true;
// 新增:清空上次测试的数字数据
number.clear();
string.setLength(0);
for (int i = 0; i < length; i++) {
    int num = Math.abs(random.nextInt() % 9);
    number.add(num);
    string.append(num);
}

2. 修复线程阻塞问题

Swing是单线程模型,不能在EDT中调用Thread.sleep。改用单独线程处理测试逻辑,所有界面更新通过SwingUtilities.invokeLater在EDT中执行:

// 构造方法中移除原有的循环逻辑,替换为单独线程
new Thread(() -> {
    while (!gameEnded) {
        wait = true;
        number.clear();
        string.setLength(0);
        
        // 生成随机数字序列
        for (int i = 0; i < length; i++) {
            int num = Math.abs(random.nextInt() % 9);
            number.add(num);
            string.append(num);
        }

        // 更新显示记忆数字(必须在EDT中执行)
        SwingUtilities.invokeLater(() -> {
            title.setText("Remember the number:");
            input.setText(string.toString());
            input.setEditable(false);
            frame.revalidate();
            frame.repaint();
        });

        // 等待记忆时间,这里的sleep不会阻塞EDT
        try {
            Thread.sleep(length * 1500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        // 切换到输入模式
        SwingUtilities.invokeLater(() -> {
            title.setText("What was the number?");
            input.setText("");
            input.setEditable(true);
            frame.revalidate();
            frame.repaint();
        });

        // 等待用户操作,添加sleep降低CPU占用
        while (wait) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }
}).start();

3. 修正测试长度递增逻辑

在next按钮的事件处理中,增加长度递增逻辑,否则每次测试始终是1位数字:

if (e.getActionCommand().equals("next")) {
    wait = false;
    length++; // 新增:测试长度+1,提升难度
}

4. 优化组件初始化逻辑

避免在循环中反复创建和移除组件,一次性初始化所有界面元素,后续仅更新内容:

// 构造方法开头一次性初始化界面
public Numerical() {
    frame.setLayout(null); 
    frame.setSize(500, 300); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    top.setLayout(new GridLayout(2, 1));
    top.setBounds(0, 0, 500, 200);
    title = new JLabel("Remember the number:");
    input = new JTextField();
    input.setEditable(false);
    top.add(title);
    top.add(input);
    frame.add(top);

    bottom.setLayout(new GridLayout(1, 3));
    bottom.setBounds(0, 210, 500, 40);
    output = new JLabel();
    button1 = new JButton("Submit");
    button2 = new JButton("Back");
    button1.addActionListener(this);
    button2.addActionListener(this);
    button2.setVisible(false);
    bottom.add(output);
    bottom.add(button1);
    bottom.add(button2);
    frame.add(bottom);

    frame.setVisible(true);
}

完整修复后代码

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Numerical implements ActionListener {
    Random random = new Random(); 
    ArrayList<Integer> number = new ArrayList<>();
    StringBuffer string = new StringBuffer();
    int length = 1;
    boolean gameEnded = false, wait = true;

    JFrame frame = new JFrame("Numerical Memory");
    JPanel top = new JPanel();
    JPanel bottom = new JPanel();
    JLabel title;
    JLabel output;
    JTextField input;
    JButton button1, button2;

    public Numerical() {
        // 初始化界面组件
        frame.setLayout(null); 
        frame.setSize(500, 300); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        top.setLayout(new GridLayout(2, 1));
        top.setBounds(0, 0, 500, 200);
        title = new JLabel("Remember the number:");
        input = new JTextField();
        input.setEditable(false);
        top.add(title);
        top.add(input);
        frame.add(top);

        bottom.setLayout(new GridLayout(1, 3));
        bottom.setBounds(0, 210, 500, 40);
        output = new JLabel();
        button1 = new JButton("Submit");
        button2 = new JButton("Back");
        button1.addActionListener(this);
        button2.addActionListener(this);
        button2.setVisible(false);
        bottom.add(output);
        bottom.add(button1);
        bottom.add(button2);
        frame.add(bottom);

        frame.setVisible(true);

        // 启动测试逻辑线程
        new Thread(() -> {
            while (!gameEnded) {
                wait = true;
                number.clear();
                string.setLength(0);

                // 生成随机数字序列
                for (int i = 0; i < length; i++) {
                    int num = Math.abs(random.nextInt() % 9);
                    number.add(num);
                    string.append(num);
                }

                // 更新记忆界面
                SwingUtilities.invokeLater(() -> {
                    title.setText("Remember the number:");
                    input.setText(string.toString());
                    input.setEditable(false);
                    output.setVisible(false);
                    button2.setVisible(false);
                    button1.setText("Submit");
                    button1.setActionCommand("submit");
                    frame.revalidate();
                    frame.repaint();
                });

                // 等待记忆时间
                try {
                    Thread.sleep(length * 1500);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                // 切换到输入界面
                SwingUtilities.invokeLater(() -> {
                    title.setText("What was the number?");
                    input.setText("");
                    input.setEditable(true);
                    frame.revalidate();
                    frame.repaint();
                });

                // 等待用户操作
                while (wait) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }).start();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("submit")) {
            try {
                int x = Integer.parseInt(input.getText());
                int y = Integer.parseInt(string.toString());
                if (x == y) {
                    output.setText("CORRECT!");
                    button1.setText("Next");
                    button1.setActionCommand("next");
                } else {
                    button2.setVisible(true);
                    output.setText("INCORRECT!");
                    button1.setText("Retry");
                    button1.setActionCommand("retry");
                }
                output.setVisible(true);
                frame.revalidate();
                frame.repaint();
            } catch (NumberFormatException ex) {
                output.setText("请输入有效数字!");
                output.setVisible(true);
                frame.revalidate();
                frame.repaint();
            }
        }
        if (e.getActionCommand().equals("next")) {
            wait = false;
            length++;
        }
        if (e.getActionCommand().equals("retry")) {
            wait = false;
        }
        if (e.getSource() == button2) {
            wait = false;
            gameEnded = true;
            frame.dispose();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Numerical::new);
    }
}

关键优化说明

  • 数据容器每次测试前清空,彻底解决数字堆叠问题
  • 测试逻辑放在单独线程执行,避免阻塞Swing EDT,保证界面流畅
  • 所有界面更新操作通过SwingUtilities.invokeLater提交到EDT,符合Swing线程安全规范
  • 修正测试长度递增逻辑,实现难度逐步提升
  • 添加输入异常捕获,提升程序健壮性

内容的提问来源于stack exchange,提问作者Hollow Clouds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:52:59