【问题标题】:Keeping track of JButtons generated in a for loop跟踪在 for 循环中生成的 JButton
【发布时间】:2015-07-11 21:47:20
【问题描述】:

我正在开发一个 Java tic-tac-toe 游戏,但我无法跟踪我的 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);
}

我想检查我的按钮文本是否匹配(在行/列/对角线中),如果匹配,则显示您获胜。

这是我所有的代码:

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?

【问题讨论】:

  • 你的问题没有问题。
  • 您需要澄清“跟踪”它们的含义。您的意思是添加单独的侦听器吗?
  • “保持跟踪”我的意思是如果 button1 text == button2 text == button3 text 那么 win=true。因为我没有为每个按钮设置不同的名称,所以我不能这样做。
  • 你只想检查这三个按钮吗

标签: java swing for-loop jbutton tic-tac-toe


【解决方案1】:

井字游戏的获胜条件是:

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. 如果标记位于角落,则为一条对角线;如果标记位于中心,则为两条对角线。

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

【讨论】:

    【解决方案2】:

    首先我将回答您的问题,但根据您的代码(或缺少代码)来判断,然后我将解决一些我认为作为使用图形用户界面 (GUI) 和 Java Swing 的 Java 程序员应该注意的事情.


    第 1 部分:答案

    我能想到两种方法来解决这个问题。

    以下代码使用二维数组来表示 JButton 的 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;
            }
     }
    

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

    但是,井字游戏中也存在平局“猫的游戏”,我们如何解决这个问题?好吧,如果没有获胜的案例并且棋盘上满是棋子,那么我们就陷入了僵局。

    方法 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”类,您必须自己编写,因为 Java 不附带这样的类。

    作为 Java Swing GUI 程序员,您应该了解以下几点。

    A. Java 摇摆

    您似乎对 Java Swing 没有深入了解,所以这里是 an introductory tutorial 让您开始。

    B.布局管理器

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

    C.模型-视图-控制器 (MVC)

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

    D.我的实现

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


    干杯,编码愉快!

    【讨论】:

      猜你喜欢
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 1970-01-01
      • 2020-07-09
      • 2020-10-02
      • 2019-12-07
      • 2015-09-10
      相关资源
      最近更新 更多