Java Swing井字棋选X时棋盘填满程序冻结问题求助
问题分析与修复方案
核心问题
当选择扮演X(先手)时,玩家走完最后一步填满棋盘后,代码仍会进入电脑回合的逻辑。此时棋盘已无空按钮,电脑的while(!src.getText().equals(""))循环会无限执行——因为随机选中的按钮始终非空,循环无法退出,直接阻塞了Swing的事件调度线程(EDT),导致程序冻结。
而选择扮演O(后手)时,最后一步由电脑执行,走完后会触发胜负判断,不会再进入额外的循环,因此无问题。
修复步骤
- 添加回合前的判断逻辑:在电脑执行回合前,先检查是否已分出胜负(
hasWinner为true)或棋盘已无空位,满足任一条件则跳过电脑回合。 - 调整玩家回合后的流程:玩家走完一步后,仅在未分胜负的情况下切换回合,避免触发不必要的电脑回合。
- 优化胜负判断方法:移除
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
相关产品推荐
相关产品推荐

