如何在玩家开始之前在井字游戏中迭代整个方块 (1-9)?

How to iterate the entire square (1-9) in a tic-tac-toe game before player starts?

在井字游戏中,如果 he/she 选择 1-9 中的任何一个,如果 X 玩家将赢得游戏,我想警告 O 玩家。

我的解决办法是在O播放器开始之前迭代1-9。如果 1-9 中的任何一个会导致 X 赢得比赛,通知 O 玩家 he/she 将输掉比赛,并给出 him/her 将导致 him/her 输掉比赛的确切数字。

我的问题是我不知道如何在//Player O's turn(第87行)之前迭代1-9。

如果您有任何建议,那将对我很有帮助。谢谢!

我的源代码如下;非常感谢您的帮助。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class TicTacToe {
    public static void main(String[] args) {
        new InputStreamReader(System.in);
        BufferedReader theKeyboard = new BufferedReader(new InputStreamReader(System.in));

        Board Game = new Board();

        System.out.print("Enter 1 to play with computer;" + "\nEnter 2 to play with other people.\nPlease enter 1-2: ");

        int players = 1;
        String input = "";
        boolean badInput = false;

        do // get the number of players -- only accept 1 or 2
        {
            try {
                input = theKeyboard.readLine();
            } catch (IOException e) {
                System.out.println("input error:" + e);
                System.exit(1);
            }
            if (input.equals("1")) {
                badInput = false;
                players = 1;
            } else if (input.equals("2")) {
                badInput = false;
                players = 2;
            } else
                badInput = true;

            if (badInput)
                System.out.print("Enter a number, 1 or 2: ");
        } while (badInput);

        System.out.println("TicTacToe Game starts." + " Please enter 1-9 to make your choice.");

        int[] move = new int[2];
        char winner;
        int getTurn = 1; // The initialization of turns

        System.out.println(Game); // print the board for first time

        while (true) // loop only breaks when X or O wins, or a cat's game
        {
            // Player X's turn
            if (getTurn % 2 != 0) {
                if (players == 2) {

                    System.out.print("Player X, Enter 1-9 to make choice: ");
                    while (true) {
                        move = getMove();
                        // can't take occupied space
                        if (!Game.elementMarked(move[0], move[1]))
                            break;
                        System.out.println("That space is occupied.");
                    }

                }

                else // Or computer player
                    move = ComputerPlayer.makeMove(Game.copyBoard(), getTurn);

                Game.markFirst(move[0], move[1]); // mark an X on the board

                winner = Game.win(); // Check if win

                if (winner != 'N')
                    break;
                System.out.println(Game);

                getTurn++; // return turn to the other player
            }

            // Player O's turn
            System.out.print("Player O, Enter 1-9 to make choice: ");

            while (true) {
                move = getMove();
                if (!Game.elementMarked(move[0], move[1]))
                    break;
                System.out.println("This square has been chosen." + " Please enter a new square.");
            }

            Game.markSecond(move[0], move[1]);

            winner = Game.win(); // Check if win

            if (winner != 'N')
                break;
            System.out.println(Game);

            getTurn++; // return turn to the other player
        }

        System.out.println(Game);

        if (winner == 'C')
            System.out.println("This is a cat's game.");

        if (winner != 'C')
            System.out.println("The winner is: " + winner);

    }

    // getMove gets the users choice and translates it into rows and columns
    public static int[] getMove() {
        new InputStreamReader(System.in);
        BufferedReader theKeyboard = new BufferedReader(new InputStreamReader(System.in));

        String input = "";
        int[] move = new int[2];
        boolean errorInput = false;
        do {
            try {
                input = theKeyboard.readLine();
            } catch (IOException e) {
                System.out.println("input error:" + e);
                System.exit(1);
            }
            if (input.equals("1")) {
                move[0] = 0;
                move[1] = 0;
                errorInput = false;
            } else if (input.equals("2")) {
                move[0] = 0;
                move[1] = 1;
                errorInput = false;
            } else if (input.equals("3")) {
                move[0] = 0;
                move[1] = 2;
                errorInput = false;
            } else if (input.equals("4")) {
                move[0] = 1;
                move[1] = 0;
                errorInput = false;
            } else if (input.equals("5")) {
                move[0] = 1;
                move[1] = 1;
                errorInput = false;
            } else if (input.equals("6")) {
                move[0] = 1;
                move[1] = 2;
                errorInput = false;
            } else if (input.equals("7")) {
                move[0] = 2;
                move[1] = 0;
                errorInput = false;
            } else if (input.equals("8")) {
                move[0] = 2;
                move[1] = 1;
                errorInput = false;
            } else if (input.equals("9")) {
                move[0] = 2;
                move[1] = 2;
                errorInput = false;
            } else
                errorInput = true;

            if (errorInput)
                System.out.print("Error input. Enter a number within 1-9: ");
        } while (errorInput);

        return move;
    }
}

