Design Tic-Tac-Toe
Design a Tic-tac-toe game that is played between two players on a n x n grid.
You may assume the following rules:
- A move is guaranteed to be valid and is placed on an empty block.
- Once a winning condition is reached, no more moves is allowed.
- A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal row wins the game.
Example:
Given n = 3, assume that player 1 is "X" and player 2 is "O" in the board. TicTacToe toe = new TicTacToe(3); toe.move(0, 0, 1); -> Returns 0 (no one wins) |X| | | | | | | // Player 1 makes a move at (0, 0). | | | | toe.move(0, 2, 2); -> Returns 0 (no one wins) |X| |O| | | | | // Player 2 makes a move at (0, 2). | | | | toe.move(2, 2, 1); -> Returns 0 (no one wins) |X| |O| | | | | // Player 1 makes a move at (2, 2). | | |X| toe.move(1, 1, 2); -> Returns 0 (no one wins) |X| |O| | |O| | // Player 2 makes a move at (1, 1). | | |X| toe.move(2, 0, 1); -> Returns 0 (no one wins) |X| |O| | |O| | // Player 1 makes a move at (2, 0). |X| |X| toe.move(1, 0, 2); -> Returns 0 (no one wins) |X| |O| |O|O| | // Player 2 makes a move at (1, 0). |X| |X| toe.move(2, 1, 1); -> Returns 1 (player 1 wins) |X| |O| |O|O| | // Player 1 makes a move at (2, 1). |X|X|X|
Follow up:
Could you do better than O(n2) per move()
operation?
Hint:
- Could you trade extra space such that
move()
operation can be done in O(1)? - You need two arrays: int rows[n], int cols[n], plus two variables: diagonal, anti_diagonal.
-
1 public class TicTacToe { 2 int rows[]; 3 int cols[]; 4 int diagonal; 5 int antiDiagonal; 6 int n; 7 8 /** Initialize your data structure here. */ 9 public TicTacToe(int n) { 10 rows = new int[n]; 11 cols = new int[n]; 12 for (int i = 0; i < n; i++) { 13 rows[i] = cols[i] = 0; 14 } 15 diagonal = antiDiagonal = 0; 16 this.n = n; 17 } 18 19 /** Player {player} makes a move at ({row}, {col}). 20 @param row The row of the board. 21 @param col The column of the board. 22 @param player The player, can be either 1 or 2. 23 @return The current winning condition, can be either: 24 0: No one wins. 25 1: Player 1 wins. 26 2: Player 2 wins. */ 27 public int move(int row, int col, int player) { 28 if (player == 1) { 29 if (row == col) 30 diagonal++; 31 if (row + col == n - 1) 32 antiDiagonal++; 33 rows[row]++; 34 cols[col]++; 35 36 if (diagonal == n || antiDiagonal == n || rows[row] == n || cols[col] == n) return 1; 37 } else { 38 if (row == col) 39 diagonal--; 40 if (row + col == n - 1) 41 antiDiagonal--; 42 rows[row]--; 43 cols[col]--; 44 45 if (diagonal == -n || antiDiagonal == -n || rows[row] == -n || cols[col] == -n) return 2; 46 } 47 return 0; 48 } 49 } 50 51 /** 52 * Your TicTacToe object will be instantiated and called as such: 53 * TicTacToe obj = new TicTacToe(n); 54 * int param_1 = obj.move(row,col,player); 55 */
-
1 public class TicTacToe { 2 private char[][] board; 3 private int N = 0; 4 5 /** Initialize your data structure here. */ 6 public TicTacToe(int n) { 7 board = new char[n][n]; 8 N = n; 9 } 10 11 /** Player {player} makes a move at ({row}, {col}). 12 @param row The row of the board. 13 @param col The column of the board. 14 @param player The player, can be either 1 or 2. 15 @return The current winning condition, can be either: 16 0: No one wins. 17 1: Player 1 wins. 18 2: Player 2 wins. */ 19 public int move(int row, int col, int player) { 20 // check the first player 21 if (player == 1) { 22 board[row][col] = 'X'; 23 if (checked(board, 'X')) return 1; 24 } else { 25 board[row][col] = 'O'; 26 if (checked(board, 'O')) return 2; 27 } 28 29 return 0; 30 } 31 32 private boolean checked(char[][] board, char ch) { 33 for (int i = 0; i < N; i++) { 34 for (int j = 0; j < N; j++) { 35 if (board[i][j] == ch) { 36 int count1 = 0, count2 = 0, count3 = 0, count4 = 0; 37 // check diagonal 38 if (i == 0 && j == 0) { 39 int m = i, n = j; 40 while (m < N && n < N && board[m][n] == ch) { 41 count1++; 42 m++; n++; 43 } 44 } 45 if (i == 0 && j == N - 1) { 46 int m = i, n = j; 47 while (m < N && n >= 0 && board[m][n] == ch) { 48 count2++; 49 m++; n--; 50 } 51 } 52 if (j == 0) { // check characters in a row 53 int n = j; 54 while (n < N && board[i][n] == ch) { 55 count3++; 56 n++; 57 } 58 } 59 if (i == 0) { // check characters in a column 60 int m = i; 61 while (m < N && board[m][j] == ch) { 62 count4++; 63 m++; 64 } 65 } 66 67 if (count1 == N || count2 == N || count3 == N || count4 == N) return true; 68 } 69 } 70 } 71 return false; 72 } 73 } 74 75 /** 76 * Your TicTacToe object will be instantiated and called as such: 77 * TicTacToe obj = new TicTacToe(n); 78 * int param_1 = obj.move(row,col,player); 79 */