Tic Tac Toe

Level: Beginner 15–30 min

Concepts: StateDesign

Solutions: C# | TypeScript | Python


Create a program to implement the classic game of Tic Tac Toe.

Requirements

  1. Implement game rules:
    • 3x3 grid game board
    • Two players (X and O)
    • Players take turns placing their mark
    • First player to get 3 in a row (horizontally, vertically, or diagonally) wins
    • Game ends in a draw if all spaces are filled with no winner
  2. Handle game state:
    • Track current player’s turn
    • Validate moves (prevent playing in occupied spaces)
    • Detect win conditions
    • Detect draw conditions
  3. Return appropriate results:
    • Current game state
    • Winner (if any)
    • Error messages for invalid moves

Test Cases

ScenarioMovesExpected ResultNotes
Empty BoardNoneGame in progressInitial state
Horizontal WinX(0,0), O(1,0), X(0,1), O(1,1), X(0,2)X winsTop row win
Vertical WinX(0,0), O(0,1), X(1,0), O(1,1), X(2,0)X winsLeft column win
Diagonal WinX(0,0), O(0,1), X(1,1), O(0,2), X(2,2)X winsTop-left to bottom-right
DrawX(0,0), O(0,1), X(0,2), O(1,0), X(1,1), O(2,0), X(1,2), O(2,2), X(2,1)DrawNo winner
Invalid MoveX(0,0), X(0,1)ErrorSame player twice

Edge Cases to Consider

  • Playing in an occupied space
  • Playing out of turn
  • Playing outside the board boundaries
  • Continuing play after game end
  • Multiple win conditions

Tips

  • Start with an empty board representation
  • Add move validation next
  • Then implement win detection
  • Finally add game state management
  • Consider using enums for player marks and game states

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/tic-tac-toe. This is an F2 (light builder) kata: one primary entity (Board), a pair of value enums (Cell, Outcome), three domain exceptions for invalid moves, and one small test-folder BoardBuilder (10–30 lines) whose chained .withXAt(r,c) and .withOAt(r,c) calls read as a direct literal of the board state under test.

Scope note — pure domain only. The reference covers placing marks, turn tracking, win/draw detection, and invalid-move rejection. Rendering (ASCII board, HTML view), a CLI loop, a computer opponent, move history/undo, and n-in-a-row generalisation are all out of scope and listed as stretch goals in the repo README. Those responsibilities introduce collaborators (renderers, input parsers, strategy interfaces) — which is F3 territory, not F2.

This kata ships in Agent Full-Bake mode at middle gear, the F2 (light builder) tier. See the repo’s Gears section for why middle gear is the deliberate choice.