/**
 * ComputerPlayer is the AI client for computer, user can play with this "smart"
 * computer.
 */

class ComputerPlayer {
    public static int[] makeMove(int board[][], int turn) {
        int square = 5;
        int move[] = new int[2];

        if (turn == 1) // first move is to get 5
        {
            square = 5;
            move = Convert(square);
            return move;
        }

        move = randomMove(board); // make a random move.
        return move;
    }

    public static int[] randomMove(int board[][]) {
        int move[] = new int[2];
        int randomRow;
        int randomCol;

        while (true) {
            randomRow = (int) (Math.random() * 3);
            randomCol = (int) (Math.random() * 3);
            if (board[randomRow][randomCol] == 0)
                break;
        }
        move[0] = randomRow;
        move[1] = randomCol;

        return move;
    }

    // Convert will convert square (1-9) into a row and column
    public static int[] Convert(int square) {
        int move[] = new int[2];

        if (square == 1) {
            move[0] = 0;
            move[1] = 0;
        } else if (square == 2) {
            move[0] = 0;
            move[1] = 1;
        } else if (square == 3) {
            move[0] = 0;
            move[1] = 2;
        } else if (square == 4) {
            move[0] = 1;
            move[1] = 0;
        } else if (square == 5) {
            move[0] = 1;
            move[1] = 1;
        } else if (square == 6) {
            move[0] = 1;
            move[1] = 2;
        } else if (square == 7) {
            move[0] = 2;
            move[1] = 0;
        } else if (square == 8) {
            move[0] = 2;
            move[1] = 1;
        } else if (square == 9) {
            move[0] = 2;
            move[1] = 2;
        }

        return move;
    }
}

/**
 * Board can represents 2D 3*3 array for TicTacToe game. It can check if someone
 * wins or a cat's game. It can check if a square has been chosen. It can also
 * mark an X or O from the player's choice.
 */

class Board {
    private int[][] myBoard = new int[3][3];

    // Create a 3 by 3 array and use for a tic tac toe board.
    public Board() {
        for (int row = 0; row < 3; row++) {
            for (int column = 0; column < 3; column++) {
                myBoard[row][column] = 0;
            }
        }
    }

    public int[][] copyBoard() {
        return myBoard;
    }

    /*
     * markFirst makes places a 2 accumulation for X
     */
    public void markFirst(int row, int column) {
        myBoard[row][column] = 2;
    }

    /*
     * markSecond makes places a 1 accumulation for O
     */
    public void markSecond(int row, int column) {
        myBoard[row][column] = 1;
    }

    /*
     * elementMarked returns a true if the space has been taken
     */
    public boolean elementMarked(int row, int column) {
        if (myBoard[row][column] == 0)
            return false;
        else
            return true;
    }

