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

Java Swing:如何让while循环等待JButton按下?猜数字游戏问题

问题分析与解决方案

你的代码核心问题在于Swing是事件驱动模型,main线程在窗口显示后会立刻执行后续的while循环——这时候用户还没点击按钮,guess保持初始值-1,循环会快速耗尽所有猜测次数,直接跳到失败提示逻辑。

正确的做法是把游戏逻辑绑定到按钮的点击事件上,每次用户点击按钮才处理一次猜测,而非用while循环在main线程里“死等”。

下面是修改后的完整代码,附带关键改动说明:

import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;

public class NumberGame {
    // 将静态变量改为实例变量,避免多线程同步问题
    private int guess = -1;
    private int presses = 0;
    private int targetNum;
    private int remainingGuesses;
    private JLabel tipLabel;
    private JTextField inputField;

    public NumberGame() {
        JFrame window = new JFrame("猜数字游戏");
        window.setLayout(new BorderLayout());
        
        JPanel topPanel = new JPanel();
        JPanel bottomPanel = new JPanel();
        JPanel centerPanel = new JPanel();
        
        JLabel titleLabel = new JLabel("请输入1到77之间的数字");
        topPanel.add(titleLabel);
        
        inputField = new JTextField(10);
        inputField.setPreferredSize(new Dimension(80,20));
        topPanel.add(inputField);
        
        JButton guessBtn = new JButton("提交猜测");
        guessBtn.setPreferredSize(new Dimension(100,40));
        centerPanel.add(guessBtn);
        
        tipLabel = new JLabel("请输入你的猜测");
        bottomPanel.setLayout(new BorderLayout());
        bottomPanel.add(tipLabel, BorderLayout.CENTER);
        
        // 初始化游戏参数
        targetNum = (int)(77*Math.random())+1;
        remainingGuesses = 5;
        
        // 按钮点击事件处理猜数逻辑
        guessBtn.addActionListener(e -> {
            // 游戏已结束时不再响应点击
            if (remainingGuesses <= 0) {
                return;
            }
            
            String input = inputField.getText().trim();
            // 空输入直接提示
            if (input.isEmpty()) {
                tipLabel.setText("请输入1-77之间的数字!");
                return;
            }
            
            try {
                guess = Integer.parseInt(input);
                // 验证输入范围
                if (guess < 1 || guess >77) {
                    tipLabel.setText("数字必须在1到77之间!");
                    inputField.setText("");
                    return;
                }
                
                presses++;
                remainingGuesses--;
                
                // 判断猜数结果
                if (guess == targetNum) {
                    tipLabel.setText("恭喜你赢了!还剩 " + remainingGuesses + " 次机会。");
                    remainingGuesses = 0; // 标记游戏结束
                } else if (guess > targetNum) {
                    tipLabel.setText("太大了,再来一次。剩余次数:" + remainingGuesses);
                } else {
                    tipLabel.setText("太小了,再来一次。剩余次数:" + remainingGuesses);
                }
                
                // 检查是否耗尽所有机会
                if (remainingGuesses == 0 && guess != targetNum) {
                    tipLabel.setText("你输了!正确数字是 " + targetNum + "。");
                }
                
                inputField.setText("");
            } catch (NumberFormatException ex) {
                tipLabel.setText("请输入有效的数字!");
                inputField.setText("");
            }
        });
        
        window.add(topPanel, BorderLayout.NORTH);
        window.add(bottomPanel, BorderLayout.SOUTH);
        window.add(centerPanel, BorderLayout.CENTER);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setSize(300,200);
        window.setVisible(true);
    }

    public static void main(String[] args) {
        // 确保Swing组件在事件调度线程中创建,符合线程规范
        SwingUtilities.invokeLater(NumberGame::new);
    }
}

关键改动说明

  1. 事件驱动逻辑:把所有猜数判断放到按钮点击事件中,用户每点击一次才处理一次猜测,完全贴合Swing的事件驱动模型。
  2. 变量作用域优化:将游戏状态变量(剩余次数、目标数字等)改为实例变量,避免静态变量在多线程中的同步问题。
  3. 输入合法性验证:增加空输入、非数字输入、范围外输入的判断,防止程序崩溃或逻辑异常。
  4. 线程安全规范:用SwingUtilities.invokeLater启动UI,确保Swing组件在事件调度线程中初始化,符合Swing的线程要求。

内容的提问来源于stack exchange,提问作者Michael Carpiano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:12:08