Valid Tic-Tac-Toe State

题目
A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to reach this board position during the course of a valid tic-tac-toe game.

The board is a 3 x 3 array, and consists of characters " ", "X", and "O". The " " character represents an empty square.

Here are the rules of Tic-Tac-Toe:

Players take turns placing characters into empty squares (" ").
The first player always places "X" characters, while the second player always places "O" characters.
"X" and "O" characters are always placed into empty squares, never filled ones.
The game ends when there are 3 of the same (non-empty) character filling any row, column, or diagonal.
The game also ends if all squares are non-empty.
No more moves can be played if the game is over.

答案
Code may be a bit long because of the simple helper functions, but the main idea is REALLY straighforward:

Step 1, check #X = #O, or #X = #O + 1, otherwise it couldn't be a valid state
Step 2, recursively take off pieces until board is empty.

If there is one way you can take pieces off without triggering the end condition, then it means there is at least one way you can start from an empty board and reach the state given.

public int countPieces(char[][] board, char piece) {
        int cnt = 0;
        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                if(board[i][j] == piece) cnt++;
            }
        }
        return cnt;
    }

    public boolean isEnd(char[][] board) {
        // Horizontal
        String s0 = Character.toString(board[0][0]) + Character.toString(board[0][1]) + Character.toString(board[0][2]);
        String s1 = Character.toString(board[1][0]) + Character.toString(board[1][1]) + Character.toString(board[1][2]);
        String s2 = Character.toString(board[2][0]) + Character.toString(board[2][1]) + Character.toString(board[2][2]);

        // Vertical
        String s3 = "", s4 = "", s5 = "";
        s3 = Character.toString(board[0][0]) + Character.toString(board[1][0]) + Character.toString(board[2][0]);
        s4 = Character.toString(board[0][1]) + Character.toString(board[1][1]) + Character.toString(board[2][1]);
        s5 = Character.toString(board[0][2]) + Character.toString(board[1][2]) + Character.toString(board[2][2]);

        // Diagonal
        String s6 = "", s7 = "";
        s6 = Character.toString(board[0][0]) + Character.toString(board[1][1]) + Character.toString(board[2][2]);
        s7 = Character.toString(board[0][2]) + Character.toString(board[1][1]) + Character.toString(board[2][0]);

        return s0.equals("XXX") || s0.equals("OOO") || s1.equals("XXX") || s1.equals("OOO") || s2.equals("XXX") ||
                s2.equals("OOO") || s3.equals("XXX") || s3.equals("OOO") || s4.equals("XXX") || s4.equals("OOO") ||
                s5.equals("XXX") || s5.equals("OOO") || s6.equals("XXX") || s6.equals("OOO") || s7.equals("XXX") ||
                s7.equals("OOO");
    }

    public boolean validTicTacToe(String[] board) {
        // Convert array of strings to character board
        char[][] cBoard = new char[3][3];
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                cBoard[i][j] = board[i].charAt(j);

        // First, check either #X = #O or #X = #O + 1
        int numX = countPieces(cBoard, 'X');
        int numO = countPieces(cBoard, 'O');
        if(numX != numO && numX != numO + 1) return false;

        // Second, start with current state, find a way to remove pieces without meeting the end condition
        return recur(cBoard, numX, numO, true);
    }


    public boolean recur(char[][] board, int numX, int numO, boolean start) {
        if(numX == 0 && numO == 0) return true;
        if(isEnd(board) && !start) return false;

        boolean turn = numX > numO;
        boolean ret = false;
        // If to take 'X' off, recur on the choices of X. Same logic for 'O'.

        for(int i = 0; i < 3; i++) {
            for(int j = 0; j < 3; j++) {
                if(turn && board[i][j]== 'X') {
                    // Set board[i][j] to empty
                    board[i][j] = ' ';
                    ret = ret || recur(board, numX - 1, numO, false);
                    // Restore board
                    board[i][j] = 'X';
                }
                else if(!turn && board[i][j] == 'O') {
                    // Set board[i][j] to empty
                    board[i][j] = ' ';
                    ret = ret || recur(board, numX, numO - 1, false);
                    // Restore board
                    board[i][j] = 'O';
                }
            }
        }

        return ret;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容