PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

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.

  • hard
  • Databricks
  • Coding & Algorithms
  • Software Engineer

Implement an Alternating Tic-Tac-Toe Game

Company: Databricks

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: hard

Interview Round: Technical Screen

Implement a Tic-Tac-Toe game for two players. Requirements: 1. The board is a standard 3 x 3 grid. 2. Players do not need to be passed into each move. Instead, players alternate automatically: - The first call to `play()` is made by Player 1. - The second call to `play()` is made by Player 2. - The third call is Player 1 again, and so on. 3. After each valid move, print or return the current board in a clear, consistent format. 4. If a player wins after a move, output `Player X won`, where `X` is the winning player number. 5. If the board is full and nobody has won, report a draw. 6. Invalid moves, such as playing outside the board or on an occupied cell, should be handled gracefully. 7. Write your own test cases covering normal play, wins by row, column, diagonal, draw, and invalid moves. Follow-up: Design an automated player that chooses random valid moves. Simulate a full game where the automated player keeps making random valid moves until the game ends with a win or a draw.

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

Implement a 3 x 3 Tic-Tac-Toe game processor. You are given a list of attempted moves. Player 1 moves first, Player 2 moves second, and turns alternate after each valid move. Invalid moves do not change the board and do not advance the turn. After every attempted move, return a snapshot containing a status message and the current board. Stop changing the board after a win or draw; any later attempted moves should return a game-over snapshot.

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

  1. Track the current player internally and flip it only after a valid non-terminal move.
  2. 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

Simulate a full 3 x 3 Tic-Tac-Toe game where the current player is controlled by an automated random-move chooser. Player 1 moves first and players alternate automatically. To make the random behavior testable, the random source is provided as a list of integers. On each turn, list all currently valid empty cells in row-major order, choose index random_values[turn] % number_of_valid_cells, and place the current player's mark there. If random_values is exhausted, use 0 for all remaining turns. Continue until a player wins or the board is full.

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

  1. Generate the list of empty cells fresh on every turn; its size changes after each move.
  2. Using modulo lets any random integer map to one of the currently valid moves.
Last updated: Jun 19, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Choose the Best Travel Mode - Databricks (medium)
  • Implement a Snapshot Set Iterator - Databricks (medium)
  • Find the Best Commute Mode - Databricks (medium)
  • Partition a Target String by Source Substrings - Databricks (medium)
  • Design In-Memory QPS Counter - Databricks (medium)