Algorithm 确定Tic-Tac-Toe博弈的算法

Algorithm 确定Tic-Tac-Toe博弈的算法,algorithm,state,tic-tac-toe,Algorithm,State,Tic Tac Toe,我已经用Java编写了一个tic-tac-toe游戏,我目前确定游戏结束的方法考虑了游戏结束后可能出现的以下情况: 棋盘已满,尚未宣布胜利者:比赛是平局 克罗斯赢了 Circle赢了 不幸的是,要这样做,它会从一个表中读取这些场景的预定义集合。考虑到一个棋盘上只有9个空格,因此桌子有点小,这并不一定不好,但是有没有更好的算法来确定游戏是否结束?确定某人是否获胜是问题的关键,因为检查9个空格是否已满是微不足道的 table方法可能是解决方案,但如果不是,是什么?此外,如果电路板的尺寸不是n=9,该

我已经用Java编写了一个tic-tac-toe游戏,我目前确定游戏结束的方法考虑了游戏结束后可能出现的以下情况:

  • 棋盘已满,尚未宣布胜利者:比赛是平局
  • 克罗斯赢了
  • Circle赢了
  • 不幸的是,要这样做,它会从一个表中读取这些场景的预定义集合。考虑到一个棋盘上只有9个空格,因此桌子有点小,这并不一定不好,但是有没有更好的算法来确定游戏是否结束?确定某人是否获胜是问题的关键,因为检查9个空格是否已满是微不足道的


    table方法可能是解决方案,但如果不是,是什么?此外,如果电路板的尺寸不是
    n=9
    ,该怎么办?如果它是一个更大的棋盘,比如说
    n=16
    n=25
    ,等等,导致连续放置的项目数量为
    x=4
    x=5
    ,等等,会怎么样?一种用于所有
    n={9,16,25,36…}

    如果任何一行、一列或一条对角线加起来等于15,则玩家获胜,则可以使用幻方。

    如果棋盘为n×n,则有n行、n列和2条对角线。检查每一个都是全X或全O,以找到一个赢家

    如果只需要x (我实际上并没有测试这个*cough*,但它在第一次尝试时就编译好了,耶!)

    公共类TicTacToe
    {
    公共枚举方{X,O,NONE}
    /**
    *返回获胜的玩家,如果游戏已结束,则返回“无”
    *完成时没有赢家,如果游戏未完成则为空。
    */
    公共广场findWinner(广场[]板,国际长度){
    //检查每个lengthToWin x lengthToWin板是否有赢家。
    
    对于(int top=0;top您知道只有在X或O最近一次移动后才能进行获胜移动,因此您只能使用该移动中包含的可选diag搜索行/列,以限制您在尝试确定获胜棋盘时的搜索空间。此外,由于平局tic tac toe游戏中的移动次数是固定的,因此最后一个m如果这不是一个胜利的举动,那么这是一个默认的平局游戏

    编辑:此代码适用于n乘n板,n在一行中获胜(3x3板要求3在一行中,等等)

    编辑:添加了检查反诊断的代码,我无法找到一种非循环的方法来确定该点是否在反诊断上,所以这就是缺少该步骤的原因

    public class TripleT {
    
        enum State{Blank, X, O};
    
        int n = 3;
        State[][] board = new State[n][n];
        int moveCount;
    
        void Move(int x, int y, State s){
            if(board[x][y] == State.Blank){
                board[x][y] = s;
            }
            moveCount++;
    
            //check end conditions
    
            //check col
            for(int i = 0; i < n; i++){
                if(board[x][i] != s)
                    break;
                if(i == n-1){
                    //report win for s
                }
            }
    
            //check row
            for(int i = 0; i < n; i++){
                if(board[i][y] != s)
                    break;
                if(i == n-1){
                    //report win for s
                }
            }
    
            //check diag
            if(x == y){
                //we're on a diagonal
                for(int i = 0; i < n; i++){
                    if(board[i][i] != s)
                        break;
                    if(i == n-1){
                        //report win for s
                    }
                }
            }
    
            //check anti diag (thanks rampion)
            if(x + y == n - 1){
                for(int i = 0; i < n; i++){
                    if(board[i][(n-1)-i] != s)
                        break;
                    if(i == n-1){
                        //report win for s
                    }
                }
            }
    
            //check draw
            if(moveCount == (Math.pow(n, 2) - 1)){
                //report draw
            }
        }
    }
    
    公共类三元组{
    枚举状态{Blank,X,O};
    int n=3;
    州[]董事会=新州[n][n];
    int moveCount;
    无效移动(整数x,整数y,状态s){
    如果(线路板[x][y]==状态为空){
    板[x][y]=s;
    }
    moveCount++;
    //检查结束条件
    //检查列
    对于(int i=0;i
    我不太懂Java,但我确实懂C,所以我试过(和其他人一起)

    //tic tac toe.c
    //汇编:
    //%gcc-o tic tac toe tic tac toe.c
    //要运行:
    //百分比/井字通
    #包括
    //两种类型的标记可用
    typedef枚举{Empty=2,X=0,O=1,NumMarks=2}标记;
    字符常量MarkToChar[]=“XO”;
    //保存各种标记总和的结构
    typedef struct{unsigned char of[NumMarks];}Sum;
    //电路板中具有特定值的单元
    #定义幻数15
    类型定义结构{
    标记;
    无符号字符常量值;
    大小常数和数;
    总和*常数总和[4];
    }细胞;
    #定义第3行的数量
    #定义NUM_COLS 3
    //为每个可能的tic-tac-toe创建一个总和
    求和行[NUM_ROWS]={0};
    和列[NUM_COLS]={0};
    和nw_diag={0};
    和ne_diag={0};
    //初始化电路板值,使任何行、列或对角线都添加到
    //神奇的数字,所以他们每个人都在适当的行、列中记录他们的总和,
    //和对角线
    单元板[NUM_ROWS][NUM_COLS]={
    { 
    {Empty,8,3,{&row[0],&col[0],&nw_diag},
    {Empty,1,2,{&row[0],&col[1]},
    {Empty,6,3,{&row[0],&col[2],&ne_diag},
    },
    { 
    {Empty,3,2,{&row[1],&col[0]},
    {Empty,5,4,{&row[1],&col[1],&nw_diag,&ne_diag},
    {Empty,7,2,{&row[1],&col[2]},
    },
    { 
    {Empty,4,3,{&row[2],&col[0],&ne_diag}},
    {Empty,9,2,{&row[2],&col[1]},
    {Empty,2,3,{&row[2],&col[2],&nw_diag},
    }
    };
    //打印电路板
    无效显示板(无效)
    {
    尺寸r,c;
    对于(r=0;r0){printf(“--+--+--+--\n”);}
    对于(c=0;c0){printf(“|”);}
    printf(“%c”,MarkToChar[board[r][c].mark]);
    }
    printf(“\n”);
    }
    }
    //运行游戏,要求玩家为每一方提供输入
    内部主(内部a
    
    public class TripleT {
    
        enum State{Blank, X, O};
    
        int n = 3;
        State[][] board = new State[n][n];
        int moveCount;
    
        void Move(int x, int y, State s){
            if(board[x][y] == State.Blank){
                board[x][y] = s;
            }
            moveCount++;
    
            //check end conditions
    
            //check col
            for(int i = 0; i < n; i++){
                if(board[x][i] != s)
                    break;
                if(i == n-1){
                    //report win for s
                }
            }
    
            //check row
            for(int i = 0; i < n; i++){
                if(board[i][y] != s)
                    break;
                if(i == n-1){
                    //report win for s
                }
            }
    
            //check diag
            if(x == y){
                //we're on a diagonal
                for(int i = 0; i < n; i++){
                    if(board[i][i] != s)
                        break;
                    if(i == n-1){
                        //report win for s
                    }
                }
            }
    
            //check anti diag (thanks rampion)
            if(x + y == n - 1){
                for(int i = 0; i < n; i++){
                    if(board[i][(n-1)-i] != s)
                        break;
                    if(i == n-1){
                        //report win for s
                    }
                }
            }
    
            //check draw
            if(moveCount == (Math.pow(n, 2) - 1)){
                //report draw
            }
        }
    }
    
    // tic-tac-toe.c
    // to compile:
    //  % gcc -o tic-tac-toe tic-tac-toe.c
    // to run:
    //  % ./tic-tac-toe
    #include <stdio.h>
    
    // the two types of marks available
    typedef enum { Empty=2, X=0, O=1, NumMarks=2 } Mark;
    char const MarkToChar[] = "XO ";
    
    // a structure to hold the sums of each kind of mark
    typedef struct { unsigned char of[NumMarks]; } Sum;
    
    // a cell in the board, which has a particular value
    #define MAGIC_NUMBER 15
    typedef struct {
      Mark mark;
      unsigned char const value;
      size_t const num_sums;
      Sum * const sums[4];
    } Cell;
    
    #define NUM_ROWS 3
    #define NUM_COLS 3
    
    // create a sum for each possible tic-tac-toe
    Sum row[NUM_ROWS] = {0};
    Sum col[NUM_COLS] = {0};
    Sum nw_diag = {0};
    Sum ne_diag = {0};
    
    // initialize the board values so any row, column, or diagonal adds to
    // MAGIC_NUMBER, and so they each record their sums in the proper rows, columns,
    // and diagonals
    Cell board[NUM_ROWS][NUM_COLS] = { 
      { 
        { Empty, 8, 3, { &row[0], &col[0], &nw_diag } },
        { Empty, 1, 2, { &row[0], &col[1] } },
        { Empty, 6, 3, { &row[0], &col[2], &ne_diag } },
      },
      { 
        { Empty, 3, 2, { &row[1], &col[0] } },
        { Empty, 5, 4, { &row[1], &col[1], &nw_diag, &ne_diag } },
        { Empty, 7, 2, { &row[1], &col[2] } },
      },
      { 
        { Empty, 4, 3, { &row[2], &col[0], &ne_diag } },
        { Empty, 9, 2, { &row[2], &col[1] } },
        { Empty, 2, 3, { &row[2], &col[2], &nw_diag } },
      }
    };
    
    // print the board
    void show_board(void)
    {
      size_t r, c;
      for (r = 0; r < NUM_ROWS; r++) 
      {
        if (r > 0) { printf("---+---+---\n"); }
        for (c = 0; c < NUM_COLS; c++) 
        {
          if (c > 0) { printf("|"); }
          printf(" %c ", MarkToChar[board[r][c].mark]);
        }
        printf("\n");
      }
    }
    
    
    // run the game, asking the player for inputs for each side
    int main(int argc, char * argv[])
    {
      size_t m;
      show_board();
      printf("Enter moves as \"<row> <col>\" (no quotes, zero indexed)\n");
      for( m = 0; m < NUM_ROWS * NUM_COLS; m++ )
      {
        Mark const mark = (Mark) (m % NumMarks);
        size_t c, r;
    
        // read the player's move
        do
        {
          printf("%c's move: ", MarkToChar[mark]);
          fflush(stdout);
          scanf("%d %d", &r, &c);
          if (r >= NUM_ROWS || c >= NUM_COLS)
          {
            printf("illegal move (off the board), try again\n");
          }
          else if (board[r][c].mark != Empty)
          {
            printf("illegal move (already taken), try again\n");
          }
          else
          {
            break;
          }
        }
        while (1);
    
        {
          Cell * const cell = &(board[r][c]);
          size_t s;
    
          // update the board state
          cell->mark = mark;
          show_board();
    
          // check for tic-tac-toe
          for (s = 0; s < cell->num_sums; s++)
          {
            cell->sums[s]->of[mark] += cell->value;
            if (cell->sums[s]->of[mark] == MAGIC_NUMBER)
            {
              printf("tic-tac-toe! %c wins!\n", MarkToChar[mark]);
              goto done;
            }
          }
        }
      }
      printf("stalemate... nobody wins :(\n");
    done:
      return 0;
    }
    
    % gcc -o tic-tac-toe tic-tac-toe.c % ./tic-tac-toe | | ---+---+--- | | ---+---+--- | | Enter moves as " " (no quotes, zero indexed) X's move: 1 2 | | ---+---+--- | | X ---+---+--- | | O's move: 1 2 illegal move (already taken), try again O's move: 3 3 illegal move (off the board), try again O's move: 2 2 | | ---+---+--- | | X ---+---+--- | | O X's move: 1 0 | | ---+---+--- X | | X ---+---+--- | | O O's move: 1 1 | | ---+---+--- X | O | X ---+---+--- | | O X's move: 0 0 X | | ---+---+--- X | O | X ---+---+--- | | O O's move: 2 0 X | | ---+---+--- X | O | X ---+---+--- O | | O X's move: 2 1 X | | ---+---+--- X | O | X ---+---+--- O | X | O O's move: 0 2 X | | O ---+---+--- X | O | X ---+---+--- O | X | O tic-tac-toe! O wins! % ./tic-tac-toe | | ---+---+--- | | ---+---+--- | | Enter moves as " " (no quotes, zero indexed) X's move: 0 0 X | | ---+---+--- | | ---+---+--- | | O's move: 0 1 X | O | ---+---+--- | | ---+---+--- | | X's move: 0 2 X | O | X ---+---+--- | | ---+---+--- | | O's move: 1 0 X | O | X ---+---+--- O | | ---+---+--- | | X's move: 1 1 X | O | X ---+---+--- O | X | ---+---+--- | | O's move: 2 0 X | O | X ---+---+--- O | X | ---+---+--- O | | X's move: 2 1 X | O | X ---+---+--- O | X | ---+---+--- O | X | O's move: 2 2 X | O | X ---+---+--- O | X | ---+---+--- O | X | O X's move: 1 2 X | O | X ---+---+--- O | X | X ---+---+--- O | X | O stalemate... nobody wins :( %
    col=row=diag=rdiag=0
    winner=false
    for i=1 to n
      if cell[x,i]=player then col++
      if cell[i,y]=player then row++
      if cell[i,i]=player then diag++
      if cell[i,n-i+1]=player then rdiag++
    if row=n or col=n or diag=n or rdiag=n then winner=true
    
    A piece from player A has value (1,0) A piece from player B has value (0,1) O(1) time (per move) O(n) space (overall) two_elements*n_rows + two_elements*n_columns + two_elements*two_diagonals = 4*n + 4 integers = 4(n+1) integers
    `if (x + y == n - 1)`
    
    // This program will work with any whole number sized rectangular gameBoard.
    // It checks for N marks in straight lines (rows, columns, and diagonals).
    // It is prettiest when ROWS and COLS are single digit numbers.
    // Try altering the constants for ROWS, COLS, and N for great fun!    
    
    // PPDs come first
    
        #include <stdio.h>
        #define ROWS 9              // The number of rows our gameBoard array will have
        #define COLS 9              // The number of columns of the same - Single digit numbers will be prettier!
        #define N 3                 // This is the number of contiguous marks a player must have to win
        #define INITCHAR ' '        // This changes the character displayed (a ' ' here probably looks the best)
        #define PLAYER1CHAR 'X'     // Some marks are more aesthetically pleasing than others
        #define PLAYER2CHAR 'O'     // Change these lines if you care to experiment with them
    
    
    // Function prototypes are next
    
        int playGame    (char gameBoard[ROWS][COLS]);               // This function allows the game to be replayed easily, as desired
        void initBoard  (char gameBoard[ROWS][COLS]);               // Fills the ROWSxCOLS character array with the INITCHAR character
        void printBoard (char gameBoard[ROWS][COLS]);               // Prints out the current board, now with pretty formatting and #s!
        void makeMove   (char gameBoard[ROWS][COLS], int player);   // Prompts for (and validates!) a move and stores it into the array
        int checkWinner (char gameBoard[ROWS][COLS], int player);   // Checks the current state of the board to see if anyone has won
    
    // The starting line
    int main (void)
    {
        // Inits
        char gameBoard[ROWS][COLS];     // Our gameBoard is declared as a character array, ROWS x COLS in size
        int winner = 0;
        char replay;
    
        //Code
        do                              // This loop plays through the game until the user elects not to
        {
            winner = playGame(gameBoard);
            printf("\nWould you like to play again? Y for yes, anything else exits: ");
    
            scanf("%c",&replay);        // I have to use both a scanf() and a getchar() in
            replay = getchar();         // order to clear the input buffer of a newline char
                                        // (http://cboard.cprogramming.com/c-programming/121190-problem-do-while-loop-char.html)
    
        } while ( replay == 'y' || replay == 'Y' );
    
        // Housekeeping
        printf("\n");
        return winner;
    }
    
    
    int playGame(char gameBoard[ROWS][COLS])
    {
        int turn = 0, player = 0, winner = 0, i = 0;
    
        initBoard(gameBoard);
    
        do
        {
            turn++;                                 // Every time this loop executes, a unique turn is about to be made
            player = (turn+1)%2+1;                  // This mod function alternates the player variable between 1 & 2 each turn
            makeMove(gameBoard,player);
            printBoard(gameBoard);
            winner = checkWinner(gameBoard,player);
    
            if (winner != 0)
            {
                printBoard(gameBoard);
    
                for (i=0;i<19-2*ROWS;i++)           // Formatting - works with the default shell height on my machine
                    printf("\n");                   // Hopefully I can replace these with something that clears the screen for me
    
                printf("\n\nCongratulations Player %i, you've won with %i in a row!\n\n",winner,N);
                return winner;
            }
    
        } while ( turn < ROWS*COLS );                           // Once ROWS*COLS turns have elapsed
    
        printf("\n\nGame Over!\n\nThere was no Winner :-(\n");  // The board is full and the game is over
        return winner;
    }
    
    
    void initBoard (char gameBoard[ROWS][COLS])
    {
        int row = 0, col = 0;
    
        for (row=0;row<ROWS;row++)
        {
            for (col=0;col<COLS;col++)
            {
                gameBoard[row][col] = INITCHAR;     // Fill the gameBoard with INITCHAR characters
            }
        }
    
        printBoard(gameBoard);                      // Having this here prints out the board before
        return;                             // the playGame function asks for the first move
    }
    
    
    void printBoard (char gameBoard[ROWS][COLS])    // There is a ton of formatting in here
    {                                               // That I don't feel like commenting :P
        int row = 0, col = 0, i=0;                  // It took a while to fine tune
                                                    // But now the output is something like:
        printf("\n");                               // 
                                                    //    1   2   3
        for (row=0;row<ROWS;row++)                  // 1    |   |
        {                                           //   -----------
            if (row == 0)                           // 2    |   |
            {                                       //   -----------
                printf("  ");                       // 3    |   |
    
                for (i=0;i<COLS;i++)
                {
                    printf(" %i  ",i+1);
                }
    
                printf("\n\n");
            }
    
            for (col=0;col<COLS;col++)
            {
                if (col==0)
                    printf("%i ",row+1);
    
                printf(" %c ",gameBoard[row][col]);
    
                if (col<COLS-1)
                    printf("|");
            }
    
            printf("\n");
    
            if (row < ROWS-1)
            {
                for(i=0;i<COLS-1;i++)
                {
                    if(i==0)
                        printf("  ----");
                    else
                        printf("----");
                }
    
                printf("---\n");
            }
        }
    
        return;
    }
    
    
    void makeMove (char gameBoard[ROWS][COLS],int player)
    {
        int row = 0, col = 0, i=0;
        char currentChar;
    
        if (player == 1)                    // This gets the correct player's mark
            currentChar = PLAYER1CHAR;
        else
            currentChar = PLAYER2CHAR;
    
        for (i=0;i<21-2*ROWS;i++)           // Newline formatting again :-(
            printf("\n");
    
        printf("\nPlayer %i, please enter the column of your move: ",player);
        scanf("%i",&col);
        printf("Please enter the row of your move: ");
        scanf("%i",&row);
    
        row--;                              // These lines translate the user's rows and columns numbering
        col--;                              // (starting with 1) to the computer's (starting with 0)
    
        while(gameBoard[row][col] != INITCHAR || row > ROWS-1 || col > COLS-1)  // We are not using a do... while because
        {                                                                       // I wanted the prompt to change
            printBoard(gameBoard);
            for (i=0;i<20-2*ROWS;i++)
                printf("\n");
            printf("\nPlayer %i, please enter a valid move! Column first, then row.\n",player);
            scanf("%i %i",&col,&row);
    
            row--;                          // See above ^^^
            col--;
        }
    
        gameBoard[row][col] = currentChar;  // Finally, we store the correct mark into the given location
        return;                             // And pop back out of this function
    }
    
    
    int checkWinner(char gameBoard[ROWS][COLS], int player)     // I've commented the last (and the hardest, for me anyway)
    {                                                           // check, which checks for backwards diagonal runs below >>>
        int row = 0, col = 0, i = 0;
        char currentChar;
    
        if (player == 1)
            currentChar = PLAYER1CHAR;
        else
            currentChar = PLAYER2CHAR;
    
        for ( row = 0; row < ROWS; row++)                       // This first for loop checks every row
        {
            for ( col = 0; col < (COLS-(N-1)); col++)           // And all columns until N away from the end
            {
                while (gameBoard[row][col] == currentChar)      // For consecutive rows of the current player's mark
                {
                    col++;
                    i++;
                    if (i == N)
                    {
                        return player;
                    }
                }
                i = 0;
            }
        }
    
        for ( col = 0; col < COLS; col++)                       // This one checks for columns of consecutive marks
        {
            for ( row = 0; row < (ROWS-(N-1)); row++)
            {
                while (gameBoard[row][col] == currentChar)
                {
                    row++;
                    i++;
                    if (i == N)
                    {
                        return player;
                    }
                }
                i = 0;
            }
        }
    
        for ( col = 0; col < (COLS - (N-1)); col++)             // This one checks for "forwards" diagonal runs
        {
            for ( row = 0; row < (ROWS-(N-1)); row++)
            {
                while (gameBoard[row][col] == currentChar)
                {
                    row++;
                    col++;
                    i++;
                    if (i == N)
                    {
                        return player;
                    }
                }
                i = 0;
            }
        }
                                                            // Finally, the backwards diagonals:
        for ( col = COLS-1; col > 0+(N-2); col--)           // Start from the last column and go until N columns from the first
        {                                                   // The math seems strange here but the numbers work out when you trace them
            for ( row = 0; row < (ROWS-(N-1)); row++)       // Start from the first row and go until N rows from the last
            {
                while (gameBoard[row][col] == currentChar)  // If the current player's character is there
                {
                    row++;                                  // Go down a row
                    col--;                                  // And back a column
                    i++;                                    // The i variable tracks how many consecutive marks have been found
                    if (i == N)                             // Once i == N
                    {
                        return player;                      // Return the current player number to the
                    }                                       // winnner variable in the playGame function
                }                                           // If it breaks out of the while loop, there weren't N consecutive marks
                i = 0;                                      // So make i = 0 again
            }                                               // And go back into the for loop, incrementing the row to check from
        }
    
        return 0;                                           // If we got to here, no winner has been detected,
    }                                                       // so we pop back up into the playGame function
    
    // The end!
    
    // Well, almost.
    
    // Eventually I hope to get this thing going
    // with a dynamically sized array. I'll make
    // the CONSTANTS into variables in an initGame
    // function and allow the user to define them.
    
        int gameState(int values[][], int boardSz) {
    
    
        boolean colCheckNotRequired[] = new boolean[boardSz];//default is false
        boolean diag1CheckNotRequired = false;
        boolean diag2CheckNotRequired = false;
        boolean allFilled = true;
    
    
        int x_count = 0;
        int o_count = 0;
        /* Check rows */
        for (int i = 0; i < boardSz; i++) {
            x_count = o_count = 0;
            for (int j = 0; j < boardSz; j++) {
                if(values[i][j] == x_val)x_count++;
                if(values[i][j] == o_val)o_count++;
                if(values[i][j] == 0)
                {
                    colCheckNotRequired[j] = true;
                    if(i==j)diag1CheckNotRequired = true;
                    if(i + j == boardSz - 1)diag2CheckNotRequired = true;
                    allFilled = false;
                    //No need check further
                    break;
                }
            }
            if(x_count == boardSz)return X_WIN;
            if(o_count == boardSz)return O_WIN;         
        }
    
    
        /* check cols */
        for (int i = 0; i < boardSz; i++) {
            x_count = o_count = 0;
            if(colCheckNotRequired[i] == false)
            {
                for (int j = 0; j < boardSz; j++) {
                    if(values[j][i] == x_val)x_count++;
                    if(values[j][i] == o_val)o_count++;
                    //No need check further
                    if(values[i][j] == 0)break;
                }
                if(x_count == boardSz)return X_WIN;
                if(o_count == boardSz)return O_WIN;
            }
        }
    
        x_count = o_count = 0;
        /* check diagonal 1 */
        if(diag1CheckNotRequired == false)
        {
            for (int i = 0; i < boardSz; i++) {
                if(values[i][i] == x_val)x_count++;
                if(values[i][i] == o_val)o_count++;
                if(values[i][i] == 0)break;
            }
            if(x_count == boardSz)return X_WIN;
            if(o_count == boardSz)return O_WIN;
        }
    
        x_count = o_count = 0;
        /* check diagonal 2 */
        if( diag2CheckNotRequired == false)
        {
            for (int i = boardSz - 1,j = 0; i >= 0 && j < boardSz; i--,j++) {
                if(values[j][i] == x_val)x_count++;
                if(values[j][i] == o_val)o_count++;
                if(values[j][i] == 0)break;
            }
            if(x_count == boardSz)return X_WIN;
            if(o_count == boardSz)return O_WIN;
            x_count = o_count = 0;
        }
    
        if( allFilled == true)
        {
            for (int i = 0; i < boardSz; i++) {
                for (int j = 0; j < boardSz; j++) {
                    if (values[i][j] == 0) {
                        allFilled = false;
                        break;
                    }
                }
    
                if (allFilled == false) {
                    break;
                }
            }
        }
    
        if (allFilled)
            return DRAW;
    
        return INPROGRESS;
    }
    
    def spin(g): return set([g, turn(g), turn(turn(g)), turn(turn(turn(g)))])
    def turn(g): return tuple(tuple(g[y][x] for y in (0,1,2)) for x in (2,1,0))
    
    X,s = 'X.'
    XXX = X, X, X
    sss = s, s, s
    
    ways_to_win = (  spin((XXX, sss, sss))
                   | spin((sss, XXX, sss))
                   | spin(((X,s,s),
                           (s,X,s),
                           (s,s,X))))
    
    public class TicTacToe {
        public static final char BLANK = '\u0000';
        private final char[][] board;
        private int moveCount;
        private Referee referee;
    
        public TicTacToe(int gridSize) {
            if (gridSize < 3)
                throw new IllegalArgumentException("TicTacToe board size has to be minimum 3x3 grid");
            board = new char[gridSize][gridSize];
            referee = new Referee(gridSize);
        }
    
        public char[][] displayBoard() {
            return board.clone();
        }
    
        public String move(int x, int y) {
            if (board[x][y] != BLANK)
                return "(" + x + "," + y + ") is already occupied";
            board[x][y] = whoseTurn();
            return referee.isGameOver(x, y, board[x][y], ++moveCount);
        }
    
        private char whoseTurn() {
            return moveCount % 2 == 0 ? 'X' : 'O';
        }
    
        private class Referee {
            private static final int NO_OF_DIAGONALS = 2;
            private static final int MINOR = 1;
            private static final int PRINCIPAL = 0;
            private final int gridSize;
            private final int[] rowTotal;
            private final int[] colTotal;
            private final int[] diagonalTotal;
    
            private Referee(int size) {
                gridSize = size;
                rowTotal = new int[size];
                colTotal = new int[size];
                diagonalTotal = new int[NO_OF_DIAGONALS];
            }
    
            private String isGameOver(int x, int y, char symbol, int moveCount) {
                if (isWinningMove(x, y, symbol))
                    return symbol + " won the game!";
                if (isBoardCompletelyFilled(moveCount))
                    return "Its a Draw!";
                return "continue";
            }
    
            private boolean isBoardCompletelyFilled(int moveCount) {
                return moveCount == gridSize * gridSize;
            }
    
            private boolean isWinningMove(int x, int y, char symbol) {
                if (isPrincipalDiagonal(x, y) && allSymbolsMatch(symbol, diagonalTotal, PRINCIPAL))
                    return true;
                if (isMinorDiagonal(x, y) && allSymbolsMatch(symbol, diagonalTotal, MINOR))
                    return true;
                return allSymbolsMatch(symbol, rowTotal, x) || allSymbolsMatch(symbol, colTotal, y);
            }
    
            private boolean allSymbolsMatch(char symbol, int[] total, int index) {
                total[index] += symbol;
                return total[index] / gridSize == symbol;
            }
    
            private boolean isPrincipalDiagonal(int x, int y) {
                return x == y;
            }
    
            private boolean isMinorDiagonal(int x, int y) {
                return x + y == gridSize - 1;
            }
        }
    }
    
    import static com.agilefaqs.tdd.demo.TicTacToe.BLANK;
    import static org.junit.Assert.assertArrayEquals;
    import static org.junit.Assert.assertEquals;
    
    import org.junit.Test;
    
    public class TicTacToeTest {
        private TicTacToe game = new TicTacToe(3);
    
        @Test
        public void allCellsAreEmptyInANewGame() {
            assertBoardIs(new char[][] { { BLANK, BLANK, BLANK },
                    { BLANK, BLANK, BLANK },
                    { BLANK, BLANK, BLANK } });
        }
    
        @Test(expected = IllegalArgumentException.class)
        public void boardHasToBeMinimum3x3Grid() {
            new TicTacToe(2);
        }
    
        @Test
        public void firstPlayersMoveMarks_X_OnTheBoard() {
            assertEquals("continue", game.move(1, 1));
            assertBoardIs(new char[][] { { BLANK, BLANK, BLANK },
                    { BLANK, 'X', BLANK },
                    { BLANK, BLANK, BLANK } });
        }
    
        @Test
        public void secondPlayersMoveMarks_O_OnTheBoard() {
            game.move(1, 1);
            assertEquals("continue", game.move(2, 2));
            assertBoardIs(new char[][] { { BLANK, BLANK, BLANK },
                    { BLANK, 'X', BLANK },
                    { BLANK, BLANK, 'O' } });
        }
    
        @Test
        public void playerCanOnlyMoveToAnEmptyCell() {
            game.move(1, 1);
            assertEquals("(1,1) is already occupied", game.move(1, 1));
        }
    
        @Test
        public void firstPlayerWithAllSymbolsInOneRowWins() {
            game.move(0, 0);
            game.move(1, 0);
            game.move(0, 1);
            game.move(2, 1);
            assertEquals("X won the game!", game.move(0, 2));
        }
    
        @Test
        public void firstPlayerWithAllSymbolsInOneColumnWins() {
            game.move(1, 1);
            game.move(0, 0);
            game.move(2, 1);
            game.move(1, 0);
            game.move(2, 2);
            assertEquals("O won the game!", game.move(2, 0));
        }
    
        @Test
        public void firstPlayerWithAllSymbolsInPrincipalDiagonalWins() {
            game.move(0, 0);
            game.move(1, 0);
            game.move(1, 1);
            game.move(2, 1);
            assertEquals("X won the game!", game.move(2, 2));
        }
    
        @Test
        public void firstPlayerWithAllSymbolsInMinorDiagonalWins() {
            game.move(0, 2);
            game.move(1, 0);
            game.move(1, 1);
            game.move(2, 1);
            assertEquals("X won the game!", game.move(2, 0));
        }
    
        @Test
        public void whenAllCellsAreFilledTheGameIsADraw() {
            game.move(0, 2);
            game.move(1, 1);
            game.move(1, 0);
            game.move(2, 1);
            game.move(2, 2);
            game.move(0, 0);
            game.move(0, 1);
            game.move(1, 2);
            assertEquals("Its a Draw!", game.move(2, 0));
        }
    
        private void assertBoardIs(char[][] expectedBoard) {
            assertArrayEquals(expectedBoard, game.displayBoard());
        }
    }
    
    4 9 2
    3 5 7
    8 1 6
    
    [7, 0, 0, 4, 3, 0, 4, 0];
    
    X . .
    X . .
    . . .
    
    get_winning_move = function() {
      for (var i = 0, i < scores.length; i++) {
        // keep track of the number of times pieces were added to the row
        // subtract when the opposite team adds a piece
        if (scores[i].inc === 2) {
          return 15 - state[i].val; // 8
        }
      }
    }
    
    /*
     * Determines if the last move resulted in a win for either player
     * board: is an array representing the board
     * lastMove: is the boardIndex of the last (most recent) move
     *  these are the boardIndexes:
     *
     *   0 | 1 | 2
     *  ---+---+---
     *   3 | 4 | 5
     *  ---+---+---
     *   6 | 7 | 8
     * 
     * returns true if there was a win
     */
    var winLines = [
        [[1, 2], [4, 8], [3, 6]],
        [[0, 2], [4, 7]],
        [[0, 1], [4, 6], [5, 8]],
        [[4, 5], [0, 6]],
        [[3, 5], [0, 8], [2, 6], [1, 7]],
        [[3, 4], [2, 8]],
        [[7, 8], [2, 4], [0, 3]],
        [[6, 8], [1, 4]],
        [[6, 7], [0, 4], [2, 5]]
    ];
    function isWinningMove(board, lastMove) {
        var player = board[lastMove];
        for (var i = 0; i < winLines[lastMove].length; i++) {
            var line = winLines[lastMove][i];
            if(player === board[line[0]] && player === board[line[1]]) {
                return true;
            }
        }
        return false;
    }
    
    private int[] board = new int[9];
    private static final int[] START = new int[] { 0, 3, 6, 0, 1, 2, 0, 2 };
    private static final int[] INCR  = new int[] { 1, 1, 1, 3, 3, 3, 4, 2 };
    private static int SIZE = 3;
    /**
     * Determines if there is a winner in tic-tac-toe board.
     * @return {@code 0} for draw, {@code 1} for 'X', {@code -1} for 'Y'
     */
    public int hasWinner() {
        for (int i = 0; i < START.length; i++) {
            int sum = 0;
            for (int j = 0; j < SIZE; j++) {
                sum += board[START[i] + j * INCR[i]];
            }
            if (Math.abs(sum) == SIZE) {
                return sum / SIZE;
            }
        }
        return 0;
    }
    
    +-----------------+ | 2^0 | 2^1 | 2^2 | |-----------------| | 2^3 | 2^4 | 2^5 | |-----------------| | 2^6 | 2^7 | 2^8 | +-----------------+ +-----------+ | X | O | X | |-----------| | O | X | | |-----------| | | O | | +-----------+ 0 1 2 3 4 5 6 7 8 X: 1 0 1 0 1 0 0 0 0 O: 0 1 0 1 0 0 0 1 0
    boolean isWinner(short X) {
        for (int i = 0; i < 8; i++)
            if ((X & winCombinations[i]) == winCombinations[i])
                return true;
        return false;
    }
    
    X: 111001010 W: 111000000 // win position, all same across first row. ------------ &: 111000000
    short[] winCombinations = new short[] {
      // each row
      0b000000111,
      0b000111000,
      0b111000000,
      // each column
      0b100100100,
      0b010010010,
      0b001001001,
      // each diagonal
      0b100010001,
      0b001010100
    };
    
    for (short X = 0; X < (Math.pow(2,9) - 1); X++)
       System.out.println(isWinner(X));
    
        public class Game() { 
    
        Game player1 = new Game('x');
        Game player2 = new Game('o');
    
        char piece;
    
        Game(char piece) {
           this.piece = piece;
        }
    
    public void checkWin(Game player) {
    
        // check horizontal win
        for (int i = 0; i <= 6; i += 3) {
    
            if (board[i] == player.piece &&
                    board[i + 1] == player.piece &&
                    board[i + 2] == player.piece)
                endGame(player);
        }
    
        // check vertical win
        for (int i = 0; i <= 2; i++) {
    
            if (board[i] == player.piece &&
                    board[i + 3] == player.piece &&
                    board[i + 6] == player.piece)
                endGame(player);
        }
    
        // check diagonal win
        if ((board[0] == player.piece &&
                board[4] == player.piece &&
                board[8] == player.piece) ||
                board[2] == player.piece &&
                board[4] == player.piece &&
                board[6] == player.piece)
            endGame(player);
        }
    
    public static boolean checkWin(char symb) {
      int SIZE = 5;
    
            for (int i = 0; i < SIZE-1; i++) {
                for (int j = 0; j <SIZE-1 ; j++) {
                    //vertical checking
                if (map[0][j] == symb && map[1][j] == symb && map[2][j] == symb && map[3][j] == symb && map[4][j] == symb) return true;      // j=0
                }
                //horisontal checking
                if(map[i][0] == symb && map[i][1] == symb && map[i][2] == symb && map[i][3] == symb && map[i][4] == symb) return true;  // i=0
            }
            //diagonal checking (5*5)
            if (map[0][0] == symb && map[1][1] == symb && map[2][2] == symb && map[3][3] == symb && map[4][4] == symb) return true;
            if (map[4][0] == symb && map[3][1] == symb && map[2][2] == symb && map[1][3] == symb && map[0][4] == symb) return true;
    
            return false; 
            }
    
    private static final int dimension = 3;
    private static final int[][] board = new int[dimension][dimension];
    private static final int xwins = dimension * 1;
    private static final int owins = dimension * -1;
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int count = 0;
        boolean keepPlaying = true;
        boolean xsTurn = true;
        while (keepPlaying) {
            xsTurn = (count % 2 == 0);
            System.out.print("Enter i-j in the format:");
            if (xsTurn) {
                System.out.println(" X plays: ");
            } else {
                System.out.println(" O plays: ");
            }
            String result = null;
            while (result == null) {
                result = parseInput(scanner, xsTurn);
            }
            String[] xy = result.split(",");
            int x = Integer.parseInt(xy[0]);
            int y = Integer.parseInt(xy[1]);
            keepPlaying = makeMove(xsTurn, x, y);
            count++;
        }
        if (xsTurn) {
            System.out.print("X");
        } else {
            System.out.print("O");
        }
        System.out.println(" WON");
        printArrayBoard(board);
    }
    
    private static String parseInput(Scanner scanner, boolean xsTurn) {
        String line = scanner.nextLine();
        String[] values = line.split("-");
        int x = Integer.parseInt(values[0]);
        int y = Integer.parseInt(values[1]);
        boolean alreadyPlayed = alreadyPlayed(x, y);
        String result = null;
        if (alreadyPlayed) {
            System.out.println("Already played in this x-y. Retry");
        } else {
            result = "" + x + "," + y;
        }
        return result;
    }
    
    private static boolean alreadyPlayed(int x, int y) {
        System.out.println("x-y: " + x + "-" + y + " board[x][y]: " + board[x][y]);
        if (board[x][y] != 0) {
            return true;
        }
        return false;
    }
    
    private static void printArrayBoard(int[][] board) {
        for (int i = 0; i < dimension; i++) {
            int[] height = board[i];
            for (int j = 0; j < dimension; j++) {
                System.out.print(height[j] + " ");
            }
            System.out.println();
        }
    }
    
    private static boolean makeMove(boolean xo, int x, int y) {
        if (xo) {
            board[x][y] = 1;
        } else {
            board[x][y] = -1;
        }
        boolean didWin = checkBoard();
        if (didWin) {
            System.out.println("keep playing");
        }
        return didWin;
    }
    
    private static boolean checkBoard() {
        //check horizontal
        int[] horizontalTotal = new int[dimension];
        for (int i = 0; i < dimension; i++) {
            int[] height = board[i];
            int total = 0;
            for (int j = 0; j < dimension; j++) {
                total += height[j];
            }
            horizontalTotal[i] = total;
        }
        for (int a = 0; a < horizontalTotal.length; a++) {
            if (horizontalTotal[a] == xwins || horizontalTotal[a] == owins) {
                System.out.println("horizontal");
                return false;
            }
        }
        //check vertical
        int[] verticalTotal = new int[dimension];
    
        for (int j = 0; j < dimension; j++) {
            int total = 0;
            for (int i = 0; i < dimension; i++) {
                total += board[i][j];
            }
            verticalTotal[j] = total;
        }
        for (int a = 0; a < verticalTotal.length; a++) {
            if (verticalTotal[a] == xwins || verticalTotal[a] == owins) {
                System.out.println("vertical");
                return false;
            }
        }
        //check diagonal
        int total1 = 0;
        int total2 = 0;
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                if (i == j) {
                    total1 += board[i][j];
                }
                if (i == (dimension - 1 - j)) {
                    total2 += board[i][j];
                }
            }
        }
        if (total1 == xwins || total1 == owins) {
            System.out.println("diagonal 1");
            return false;
        }
        if (total2 == xwins || total2 == owins) {
            System.out.println("diagonal 2");
            return false;
        }
        return true;
    }
    
    private boolean validateWinner(int x, int y, int player) {
        //same col
        int low = x-winnerPos-1;
        int high = low;
        while(high <= x+winnerPos-1) {
            if(isValidPos(high, y) && isFilledPos(high, y, player)) {
                high++;
                if(high - low == winnerPos) {
                    return true;
                }
            } else {
                low = high + 1;
                high = low;
            }
        }
    
        //same row
        low = y-winnerPos-1;
        high = low;
        while(high <= y+winnerPos-1) {
            if(isValidPos(x, high) && isFilledPos(x, high, player)) {
                high++;
                if(high - low == winnerPos) {
                    return true;
                }
            } else {
                low = high + 1;
                high = low;
            }
        }
        if(high - low == winnerPos) {
            return true;
        }
    
        //diagonal 1
        int lowY = y-winnerPos-1;
        int highY = lowY;
        int lowX = x-winnerPos-1;
        int highX = lowX;
        while(highX <= x+winnerPos-1 && highY <= y+winnerPos-1) {
            if(isValidPos(highX, highY) && isFilledPos(highX, highY, player)) {
                highX++;
                highY++;
                if(highX - lowX == winnerPos) {
                    return true;
                }
            } else {
                lowX = highX + 1;
                lowY = highY + 1;
                highX = lowX;
                highY = lowY;
            }
        }
    
        //diagonal 2
        lowY = y+winnerPos-1;
        highY = lowY;
        lowX = x-winnerPos+1;
        highX = lowX;
        while(highX <= x+winnerPos-1 && highY <= y+winnerPos-1) {
            if(isValidPos(highX, highY) && isFilledPos(highX, highY, player)) {
                highX++;
                highY--;
                if(highX - lowX == winnerPos) {
                    return true;
                }
            } else {
                lowX = highX + 1;
                lowY = highY + 1;
                highX = lowX;
                highY = lowY;
            }
        }
        if(highX - lowX == winnerPos) {
            return true;
        }
        return false;
    }
    
    private boolean isValidPos(int x, int y) {
        return x >= 0 && x < row && y >= 0 && y< col;
    }
    public boolean isFilledPos(int x, int y, int p) throws IndexOutOfBoundsException {
        return arena[x][y] == p;
    }
    
    getWin(x,y,value,searchvector) {
    if (arguments.length==2) {
      var checkTurn = this.state.squares[y][x];
      var searchdirections = [[-1,-1],[0,-1],[1,-1],[-1,0]];
      return searchdirections.reduce((maxinrow,searchdirection)=>Math.max(this.getWin(x,y,checkTurn,searchdirection)+this.getWin(x,y,checkTurn,[-searchdirection[0],-searchdirection[1]]),maxinrow),0);
    } else {
      if (this.state.squares[y][x]===value) {
        var result = 1;
        if (
          x+searchvector[0] >= 0 && x+searchvector[0] < 3 && 
          y+searchvector[1] >= 0 && y+searchvector[1] < 3
          ) result += this.getWin(x+searchvector[0],y+searchvector[1],value,searchvector);
        return result;
      } else {
        return 0;
      }
    }
    
    For every move:
       checkDiagonals()
       checkVerticals()
       checkHorizontals()
    
        const checkDiagonals = () => {
            if ((state[0][0] === val && state[1][1] === val && state[2][2] === val) ||
                (state[0][2] === val && state[1][1] === val && state[2][0] === val)) {
                return val;
            }
            return -1;
        }
    
        const checkVerticals = () => {
            for (let i = 0; i <= 2; i++) {
                if (state[0][i] === val && state[1][i] === val && state[2][i] === val) {
                    return val;
                }
            }
            return -1;
        }
    
        const checkHorizontals = () => {
            for (let i = 0; i <= 2; i++) {
                if (state[i][0] === val && state[i][1] === val && state[i][2] === val) {
                    return val;
                }
            }
            return -1;
        }
    
    const updateWinningPlayer = () => {
    
        const diagonals = checkDiagonals();
        const verticals = checkVerticals();
        const horizontals = checkHorizontals();
    
        if (diagonals !== -1) {
            setWinner(diagonals)
            return;
        }
    
        if (verticals !== -1) {
            setWinner(verticals);
            return;
        }
    
        if (horizontals !== -1) {
            setWinner(horizontals);
            return;
        }
    
        if (isDraw()) {
            setWinner(2);
        }
    }