(Java) 使用二维数组的井字游戏

新手上路,请多包涵

在课堂上,我们的作业是创建一个二维数组并围绕它创建一个井字游戏。除了显示整个棋盘已满并且游戏是平局之外,我已经完成了所有工作。我已经尝试了一些东西,但我还没有找到解决方案,我需要一些帮助……这是我的代码:

 import java.util.Scanner;

public class TicTacToe {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int row, column;
        char player = 'X';

        //create 2 dimensional array for tic tac toe board
        char[][] board = new char[3][3];
        char ch = '1';
        for (int i = 0; i < 3; i++){
            for (int j = 0; j < 3; j++) {
                board[i][j] = ch++;
            }
        }
        displayBoard(board);
        while(!winner(board) == true){

            //get input for row/column
            System.out.println("Enter a row and column (0, 1, or 2); for player " + player + ":");
            row = in.nextInt();
            column = in.nextInt();

            //occupied
            while (board[row][column] == 'X' || board[row][column] == 'O') {
                System.out.println("This spot is occupied. Please try again");
            }
            //place the X
            board[row][column] = player;
            displayBoard(board);

            if (winner(board)){
                System.out.println("Player " + player + " is the winner!");
            }

            //time to swap players after each go.
            if (player == 'O') {
                player = 'X';

            }
            else {
                player = 'O';
            }
            if (winner(board) == false) {
            System.out.println("The game is a draw. Please try again.");

        }

    }

    private static void displayBoard(char[][] board) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (j == board[i].length - 1) System.out.print(board[i][j]);
                else System.out.print( board[i][j] + " | ");
            }
            System.out.println();
        }

    }
    //method to determine whether there is an x or an o in the spot
    public static Boolean winner(char[][] board){
        for (int i = 0; i< board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                if (board[i][j] == 'O' || board[i][j] == 'X') {
                    return false;
                }
            }
        }

        return (board[0][0] == board [0][1] && board[0][0] == board [0][2]) ||
            (board[0][0] == board [1][1] && board[0][0] == board [2][2]) ||
            (board[0][0] == board [1][0] && board[0][0] == board [2][0]) ||
            (board[2][0] == board [2][1] && board[2][0] == board [2][2]) ||
            (board[2][0] == board [1][1] && board[0][0] == board [0][2]) ||
            (board[0][2] == board [1][2] && board[0][2] == board [2][2]) ||
            (board[0][1] == board [1][1] && board[0][1] == board [2][1]) ||
            (board[1][0] == board [1][1] && board[1][0] == board [1][2]);
    }
}

我想要输出说板已满但我什么也没得到。这是我输出的最后一行,如您所见,我当前的策略不起作用,因为它继续要求输入。 –>

输入行和列(0、1 或 2);对于玩家 X:2 0 X |欧 | XO |欧 | X X | × | O 输入一行和一列(0、1 或 2);对于玩家O:

原文由 Shepp 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 403
2 个回答

首先:

  while (board[row][column] == 'X' || board[row][column] == 'O') {
            System.out.println("This spot is occupied. Please try again");
        }

这将创建一个无限循环,因为 rowcolumn 不应该改变你应该要求新的输入!

public static Boolean winner(char[][] board){
    for (int i = 0; i< board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            if (board[i][j] == 'O' || board[i][j] == 'X') {
                return false;
            }
        }
    }

一旦你点击“O”或“X”,你将以错误的方式退出方法(没有赢家)

您可能想要检查的是是否每个位置都被占用

