Ninja is bored and hence started playing tic tac toe with his friend. As always he started losing the game. So he approaches you to find the optimal move he needs to play at a given moment so that he can defeat his friend.
You are given the current state of the game with a 3x3 grid, of which some squares are filled with 'X', some are filled with ‘O’ and the rest are filled with ‘_’ which means that this square is empty. You need to find the best possible score our ninja can get and the position of the optimal move he should make. You always start first and your symbol is ‘X’. The scores are assigned as follows:
Win: 1
Draw : 0
Lose : -1
For Example:Suppose the board looks as follows:
X O X
O O X
_ _ _
We can see that if we put X at positions 3, 3 in the grid we win straightaway. Hence the best possible score is 1 (Win). If we put our symbol anywhere else we will not be able to achieve the desired score.
Note :
If there are multiple positions leading to the same score, choose the position with the minimum row. If there are still multiple positions, choose the one with the minimum column.
Each input is described by 3 lines each of which is a string of 3 characters denoting the state of that row of the grid.
Output Format:
Output 3 integers - the maximum score, the row and the column of the optimal move.
Note:
You are not required to print anything; it has already been taken care of. Just implement the function.
The size of the grid will always be 3.
Time Limit: 1 sec.
X O X
O O X
_ _ _
1 3 3
The value of the best move is 1 (i.e win). This can be achieved by making a move at position 3, 3. This way the column 3 will contain all X and we will get the required score.
O _ O
_ X _
O X X
-1 1 2
Can you try to form the minimax tree for the tic tac toe game ?
We will be using the minimax algorithm to evaluate the score of the board. Our objective will be to maximize the score we can get across all possibilities, while the objective of the opponent will be to minimize the score. So at every stage we will maintain whose turn it is now, if it is ours we maximize across all the remaining states else the opponent minimizes across all possible moves on the current board.
Algorithm:
findTheWinner(board, player) finds the best score achievable and the position of the move to make.
minimax(board, turn) takes the state of the board and the player whose turn it is. It evaluates the board to check for final state (when one of the players wins or no moves are left) and returns a score based on that.
isMovesLeft(board) returns true if the board has a move left else returns false
isGameOver(board) returns 1 if you have won the game, -1 if the opponent won the game, else 0.
O((N^2)!), Where ‘N’ is the size of the board.
At every stage, if there are ‘E’ empty squares, then we branch ‘E’ times and the subspace reduces to size ‘E’ - 1.
So T(E) = E*T(E - 1) which gives T(E) = E!. Since at the beginning of the game we can have (N^2) empty squares it gives the time complexity is O((N^2)!).
O(N), Where ‘N’ is the size of the board
Since a recursion depth of size N is reached in the minimax tree.