    /*
     * Win constructor checks if someone wins. Here are the meanings of each
     * return type 'N' means no winner; 'X' means X won; 'O' means O won; 'C'
     * means a C's game.
     */
    public char win() {
        char winner = 'N';
        int catCheck = 1;

        // Check the columns
        for (int column = 0; column < 3; column++) {
            int accumulation = myBoard[0][column] * myBoard[1][column] * myBoard[2][column];

            if (accumulation == 8) // 2*2*2 = 8, a win for X
            {
                winner = 'X';
                break;
            }
            if (accumulation == 1) // 1*1*1 = 1, a win for O
            {
                winner = 'O';
                break;
            }
        }

        if (winner != 'N')
            return winner;

        // Check the rows
        for (int row = 0; row < 3; row++) {
            int accumulation = myBoard[row][0] * myBoard[row][1] * myBoard[row][2];
            if (accumulation == 8) {
                winner = 'X';
                break;
            }
            if (accumulation == 1) {
                winner = 'O';
                break;
            }
        }

        if (winner != 'N')
            return winner;

        // Check one diagonal
        int accumulation = myBoard[0][0] * myBoard[1][1] * myBoard[2][2];
        if (accumulation == 1)
            winner = 'O';
        if (accumulation == 8)
            winner = 'X';

        // Check the other diagonal
        accumulation = myBoard[0][2] * myBoard[1][1] * myBoard[2][0];
        if (accumulation == 1)
            winner = 'O';
        if (accumulation == 8)
            winner = 'X';

        // If nobody's won, Check for a cat's game
        if (winner == 'N') {
            for (int row = 0; row < 3; row++) {
                for (int column = 0; column < 3; column++) {
                    catCheck *= myBoard[row][column];
                }
            }
            // any empty space is a zero. So product is zero if there is space
            // left.
            if (catCheck != 0)
                winner = 'C';
        }

        return winner;
    }

    /*
     * toString enables printing out of the board
     */
    public String toString() {
        String printBoard = "";
        char XorO;
        int position = 49; // In ASCII, 49 stands for number 1

        for (int row = 0; row < 3; row++) {
            for (int column = 0; column < 3; column++) {
                if (myBoard[row][column] == 1)
                    // In ASCII, 79 stands for an O (78+1)
                    XorO = (char) (myBoard[row][column] + 78);
                else if (myBoard[row][column] == 2)
                    // In ASCII, 88 stands for an X (86+2)
                    XorO = (char) (myBoard[row][column] + 86);
                else
                    XorO = (char) (position);

                position++;

                printBoard = printBoard + XorO + " ";
            }
            printBoard = printBoard + "\n"; // starts a new line at the end of a
                                            // row
        }
        return printBoard;
    }
}

所以我想出的解决方案如下: 为了检查 X(计算机)的下一步行动是否有可能获胜,我们首先在棋盘的空闲单元格中放置一个 "theoretical/temporary"(稍后会清楚为什么它是临时的)'X' .换句话说,我们一个一个地遍历棋盘的单元格。如果一个单元格是空闲的,我们会在其中放置一个临时的 'X'。然后我们考虑我们拥有的新棋盘并检查是否有人赢了。如果是,我们清除我们放置临时 'X'(这就是它被称为临时的原因)和 return 的单元格,长度为 2 的字符数组包含谁赢了(即 'X','O'、'C' 或 'N') 以及导致获胜的理论单元格 (1-9)。如果没有人获胜,我们将清除刚刚填充的单元格,然后对下一个单元格再次尝试相同的过程,依此类推。

为了实现所有这些,我编写了一个名为 canWin() 的方法,该方法是在您的 win() 方法的基础上进行一些更改而构建的。此方法 return 是一个包含谁获胜和位置(单元格索引(1-9))的 2 元素字符数组。该方法详细工作如下: 该方法使用带有索引 i 的 for 循环,索引 i 从 1 递增到 9(单元格)。首先,使用您的转换方法,我们检查单元格 i 是否被占用:

if(!elementMarked(ComputerPlayer.Convert(i)[0], ComputerPlayer.Convert(i)[1]))

如果 elementMarked(...) return 为真,我们将跳过循环中的这次迭代并尝试以下单元格。但是,如果 elementMarked(...) return 为假,那么我们会使用您的 markFirst(...) 方法在其中放置一个 'X':

markFirst(ComputerPlayer.Convert(i)[0], ComputerPlayer.Convert(i)[1]);

之后,使用您从 win() 中检查的方式,我们检查是否有人赢了。如果确实如此,我们将获胜者和索引 i 保存在一个名为 result 和 return result 的 2 元素字符数组中。如果没有人赢,我会增加并且循环继续。此方法如下所示:

