Wednesday, October 24, 2012

Algorithm for Determining Tic Tac Toe Game Over


In Tic-Tac-Toe of any size for every move it is always for some row and some column and in addition it may or may not be for particular diagonal, and this is fact we are going to use for designing our algorithm.

Algorithm:
Initialize row, col and diagonal Score to 0 for size n.
Maintain score for each player different.
For every move of [row,col]
1. Update the score by 1 for given row if new score is = n declare player as winner
2. Update the score by 1 for given col if new score is = n declare player as winner
3. If move is for diagonal 1 update the score by 1 for diagonal 1 if new score is = n declare player as winner.
4. If move is for diagonal 2 update the score by 1 for diagonal 2 if new score is = n declare player as winner.
--------------------------------------------------------------------------------------------------------
/**
 * This class is to determine winner in game of TicTacToe.
 */
public class TicTacToe
{
/**
* Class to keep track of score for a player.
*/
 private class Score
 {
/** Size of TicTacToe Board.*/
  int _size;
  /** Array for row score.*/
  int[] _rowsScore;
  /** Array for colmun score.*/
  int[] _colsScore;
  /** Array for diagonal score.*/
  int[] _diagsScore = new int[2];

  /**
   * Constructor.
   * @param size Size of the board.
   */
  public Score(int size)
  {
   _size = size;
   _rowsScore = new int[_size];
   _colsScore = new int[_size];
  }

  /**
   * Update the score with given move.
   * @param row Row value.
   * @param col Column value.
   * @return Returns true if player is the winner else false.
   */
  public boolean updateScore(int row, int col)
  {
 // Every move has to be for one row as well as col
 // Check the row.
   if (++_rowsScore[row] == _size)
    return true;
   // Check the col.
   if (++_colsScore[col] == _size)
    return true;
   // Check for diagonal 1
   if (row == col)
   {
    if (++_diagsScore[0] == _size)
     return true;
   }
   // Check for diagonal 1
   for (int i = 0 ; i < _size; i++)
   {
    if (row == i && col == (_size -1 -i))
     if (++_diagsScore[1] == _size)
      return true;
   }
   return false;
  }
 }

 /** Score for player 1.**/
 private Score _player1;
 /** Score for player 2.**/
 private Score _player2;

 /**
  * Constructor.
  * @param size Size of the board.
  */
 public TicTacToe(int size)
 {
  _player1 = new Score(size);
  _player2 = new Score(size);
 }

 /**
  * Function for player 1 move.
  * @param row Row of move.
  * @param col Col of move.
  * @return True if Player 1 is winner for this move else false.
  */
 public boolean movePlayer1(int row, int col)
 {
  System.out.println("Moving player 1  row " + row + " column " + col);
  return _player1.updateScore(row, col);
 }

 /**
  * Function for player 2 move.
  * @param row Row of move.
  * @param col Col of move.
  * @return True if Player 2 is winner for this move else false.
  */
 public boolean movePlayer2(int row, int col)
 {
  System.out.println("Moving player 2  row " + row + " column " + col);
  return _player2.updateScore(row, col);
 }

 /**
  * @param args
  */
 public static void main(String[] args)
 {
  TicTacToe play = new TicTacToe(3);
  System.out.println(play.movePlayer1(1, 1));
  System.out.println(play.movePlayer2(0, 0));
  System.out.println(play.movePlayer1(1, 2));
  System.out.println(play.movePlayer2(1, 0));
  System.out.println(play.movePlayer1(2, 2));
  System.out.println(play.movePlayer2(2, 0));


 }
}
--------------------------------------------------------------------------------------------------------
For every move just call the respective move for the player and check the result if it's true that player is winner.

2 comments:

Naresh said...

Interesting solution. I was wondering why you need to maintain each player's score separately. Here is my solution: https://github.com/nashjain/tictactoe/blob/master/java/src/com/agilefaqs/tdd/demo/TicTacToe.java

Best of Best said...

Thank you Naresh for the updated solution looks good.