1. ホーム
  2. java

[解決済み] (Java) 2次元配列による三目並べゲーム

2022-02-09 12:17:10

質問

授業では、2次元の配列を作成し、それを中心に三目並べゲームを作成することが課題です。私は、ボード全体が一杯になり、ゲームが引き分けになったときに表示すること以外はすべて完了しました。いくつかのことを試してみましたが、解決策が見つからず、助けを必要としています...。以下は私のコードです。

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|O|X(エックス O|オー|エックス X|エックス|オー 行と列(0,1,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

でも、3つの状態がありますよね。

  • 勝つ
  • タイ
  • 未完成

変更されたメソッドでは、勝つまでゲームを終了することはできません。

理由

 while(!winner(board) == true)

これは、勝者がいない限り、ゲームを実行させるものです。 (すべてが占有されているか、勝者がいないため、winner() は偽になります)

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]);
}

どうして? なぜなら、あなたはゲームを終えて、可能な結果がWinかTieの2つだけだと知っているからです。

少しはお役に立てたでしょうか?

EDIT ロジックを間違えていました。

最初のミス その点を忘れていると、ゲーム進行中に勝敗を確認する必要がありますよ。

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

これで、勝者がいるか、空席がなくなると、ゲームのループを終了します。

2つ目の間違い。 hasEmptySpot()内

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

ではなく

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

上の例で修正しました。

ご迷惑をおかけして申し訳ございませんでした