Course content
Design Tic-Tac-Toe
Easy·Tagsstate-patterngame-designencapsulation
Problem Statement
Design a 3x3 Tic-Tac-Toe game.
Implement the `TicTacToe` class with two public methods: `move(row, col, player)` and `getStatus()`.
Rules
- The board is 3x3. Rows and columns are 0-indexed.
- `player` is the string `"X"` or `"O"`.
- A player wins by placing three of their marks in a row (horizontally, vertically, or diagonally).
- A draw is declared when all nine cells are filled and no player has won.
`move(int row, int col, String player)`
- Places `player`'s mark at `(row, col)`.
- Throws `IllegalStateException` if the move is invalid:
- Coordinates outside the 3x3 board.
- The cell is already occupied.
- The game is already over (someone has won, or the board is a draw).
`getStatus()` returns one of:
- `"X"` — X has won.
- `"O"` — O has won.
- `"DRAW"` — board is full with no winner.
- `"IN_PROGRESS"` — game is still ongoing.
The goal is not just correctness — your design will be judged on encapsulation (callers should not be able to mutate internal state), clear separation of concerns (move validation vs. status detection), and how cleanly you express the four mutually exclusive game states. The State pattern is a natural fit, but a simpler design that satisfies the contract is also acceptable.
Examples
Example 1
Input
move(0,0,"X"); move(0,1,"O"); move(1,1,"X"); move(1,0,"O"); move(2,2,"X"); getStatus()Output
"\"X\""Why
X plays the top-left/middle/bottom-right diagonal and wins. getStatus() returns "X".
Example 2
Input
new TicTacToe(); getStatus()Output
"\"IN_PROGRESS\""Why
A fresh board with no moves is in progress.
Example 3
Input
move(0,0,"X"); move(0,0,"O")Output
"throws IllegalStateException"Why
(0,0) is already occupied by X. The second move must reject it.
Constraints
- •0 <= row, col <= 2
- •player is exactly "X" or "O"
- •All operations are sequential (no concurrency required for v1)
Hints
Stuck? Reveal a nudge toward the right pattern, one step at a time.
Hint 1
Represent the board as a `String[3][3]` (or `char[3][3]`); null/space means empty.
Hint 2
After each move, check the 3 row sums, 3 column sums, and 2 diagonals for three-in-a-row. Cache the winner so getStatus() doesn't recompute every call.
Hint 3
Track move count separately from scanning the board — it makes draw detection O(1).
Hint 4
Validate inputs early in `move()`: bounds, occupancy, and game-over check should each throw IllegalStateException with a distinct message.
Hint 5
For a textbook State pattern: model each game state (InProgress, Won, Draw) as its own class implementing a `GameState` interface. For an interview answer, a single class with a status field is also fine — be ready to defend the trade-off.