java - 整数井字棋

标签 java bit

public class TicTacToe{
    /*
     * The board looks like this
     * 
     * 1 2 3
     * 4 5 6
     * 7 8 9
     * 
     */

    public final static int NORTH_WEST   = 1 << 0;
    public final static int NORTH        = 1 << 1;
    public final static int NORTH_EAST   = 1 << 2;
    public final static int MID_WEST     = 1 << 3;
    public final static int MID          = 1 << 4;
    public final static int MID_EAST     = 1 << 5;
    public final static int SOUTH_EAST   = 1 << 6;
    public final static int SOUTH        = 1 << 7;
    public final static int SOUTH_WEST   = 1 << 8;

    public final static int WIN_DIAGONAL_NW_SE = NORTH_EAST | MID      | SOUTH_EAST;
    public final static int WIN_DIAGONAL_NE_SW = NORTH_WEST | MID      | SOUTH_WEST;
    public final static int WIN_HORIZONTAL_1   = NORTH_WEST | NORTH    | NORTH_EAST;
    public final static int WIN_HORIZONTAL_2   = MID_WEST   | MID      | MID_EAST;
    public final static int WIN_HORIZONTAL_3   = SOUTH_WEST | SOUTH    | SOUTH_EAST;
    public final static int WIN_VERTICAL_1     = NORTH_WEST | MID_WEST | SOUTH_WEST;
    public final static int WIN_VERTICAL_2     = NORTH      | MID      | SOUTH;
    public final static int WIN_VERTICAL_3     = NORTH_EAST | MID_EAST | SOUTH_EAST;

    public final static int BOARD =
            NORTH_WEST | NORTH | NORTH_EAST |
            MID_WEST   | MID   | MID_EAST   |
            SOUTH_WEST | SOUTH | SOUTH_EAST;

    public final static int[] POSSIBLE_WINS = {
            WIN_DIAGONAL_NE_SW, WIN_DIAGONAL_NW_SE,
            WIN_HORIZONTAL_1, WIN_HORIZONTAL_2, WIN_HORIZONTAL_3,
            WIN_VERTICAL_1, WIN_VERTICAL_2, WIN_VERTICAL_3
    };

    /**
     * 
     * @param board
     * @return -1 for no win, 0 or 1 for the player that won
     */
    public static int checkWin(int board){
        int state = board & BOARD;
        for(int x : POSSIBLE_WINS){
            if((x & state) == x) {
                return (board & (1 << (Integer.lowestOneBit(x) + 8))) > 0 ? 1 : 0;
            }
        }
        return -1;
    }

    /**
     * 
     * @param player player 1 or 0
     * @param place the spot in the board to take
     * @return the new board state
     */
    public static int setBoard(int board, int player, int place){
        if(!(player == 0 || player == 1))
            throw new RuntimeException("Invalid Player. Must be 0 or 1.");
        if((place & BOARD) != place || place == 0)
            throw new RuntimeException("Invalid Place " + place);
        if(Integer.highestOneBit(place) != Integer.lowestOneBit(place))
            throw new RuntimeException("Invalid Place. Player " + player + " is attempting to steal multiple spots");


        board |= place;
        if(player == 1)
            board |= place << 9;
        else
            board &= ~(place << 9);

        return board;
    }
}

主要方法

public static void main(String[] args) {
    int board = TicTacToe.NORTH      | TicTacToe.MID      | TicTacToe.SOUTH |
                TicTacToe.NORTH << 9 | TicTacToe.MID << 9 | TicTacToe.SOUTH << 9;
    System.out.println("Board: " + board);
    System.out.println("Won: Player " + TicTacToe.checkWin(board));
    System.out.println("------");

    board &= TicTacToe.BOARD;
    System.out.println("Board: " + board);
    System.out.println("Won: Player " + TicTacToe.checkWin(board));
    System.out.println("------");

    board = 0;
    System.out.println("Board: " + board);
    System.out.println("Won: Player " + TicTacToe.checkWin(board));
    System.out.println("------");

    board = 0;
    board = TicTacToe.setBoard(board, 1, TicTacToe.NORTH_WEST);
    board = TicTacToe.setBoard(board, 1, TicTacToe.MID);
    board = TicTacToe.setBoard(board, 1, TicTacToe.SOUTH_EAST);
    System.out.println("Board: " + board);
    System.out.println("Board: " + (board&TicTacToe.BOARD));
    System.out.println("Won: Player " + TicTacToe.checkWin(board));
    System.out.println("------");


    System.out.println("The one below here doesn't work ---------------------------");
    board = 0;
    board = TicTacToe.setBoard(board, 0, TicTacToe.NORTH_WEST);
    board = TicTacToe.setBoard(board, 0, TicTacToe.MID);
    board = TicTacToe.setBoard(board, 0, TicTacToe.SOUTH_EAST);
    System.out.println("Board: " + board);
    System.out.println("Board: " + (board&TicTacToe.BOARD));
    System.out.println("Won: Player " + TicTacToe.checkWin(board));
    System.out.println("------");
}

ideone 链接 https://ideone.com/nPsWGO 这是它打印出来的内容

Board: 74898
Won: Player 1
        ------
Board: 146
Won: Player 0
        ------
Board: 0
Won: Player -1
        ------
Board: 16778065
Board: 337
Won: Player 1
        ------
The one below here doesn't work ---------------------------
Board: 81
Board: 81
Won: Player -1
        ------

您不必查看所有代码,只需查看我的 setBoard 函数,因为它适用于玩家 1 但不适用于玩家 2。我知道 check win 有效,因为我在第一个是上面输出中的示例。 这样做的目的是将整个游戏代码存储在一个整数中,我将在下面展示。

11111111111111111111111111111111
[p1 s ][p2 s ][player ][board  ]
[7 bits]p1 s   = player 1 score
[7 bits]p2 s   = player 2 score
[9 bits]player = the board shifted left 9 which player is holding the spot
[9 bits]board  = the actual board

最佳答案

你对对角线的定义有一个小错误

应该是

public final static int WIN_DIAGONAL_NW_SE = NORTH_WEST | MID | SOUTH_EAST;
public final static int WIN_DIAGONAL_NE_SW = NORTH_EAST | MID | SOUTH_WEST;

关于java - 整数井字棋,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34265214/

相关文章:

java - 如何在Eclipse中使用Gradle运行Cucumber + Spring Boot应用程序

java - 在 Java 中从字节中查找位值的问题

c - 如何将二进制数分成几部分? C语言

java - 如何在使用 CardLayout 切换后启动 JPanel

java - 有 2 个 if 语句的表渲染器

java - Jasper 报告生成错误的 HTML

Java Throw-Catch 异常困惑-1 示例

python - 翻转一个字节的最后一位

java - 如何使用java中的位操作来缩短长值?

c++ - 位操作