Snake Game
Level: Advanced 60–90 minConcepts: StateAlgorithmsBoundariesEdge Cases
Solutions: C# | TypeScript | Python
Implement the game logic for the classic Snake game. No UI required — focus on the rules, state transitions, and collision detection.
Requirements
The game takes place on a rectangular grid of configurable size (e.g. 10x10).
The Snake
- The snake starts at position
(0, 0)moving right, with a length of 1 - The snake moves one cell per tick in its current direction
- Valid directions: Up, Down, Left, Right
- The snake cannot reverse direction (e.g. moving Right cannot change to Left)
Movement
Each tick:
- The snake moves one cell in its current direction
- If the new head position contains food, the snake grows by 1 (tail doesn’t move)
- If the new head position is empty, the snake moves (tail follows)
- If the new head position is a wall or the snake’s own body, the game is over
Food
- One piece of food exists on the grid at a time
- When the snake eats food, a new piece of food appears at a random empty cell
- Food cannot spawn on the snake’s body
- Accept an injectable random source for testability
Scoring
- Each food eaten scores 1 point
- The game tracks the current score
Grid
- The grid has walls on all four edges
- The snake wraps around OR dies at walls (choose one and document it)
Test Cases
| Scenario | Setup | Action | Result |
|---|---|---|---|
| Initial state | New game 5x5 | — | Snake at (0,0), length 1, moving right |
| Move right | Snake at (0,0) | tick | Snake at (1,0) |
| Move down | Snake at (0,0), direction Down | tick | Snake at (0,1) |
| Eat food | Snake at (0,0), food at (1,0) | tick | Snake length 2, score 1 |
| Grow correctly | Snake [(0,0)], food at (1,0) | tick | Snake [(1,0),(0,0)] |
| Hit wall | Snake at (4,0) moving right, 5x5 grid | tick | Game over |
| Hit self | Snake [(3,0),(2,0),(1,0),(0,0)], direction Down then Left then Up | tick x3 | Game over (hits own body) |
| Cannot reverse | Moving right | change direction Left | Direction stays Right |
| Food respawns | Snake eats food | — | New food at random empty cell |
Bonus
- Implement wall-wrapping as an alternative to wall-death (configurable)
- Add speed levels — the snake moves faster as the score increases
- Add obstacles — static blocks on the grid that kill the snake on contact
- Track high scores across multiple games
Hint
Represent the snake as a list of coordinates (head first). Movement is: prepend the new head position, remove the tail (unless eating). This makes growth trivial — just skip the tail removal. Test the movement logic before adding food or collisions.
Reference Walkthrough
Full C#, TypeScript, and Python implementations live at tddbuddy-reference-katas/snake-game. Twenty-three scenarios across initial state, basic movement, direction changes, eating food, wall collisions, self collision, game-over behavior, and winning — shared across all three languages — with a mutable Game aggregate backed by an immutable Snake (head-first body list), Position value type, Direction enum, and injectable FoodSpawner for deterministic testing. BoardBuilder and SnakeBuilder make test setup readable.
- C# (.NET 8, xUnit, FluentAssertions) — walkthrough
- TypeScript (Node 20, Vitest, strict types) — walkthrough
- Python (3.11, pytest, frozen dataclass, Enum) — walkthrough
This kata ships in Agent Full-Bake (F3) mode: one commit per language with the full domain design landing together. The walkthroughs read as design rationale — why the snake is a head-first list (movement = prepend head, optionally pop tail), why Snake.Move() returns a new instance (collision detection reads pre-move state), why FoodSpawner is a function not an interface (single-method collaborator), why direction reversal is silently ignored rather than throwing (spec says “direction stays”). The reference chooses wall-death over wall-wrapping; bonus items (wrapping, speed levels, obstacles) are deliberately out of scope. See the repo’s Gears section for when middle gear is the right call.