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

Java Swing骰子游戏:JButton互斥启用及重启功能修复问询

解决双人掷骰子游戏的按钮互斥与全局重启问题

嘿,我仔细看了你的代码,发现你遇到的两个问题本质上都是组件实例引用错误和组件间通信缺失导致的。咱们一步步来修复它们:

问题1:Roll按钮无法互斥禁用

现在你的代码里,Player.rolldisable()方法每次都会新建一个SixNumbersPanel2实例,这根本不是操作另一个玩家的真实面板!自然没法禁用对方的按钮。而且每个玩家面板都不知道对手的存在,所以首先得让两个面板互相持有引用。

修复步骤:

  1. 在SixNumbersPanel2中添加对手面板的引用和setter方法:
private SixNumbersPanel2 opponentPanel; // 新增:对手面板引用

// 新增:设置对手面板的方法
public void setOpponentPanel(SixNumbersPanel2 opponent) {
    this.opponentPanel = opponent;
}
  1. 在DisplaySixNumbersPanel的main方法中,创建完两个玩家面板后,互相绑定对手引用:
public static void main(String[] args) {
    JFrame w1 = new JFrame("Six Numbers Game");
    w1.setLayout(new GridLayout(1,2));
    SixNumbersPanel2 player1 = new SixNumbersPanel2();
    SixNumbersPanel2 player2 = new SixNumbersPanel2();
    
    // 新增:互相设置对手面板
    player1.setOpponentPanel(player2);
    player2.setOpponentPanel(player1);
    
    w1.add(player1);
    w1.add(player2);
    w1.setSize(540, 350);
    w1.setVisible(true);
    w1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
  1. 修改SixNumbersPanel2的actionPerformed方法,点击Roll按钮时直接禁用对手的按钮,同时完成游戏时要启用对手的按钮:
public void actionPerformed(ActionEvent event) {
    if(event.getSource() == roll) {
        // 替换原来的player2.rolldisable(),直接操作对手面板
        opponentPanel.rolldisable();
        this.rollenable(); // 确保自己的按钮是启用的(当前玩家正在操作)
        
        key=dice.Roll();
        count++;
        String toScreen= "Number of rolls: "+count;
        display.setText(toScreen);
        text1.setText(""+key);
        check = player1.Check(list,key);
        
        if(check < 0) {
            count1++;
            for(int i=1;i<7;i++) {
                if(key == i) {
                    list[i] = key;
                    checkflag[i]=true;
                    fields[i].setText(""+key);
                    
                    // 检查是否集齐所有数字
                    flag = true;
                    for(int a=1; a<7; a++) {
                        if(checkflag[a]==false) {
                            flag=false;
                            break; // 优化:只要有一个未集齐,就不用继续检查
                        }
                    }
                }
            }
            
            if(flag == true) {
                display.setText("Congratulation, you have \ntaken "+count+" rolls to get one of \neach number between 1 and 6");
                this.rolldisable(); // 禁用自己的按钮
                opponentPanel.rollenable(); // 启用对手的按钮(如果需要切换回合)
                restartButton.setVisible(true);
            }
        }
    }
    
    if(event.getSource() == restartButton) {
        restart();
    }
}
  1. 删除Player类中无用的rolldisable()方法,因为按钮控制应该由面板自己处理,不需要通过Player类中转。

问题2:Restart按钮仅对单个玩家生效

现在的restart()方法只重置了当前面板的状态,没有通知对手面板也重置。我们需要在重启时同时触发对手的重启操作。

修复步骤:

修改SixNumbersPanel2的restart()方法,添加对手面板的重启调用:

public void restart() {
    display.setText("");
    text1.setText("");
    for(int i=1; i<7; i++) {
        fields[i].setText("");
    }
    count=0;
    count1=0;
    Arrays.fill(checkflag,false);
    Arrays.fill(list,0);
    flag = false;
    restartButton.setVisible(false);
    rollenable();
    
    // 新增:同时重启对手面板
    if(opponentPanel != null) {
        opponentPanel.restart();
        // 可选:重启后默认让当前玩家先操作,禁用对手按钮
        opponentPanel.rolldisable();
    }
}

额外优化建议

  • 你的checkflag数组长度是7(索引0-6),但只用了1-6,其实可以改成长度6,索引0-5对应数字1-6,更合理。
  • 在检查是否集齐所有数字的循环里,一旦发现未集齐的数字就break,能提升效率(我已经在上面的代码里加了这个优化)。
  • 可以给两个玩家面板加上不同的标题,比如Player 1和Player 2,让界面更清晰。

修改完这些后,两个玩家的Roll按钮就能互斥禁用,Restart按钮也能全局重启游戏了!

内容的提问来源于stack exchange,提问作者Terrence Chu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:42:36