Human Benchmark式数值记忆测试程序数字随机化问题求助
数值记忆测试程序问题修复方案
核心问题定位
你的程序存在两个关键问题:
- 数据残留堆叠:每次新测试时,
number列表和string缓冲区未清空,导致旧数字持续累加,最终显示的是所有历史数字的堆叠结果 - 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
相关产品推荐
相关产品推荐

