跟踪在 for 循环中生成的 JButton

Keeping track of JButtons generated in a for loop

我正在开发 Java 井字游戏,但我无法跟踪我的 JButton,因为我使用 for 循环创建 9 个按钮:

for(int i=0;i<button.length;i++){           
    button[i] = new JButton();
    button[i].setText(Integer.toString(i+1));
    frame.add(button[i]);
    button[i].addActionListener(this);
}

我想检查我的按钮文本是否匹配(rows/columns/diagonal),如果匹配,显示您赢了。

这是我的全部代码:

public class TicTacToe extends Board implements ActionListener{
    JButton button[] = new JButton[9];
    boolean win = false;
    int count = 0;
    String letter = "";

    public TicTacToe(){
        //create + add JButtons to JFrame
        for(int i=0;i<button.length;i++){
            button[i] = new JButton();
            button[i].setText(Integer.toString(i+1));
            frame.add(button[i]);
            button[i].addActionListener(this);
        }
    }   

    public void actionPerformed(ActionEvent e) {
        for(int i=0;i<button.length;i++){
            if(i%2 == 0){
                letter = "X";
            }else{
                letter = "O";
            }

            if(e.getSource() == button[i]){
                button[i].setText(letter);
                button[i].setEnabled(false);
                count = i+1;
            }

            //check win
            if(){             //<---------------NEED HELP HERE. THANK YOU
                win = true;
                JOptionPane.showMessageDialog(null, "YOU WIN");
            }
        }
    }
}

如何跟踪动态创建的 JButton?

井字游戏的获胜条件是:

X - -    - X -    - - X
X - - or - X - or - - X
X - -    - X -    - - X