public static Boolean winner(char[][] board){
   //Boolean which is true until there is a empty spot
   boolean occupied = true;
   //loop and check if there is empty space or if its a draw
    for (int i = 0; i< board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            //Check if spot is not 'O' or not 'X' => empty
            if (board[i][j] != 'O' || board[i][j] != 'X') {
                occupied = false;
            }
        }
    }
    if(occupied)
        return false;
   //Check if someone won
    return (board[0][0] == board [0][1] && board[0][0] == board [0][2]) ||
        (board[0][0] == board [1][1] && board[0][0] == board [2][2]) ||
        (board[0][0] == board [1][0] && board[0][0] == board [2][0]) ||
        (board[2][0] == board [2][1] && board[2][0] == board [2][2]) ||
        (board[2][0] == board [1][1] && board[0][0] == board [0][2]) ||
        (board[0][2] == board [1][2] && board[0][2] == board [2][2]) ||
        (board[0][1] == board [1][1] && board[0][1] == board [2][1]) ||
        (board[1][0] == board [1][1] && board[1][0] == board [1][2]);
}

现在这将检查是否有赢家或平局

Occupied == true == tie == return false

Winner == return true

但是你有三种状态:

  • 领带
  • 没做完

使用更改后的方法,在您获胜之前,您不会完成游戏。

原因:

  while(!winner(board) == true)

这使得游戏在没有赢家的情况下一直运行(winner() 将为 false,因为一切都已被占用或没有赢家)

 while(!false==true) => while(true)

您可以编写一个类似于 winner 的方法,但它只检查棋盘是否有空位:

 public static Boolean hasEmptySpot(char[][] board){
   //loop and check if there is empty space
    for (int i = 0; i< board.length; i++) {
        for (int j = 0; j < board[0].length; j++) {
            if (board[i][j] != 'O' && board[i][j] != 'X') {
                return true;
            }
        }
    }
    return false;
}

//New code
while(hasEmptySpot(board) || !winner(board)){
          //Your code for the game here
     ....
    }

当没有空位时,这将结束游戏完成游戏后,您可以调用 winner(board) ,如果您平局或获胜,它将返回!

通过创建 hasEmptySpot() 您可以将获胜者方法更改为

public static Boolean winner(char[][] board){
    return (board[0][0] == board [0][1] && board[0][0] == board [0][2]) ||
        (board[0][0] == board [1][1] && board[0][0] == board [2][2]) ||
        (board[0][0] == board [1][0] && board[0][0] == board [2][0]) ||
        (board[2][0] == board [2][1] && board[2][0] == board [2][2]) ||
        (board[2][0] == board [1][1] && board[0][0] == board [0][2]) ||
        (board[0][2] == board [1][2] && board[0][2] == board [2][2]) ||
        (board[0][1] == board [1][1] && board[0][1] == board [2][1]) ||
        (board[1][0] == board [1][1] && board[1][0] == board [1][2]);
}

为什么?因为您完成了游戏并且您知道只有赢或平两种可能的结果。

我希望这对你有所帮助。

编辑 我自己有逻辑错误!

第一个错误: 你仍然需要在游戏运行时检查是否有赢家忘记了这一点!

 while(hasEmptySpot(board) || !winner(board)){
}

现在,当有赢家或没有空位时,这将退出游戏循环

第二个错误: 在 hasEmptySpot()

  if (board[i][j] != 'O' && board[i][j] != 'X') {
                return true;

不是

 if (board[i][j] != 'O' || board[i][j] != 'X') {
                return true;

在上面的示例中修复了它。

对不起给您带来不便!

原文由 Nordiii 发布,翻译遵循 CC BY-SA 3.0 许可协议

执行此操作的最有效方法是对之前已填充的空间数量进行连续计数,并在每次占用空间时递增该计数。当计数达到 9 时,板可以被认为已满。

如果您熟悉面向对象的编程,我认为如果将 2D 数组包装在 Board 类中,您会发现这更容易实现。

例子:

 public static class Board {
    private char[][] spaces = new char[3][3];
    private int numMoves = 0;

    public void makeMove(int row, int col, char player) {
        if (spaces[row][col] == 'X' || spaces[row][col] == 'O') {
            System.out.println("This spot is occupied. Please try again");
        } else {
            spaces[row][col] = player;
            numMoves++;
        }
    }

    public boolean isFull() {
        return numMoves == 9;
    }

    public boolean hasWinner() {
        ...
    }

    public void display() {
        ...
    }
}

原文由 Pablo Napolitano 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题