public char [] canWin(){
    char winner = 'N';
    int catCheck = 1;
    char [] result=new char[2];
    for(int i=1; i<10; i++){
        winner = 'N';
        //Places an X if a cell is not occupied
        if(!elementMarked(ComputerPlayer.Convert(i)[0], ComputerPlayer.Convert(i)[1]))
            markFirst(ComputerPlayer.Convert(i)[0],ComputerPlayer.Convert(i)[1]);
        else //If cell is occupied, skip this iteration
            continue;

        // Check the columns
        for (int column = 0; column < 3; column++) {
            int accumulation = myBoard[0][column] * myBoard[1][column] * myBoard[2][column];

            if (accumulation == 8) // 2*2*2 = 8, a win for X
            {
                winner = 'X';
                break;
            }
            if (accumulation == 1) // 1*1*1 = 1, a win for O
            {
                winner = 'O';
                break;
            }
        }

        if (winner != 'N'){
            result[0] = winner; //register winner
            result[1]=(char)i;  //register cell that led to win
            myBoard[ComputerPlayer.Convert(i)[0]][ComputerPlayer.Convert(i)[1]] = 0; //undoing the cell selection
            return result;
        }

        // Check the rows
        for (int row = 0; row < 3; row++) {
            int accumulation = myBoard[row][0] * myBoard[row][1] * myBoard[row][2];
            if (accumulation == 8) {
                winner = 'X';
                break;
            }
            if (accumulation == 1) {
                winner = 'O';
                break;
            }
        }

        if (winner != 'N'){
            result[0] = winner; //register winner
            result[1]=(char)i;  //register cell that led to win
            myBoard[ComputerPlayer.Convert(i)[0]][ComputerPlayer.Convert(i)[1]] = 0; //undoing the cell selection
            return result;
        }

        // Check one diagonal
        int accumulation = myBoard[0][0] * myBoard[1][1] * myBoard[2][2];
        if (accumulation == 1)
            winner = 'O';
        if (accumulation == 8){
            winner = 'X';
            result[0] = winner; //register winner
            result[1]=(char)i;  //register cell that led to win
            myBoard[ComputerPlayer.Convert(i)[0]][ComputerPlayer.Convert(i)[1]] = 0; //undoing the cell selection
            return result;
        }

        // Check the other diagonal
        accumulation = myBoard[0][2] * myBoard[1][1] * myBoard[2][0];
        if (accumulation == 1)
            winner = 'O';
        if (accumulation == 8){
            winner = 'X';
            result[0] = winner; //register winner
            result[1]=(char)i;  //register cell that led to win
            myBoard[ComputerPlayer.Convert(i)[0]][ComputerPlayer.Convert(i)[1]] = 0; //undoing the cell selection
            return result;
        }

        // If nobody's won, Check for a cat's game
        if (winner == 'N') {
            for (int row = 0; row < 3; row++) {
                for (int column = 0; column < 3; column++) {
                    catCheck *= myBoard[row][column];
                }
            }
            // any empty space is a zero. So product is zero if there is space
            // left.
            if (catCheck != 0)
                winner = 'C';
        }

        result[0] = winner; //register winner
        result[1]=(char)i;  //register cell that led to win
        myBoard[ComputerPlayer.Convert(i)[0]][ComputerPlayer.Convert(i)[1]] = 0; //undoing the cell selection
    }
    return result;
}

现在我们需要在你的main方法中实现这个方法。我们通过在每次玩家 O 将要玩(即玩家 X 完成他的移动之后)时调用 canWin() 来实现这一点。如果 canWin() returns 'X'(即 X 可以通过他的下一步行动获胜),那么我们向玩家打印一条消息警告他并告诉他他需要占据哪个单元格以防止 X 获胜.这看起来像这样:

// Player O's turn
        char[] canWin=Game.canWin();
        if(canWin[0]=='X') //If X could win with his next move
            System.out.println("Watch out! Player X can win if he plays in cell "+(int)Game.canWin()[1]+"!");
        System.out.print("Player O, Enter 1-9 to make choice: ");