private boolean colWinner() {
  for (int i = 0; i < 3; i++) {
    String mark = button[i].getText();
    if (mark.equals(button[i+3].getText()) &&
        mark.equals(button[i+6].getText()) {
      return true;
    }
  }
  return false;
}

X X X    - - -    - - -
- - - or X X X or - - -
- - -    - - -    X X X

private boolean rowWinner() {
  for (int i = 0; i < 3; i++) {
    String mark = button[3*i].getText();
    if (mark.equals(button[3*i+1].getText()) &&
        mark.equals(button[3*i+2].getText()) {
      return true;
    }
  }
  return false;
}

X - -    - - X
- X - or - X -
- - X    X - -

private boolean diagWinner() {
  String mark = button[4].getText();
  return 
    (mark.equals(button[0].getText()) && mark.equals(button[8].getText()) ||
    (mark.equals(button[2].getText()) && mark.equals(button[6].getText());
}

这种幼稚的方法会检查所有可能的获胜条件,如果您要在每回合后检查获胜情况,则实际上没有必要这样做。您只需要检查以下条件:

  1. 新标记所在的行
  2. 制作新标记的栏目
  3. 如果标记在角上则一条对角线,如果标记在中心则两条对角线。

我会留给你解决这个问题。

首先我会回答你的问题,但根据你的代码(或缺乏代码)判断,我会解决一些我认为你作为使用图形用户界面的 Java 程序员应该知道的事情(GUI)和 Java Swing。


第 1 部分:答案

两种方法我可以想到解决这个问题。

下面的代码使用二维数组来表示JButtons 的3x3 板(请注意为什么不使用二维数组,实际上很困惑为什么不使用)。此外,它假定所有 JButton 的文本最初都设置为“.”。因为这比检查文本是否是 9 个不同字符串数字之一要容易得多。

方法 A:静态案例

由于棋盘很小,因此可以简单地检查玩家将赢得井字游戏的每种情况,并验证其中一种情况是否为真。下图说明了 八种情况 导致玩家获胜的结果。

请注意,"O" 可以很容易地替换下面的 "X",重要的是每个都属于同一个玩家。此外,任何“。”标记只是占位符,因为这实际上代表黑板上的 "X," "O," 还是 "null" 并不重要。

// Case 1

// if each location across the top row is not empty
if (board[0][0].getText() != "." && board[0][1].getText() != "." && board[0][2].getText() != ".") {

        // if each location has the same text
        if (board[0][0].getText() == board[0][1].getText() && 
            board[0][0].getText() == board[0][2].getText()) {

            // if the player is X then X is winner, else player is O and O is winner
            if (board[0][0].player() == Player.X)
                return Status.X_WINNER;
            else if (board[0][0].player() == Player.O)
                return Status.O_WINNER;
        }
 }

这可以重复七次以实现我们的目标。然而,这是很多重复代码,聪明的程序员会尽可能避免这种情况。

但是,在井字游戏中也有平局"cat's game"的情况,我们该如何解决这个?好吧,如果没有获胜案例 AND 棋盘上满是棋子,那么我们就会陷入僵局。

方法 B:动态检查

我承认,这个方法是一个庞然大物,我相信它可以使用一些智能重构,但它很实用,可以动态解决问题。有许多条件可以尝试通过仅在绝对必要时继续来提高算法效率。

请注意,我检查了棋子周围的邻居,这对于正确检查对角线是否赢得比赛至关重要。

// track if game won
boolean won = false;

        // constant for board width and height
        int BOARD_SIZE = 3;

        // track pieces on board
        int numPieces = 0;

        // track who won
        String winner = "";

        // loop through the board first time
        for (int row1 = 0; row1 < board.length; row1++) {
            for (int col1 = 0; col1 < board.length; col1++) {

                // if piece exists here
                if (board[row1][col1].getText() != ".") {

                    // increment number of pieces on board
                    numPieces++;

                    // check pieces around first piece
                    for (int row2 = row1 - 1; row2 <= row1 + 1; row2++) {
                        for (int col2 = col1 - 1; col2 <= col1 + 1; col2++) {

                            // ensure within bounds of board
                            if ((row2 >= 0 && row2 < BOARD_SIZE) && (col2 >= 0 && col2 < BOARD_SIZE)) {

                                // ignore checking with first piece (itself)
                                if (board[row2][col2] != board[row1][col1]) {

                                    // if second piece equal to first piece
                                    if (board[row2][col2].getText() == board[row1][col1].getText()) {

                                        // check pieces around second piece
                                        for (int row3 = row2 - 1; row3 <= row2 + 1; row3++) {
                                            for (int col3 = col2 - 1; col3 <= col2 + 1; col3++) {

                                                // ensure within bounds of board
                                                if ((row3 >= 0 && row3 < BOARD_SIZE) && (col3 >= 0 && col3 < BOARD_SIZE)) {

                                                    // ignore checking pieces we already have
                                                    if (board[row3][col3] != board[row2][col2] && board[row3][col3] != board[row1][col1]) {

                                                        // if third piece equal to first piece (and so also equal to second)
                                                        if (board[row3][col3].getText() == board[row1][col1].getText()) {

                                                            // if three pieces are all on same row
                                                            if (row1 == row2 && row1 == row3) {
                                                                if (board[row1][col1].getText() == "X")
                                                                    winner = "X";
                                                                else
                                                                    winner = "O";
                                                                won = true;
                                                                break;
                                                            }

                                                            // else if three pieces are all on same column
                                                            else if (col1 == col2 && col1 == col3) {
                                                                if (board[row1][col1].getText() == "X")
                                                                    winner = "X";
                                                                else
                                                                    winner = "O";
                                                                won = true;
                                                                break;
                                                            }

                                                            // else if three pieces are all on different rows and columns (winning diagonal)
                                                            else if ((row1 != row2 && row1 != row3 && row2 != row3) && (col1 != col2 && col1 != col3 && col2 != col3)) {
                                                                if (board[row1][col1].getText() == "X")
                                                                    winner = "X";
                                                                else
                                                                    winner = "O";
                                                                won = true;
                                                                break;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if (winner == "X") {
            JOptionPane.showMessageDialog(null, "X wins");
        }
        else if (winner == "O") {
            JOptionPane.showMessageDialog(null, "O wins");
        }

        // if board is full and hasn't resulted in any winners
        if (!won && numPieces == BOARD_SIZE * BOARD_SIZE)
            JOptionPane.showMessageDialog(null, "Cats game");

当然,代码行数越少并不一定能保证性能越好,我们又一次很幸运,这么小的板子。在大板上像这样循环多次(即蛮力方法)会造成灾难性的 运行 次,因此这是另一个需要考虑的设计选择。


第 2 部分:更进一步

我不认为这真的是你所有的代码,因为你提供的代码无法执行without a main method

此外,如果您要扩展 "Board" class,您必须自己编写,因为 Java 没有这样的 class。

作为 Java Swing GUI 程序员,您应该注意以下事项。

一个。 Java 秋千

您似乎对 Java Swing 没有很好的掌握,所以这里是 an introductory tutorial 开始。

乙。布局管理器

在尝试配置 GUI 布局时,布局管理器可以是您的朋友,也可以是您的敌人。 a good resource 供您探索。

摄氏度。模型-视图-控制器 (MVC)

解耦依赖关系是未来管理大型代码库的关键。 MVC 是一种流行的软件架构模式,有助于减少处理用户界面时的依赖性。 Check this out.

D.我的实现

你启发了我自己的工作Java 井字游戏的 Swing 实现。 Here it is!


干杯,编码愉快!