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

Java Swing井字棋选X时棋盘填满程序冻结问题求助

问题分析与修复方案

核心问题

当选择扮演X(先手)时,玩家走完最后一步填满棋盘后,代码仍会进入电脑回合的逻辑。此时棋盘已无空按钮,电脑的while(!src.getText().equals(""))循环会无限执行——因为随机选中的按钮始终非空,循环无法退出,直接阻塞了Swing的事件调度线程(EDT),导致程序冻结。

而选择扮演O(后手)时,最后一步由电脑执行,走完后会触发胜负判断,不会再进入额外的循环,因此无问题。

修复步骤

  1. 添加回合前的判断逻辑:在电脑执行回合前,先检查是否已分出胜负(hasWinner为true)或棋盘已无空位,满足任一条件则跳过电脑回合。
  2. 调整玩家回合后的流程:玩家走完一步后,仅在未分胜负的情况下切换回合,避免触发不必要的电脑回合。
  3. 优化胜负判断方法:移除winCheck中重置hasWinner为false的分支,避免覆盖平局判断设置的hasWinner值;提取判断空位的逻辑为独立方法,减少代码冗余。

修改后的代码片段

1. 添加判断空位的辅助方法

private boolean hasEmptySpot(){
    for (JButton button : buttons) {
        if (button.getText().equals("")) {
            return true;
        }
    }
    return false;
}

2. 修改actionPerformed方法

public void actionPerformed(ActionEvent e) {
    //Checking which button is pressed to assign player to X or O.
    if(e.getSource() == X){
        player1 = "X";
        computer = "O";
        playerTurn = true;
        board.setVisible(true);
    } else if(e.getSource() == O){
        player1 = "O";
        computer = "X";
        playerTurn = false;
        board.setVisible(true);
    }
    //After player chooses which to play as, this will check to see which value should go in the button based on whose turn it is.
    else{
        JButton src = (JButton) e.getSource();
        if(playerTurn) {
            src.setText(player1);
            winCheck(player1);
            tieCheck();
            // 仅未分胜负时切换回合
            if(!hasWinner){
                playerTurn = !playerTurn;
            }
        }
        else{
            src.setText(computer);
            winCheck(computer);
            tieCheck();
            if(!hasWinner){
                playerTurn = !playerTurn;
            }
        }
    }
    //Gets rid of the input panel once the player chooses X or O.
    if(!player1.equals("")){
        inputPanel.setVisible(false);
    }
    //Computer turn logic - 添加前置判断
    if(!playerTurn && !hasWinner && hasEmptySpot()){
        int choice = rand.nextInt(9);
        JButton src = buttons[choice];
        while(!src.getText().equals("")){
            choice = rand.nextInt(9);
            src = buttons[choice];
        }
        src.setText(computer);
        winCheck(computer);
        tieCheck();
        if(!hasWinner){
            playerTurn = !playerTurn;
        }
    }
    //After there is a winner, either create a new game window or close the window and end the program
    if(hasWinner){
        if(e.getSource() == X){
            new Moser_Problem1();
            frame.dispose();
        } else if(e.getSource() == O){
            frame.dispose();
        }
    }
}

3. 修改winCheck方法

public void winCheck(String player) {
    //All possible winning combos for tic-tac-toe board.
    if(buttons[0].getText().equals(player) && buttons[1].getText().equals(player) && buttons[2].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[3].getText().equals(player) && buttons[4].getText().equals(player) && buttons[5].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[6].getText().equals(player) && buttons[7].getText().equals(player) && buttons[8].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[0].getText().equals(player) && buttons[3].getText().equals(player) && buttons[6].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[1].getText().equals(player) && buttons[4].getText().equals(player) && buttons[7].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[2].getText().equals(player) && buttons[5].getText().equals(player) && buttons[8].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[0].getText().equals(player) && buttons[4].getText().equals(player) && buttons[8].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    } else if(buttons[6].getText().equals(player) && buttons[4].getText().equals(player) && buttons[2].getText().equals(player)){
        xOro.setText(player + " wins!\nDo you want to play again?");
        player1 = "";
        inputPanel.setVisible(true);
        X.setText("Yes");
        O.setText("No");
        hasWinner = true;
    }
    // 移除else分支,不再重置hasWinner为false
}

4. 修改tieCheck方法

public void tieCheck(){
    if(!hasEmptySpot()){
        xOro.setText("It's a tie!\nWould you like to play again?");
        X.setText("Yes");
        O.setText("No");
        player1 = "";
        inputPanel.setVisible(true);
        hasWinner = true;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:40:20