Implement an Alternating Tic-Tac-Toe Game
Company: Databricks
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Technical Screen
Quick Answer: This question evaluates a candidate's ability to implement state management, alternating turn logic, input validation, board representation, game outcome detection, and test case design for a turn-based 3x3 Tic-Tac-Toe game.
Part 1: Alternating Two-Player Tic-Tac-Toe
Constraints
- The board is always exactly 3 x 3.
- 0 <= len(moves) <= 100.
- Each move should be treated as an attempted (row, col) coordinate.
- Invalid moves do not alter the board and do not switch the current player.
- Once a player wins or the game is a draw, later moves do not alter the board.
Examples
Input: ([(0, 0), (0, 0), (3, 0), (1, 0), (0, 1), (1, 1), (0, 2), (2, 2)],)
Expected Output: ['Player 1 moved|1../.../...', 'Invalid move|1../.../...', 'Invalid move|1../.../...', 'Player 2 moved|1../2../...', 'Player 1 moved|11./2../...', 'Player 2 moved|11./22./...', 'Player 1 won|111/22./...', 'Game already over|111/22./...']
Explanation: Player 1 starts. Two invalid attempts do not switch turns. Player 1 eventually completes the top row, and the later move is ignored because the game is over.
Input: ([(0, 1), (0, 0), (1, 1), (1, 0), (2, 2), (2, 0)],)
Expected Output: ['Player 1 moved|.1./.../...', 'Player 2 moved|21./.../...', 'Player 1 moved|21./.1./...', 'Player 2 moved|21./21./...', 'Player 1 moved|21./21./..1', 'Player 2 won|21./21./2.1']
Explanation: Player 2 wins by filling column 0.
Input: ([(0, 0), (0, 1), (1, 1), (0, 2), (2, 2)],)
Expected Output: ['Player 1 moved|1../.../...', 'Player 2 moved|12./.../...', 'Player 1 moved|12./.1./...', 'Player 2 moved|122/.1./...', 'Player 1 won|122/.1./..1']
Explanation: Player 1 wins on the main diagonal.
Input: ([(0, 0), (0, 1), (0, 2), (1, 1), (1, 0), (1, 2), (2, 1), (2, 0), (2, 2)],)
Expected Output: ['Player 1 moved|1../.../...', 'Player 2 moved|12./.../...', 'Player 1 moved|121/.../...', 'Player 2 moved|121/.2./...', 'Player 1 moved|121/12./...', 'Player 2 moved|121/122/...', 'Player 1 moved|121/122/.1.', 'Player 2 moved|121/122/21.', 'Draw|121/122/211']
Explanation: All 9 cells are filled and neither player has three in a row.
Input: ([],)
Expected Output: []
Explanation: Edge case: no attempted moves produce no snapshots.
Hints
- Track the current player internally and flip it only after a valid non-terminal move.
- After each valid placement, check the three rows, three columns, and two diagonals for a win.
Part 2: Automated Random-Move Tic-Tac-Toe Simulation
Constraints
- The board is always exactly 3 x 3.
- 0 <= len(random_values) <= 100.
- 0 <= random_values[i] <= 10^9.
- At most 9 automated moves are made because each move fills one cell.
- Extra random values after the game ends are ignored.
Examples
Input: ([],)
Expected Output: ['Player 1 moved|1../.../...', 'Player 2 moved|12./.../...', 'Player 1 moved|121/.../...', 'Player 2 moved|121/2../...', 'Player 1 moved|121/21./...', 'Player 2 moved|121/212/...', 'Player 1 won|121/212/1..']
Explanation: Edge case: with no supplied random values, the chooser always uses 0, so it repeatedly chooses the first available cell.
Input: ([0, 0, 2, 0, 4],)
Expected Output: ['Player 1 moved|1../.../...', 'Player 2 moved|12./.../...', 'Player 1 moved|12./.1./...', 'Player 2 moved|122/.1./...', 'Player 1 won|122/.1./..1']
Explanation: The supplied choices lead Player 1 to occupy the main diagonal.
Input: ([1, 0, 2, 1, 4, 2],)
Expected Output: ['Player 1 moved|.1./.../...', 'Player 2 moved|21./.../...', 'Player 1 moved|21./.1./...', 'Player 2 moved|21./21./...', 'Player 1 moved|21./21./..1', 'Player 2 won|21./21./2.1']
Explanation: The automated choices lead Player 2 to fill column 0.
Input: ([0, 0, 0, 1, 0, 0, 1, 0, 0],)
Expected Output: ['Player 1 moved|1../.../...', 'Player 2 moved|12./.../...', 'Player 1 moved|121/.../...', 'Player 2 moved|121/.2./...', 'Player 1 moved|121/12./...', 'Player 2 moved|121/122/...', 'Player 1 moved|121/122/.1.', 'Player 2 moved|121/122/21.', 'Draw|121/122/211']
Explanation: The game fills all cells without a winning row, column, or diagonal.
Hints
- Generate the list of empty cells fresh on every turn; its size changes after each move.
- Using modulo lets any random integer map to one of the currently valid moves.