Snake and Ladder
A board game with exactly one rule that makes it interesting: landing on certain cells teleports you somewhere else on the board. Everything else - turns, dice, winning - is bookkeeping. The design question is where that teleport rule should live.
Requirements
Functional
- The board has a fixed number of cells (typically 100), numbered from 1 to N.
- Some cells are the head of a snake (landing there sends you down to a lower cell) or the bottom of a ladder (landing there sends you up to a higher cell).
- Two or more players take turns rolling a dice and advancing their position by the roll.
- A player who reaches the last cell wins; a roll that would overshoot the last cell is simply not applied (the player stays put and passes the turn).
Non-functional
- Adding a new game variant (loaded dice, two dice, a "must roll a 6 to start" house rule) should mean swapping one component, not editing the turn loop.
- Board setup must reject an invalid snake or ladder (head below tail, or a ladder that goes down) at construction time, not three turns into a game.
Design
The whole game hinges on one decision: Snake and Ladder are configuration used only to
build the board, never referenced again once the game starts. What Game actually reads
at runtime is a single jumpTo value on each Cell - it has no idea whether that jump came
from a snake or a ladder, and it doesn't need to.
- 1The referee just asks the game to advance one turn; it never touches a player or the board directly.
- 2The current player's move count comes from whatever Dice implementation was configured.
- 3The game computes the naive new position, then asks the board for that cell.
- 4Only the cell knows if it redirects - the board and game never inspect a snake or ladder object.
- 5The player's position updates once, after any redirect is resolved.
That collapse is what keeps playTurn short: move by the roll, then ask the landing cell
"do you redirect me?" once. No branching on snake-vs-ladder anywhere in the turn logic.
Class diagram
Code
Design decisions
- Snakes and ladders unify into one
jumpTofield onCellinstead of two lookup maps checked every turn. The turn loop does not care which of the two sent a player from cell 47 to cell 12 - it only cares that it happened. Folding both into the same mechanism at board-build time means the hot path (playTurn) has one branch, not two. Diceis an interface, not a fixed die roll. Rolling is the one part of this game that interview variants love to change: two dice, a loaded die for testing, "roll again on a 6." Isolating it behindroll()means those variants are a new class, never an edit toGame.- Validation happens in the
Boardconstructor, not inplayTurn. A snake whose head is below its tail, or a ladder that goes downward, is a setup bug - catching it when the board is built means a broken configuration fails loudly on line one instead of producing a silently wrong game forty turns later. - What's missing for a real system: a cell that is simultaneously a snake head and a ladder bottom needs an explicit tie-breaking rule (this design picks whichever the board applies last, which is worth calling out rather than leaving accidental), and a real multiplayer version needs turn timeouts and a move-history log for replay - neither is needed to demonstrate the class model.