Snake and Ladder
Design a multiplayer Snake and Ladder game: a board of 100 cells with snakes and ladders, two or more players taking turns rolling a die, and a winner who lands exactly on the last cell.
Clarifying Questions
- Is the board always 10 by 10, or configurable?
- Must a player land exactly on 100, or does overshooting win?
- Does rolling a six grant an extra turn, and do three sixes forfeit it?
- One die or several?
- Does the game end at the first winner, or continue to rank everyone?
Core Requirements
- Configure a board size with snakes and ladders at given cells.
- Validate the board: no cycles, no jump from the last cell, and at most one jump per cell.
- Rotate turns among players and roll the die.
- Move a player and apply any snake or ladder at the landing cell.
- Enforce the exact-finish rule and declare the winner.
- Log each move for replay.
Canonical class breakdown
Game: Owns the Board, the Player queue, the Dice, and the game status; runs the turn loop.
Board: Holds the size and a map from start cell to Jump; returns the final cell for any landing position.
Jump / Snake, Ladder: A start and end cell; a snake goes down and a ladder goes up, validated at construction.
Player: Name and current position.
Dice (interface): Returns a roll; a seeded implementation makes tests and replays deterministic.
TurnPolicy: Encodes rules like an extra turn on six and the exact finish, kept apart from the turn loop.
MoveRecord: Immutable log entry of player, roll, from cell, and to cell.
Java sketchjava
// Java skeleton
enum GameStatus { NOT_STARTED, IN_PROGRESS, FINISHED }
abstract class Jump {
protected final int start;
protected final int end;
}
class Snake extends Jump { /* constructor requires end < start */ }
class Ladder extends Jump { /* constructor requires end > start */ }
class Board {
private final int size;
private final Map<Integer, Jump> jumpsByStart;
public Board(int size, List<Jump> jumps) { /* validate: one jump per cell, none from the last cell, no cycles */ }
public int resolve(int landing) { ... }
public int lastCell() { return size; }
}
class Player {
private final String name;
private int position;
}
interface Dice {
int roll();
}
class SeededDice implements Dice {
private final Random random;
public SeededDice(long seed) { this.random = new Random(seed); }
public int roll() { return random.nextInt(6) + 1; }
}
interface TurnPolicy {
int nextPosition(int current, int roll, Board board); // exact-finish rule
boolean grantsExtraTurn(int roll, int consecutiveSixes);
}
record MoveRecord(String player, int roll, int from, int to) {}
class Game {
private final Board board;
private final Deque<Player> turnOrder;
private final Dice dice;
private final TurnPolicy policy;
private final List<MoveRecord> history;
private GameStatus status;
private Player winner;
public MoveRecord playTurn() { ... }
public Player play() { /* loop until a player reaches the last cell */ }
}
Key Decisions to Defend
- Snakes and ladders are both a Jump with a start and an end, so the board resolves a landing with one map lookup.
- Board validation runs once at construction, so the turn loop can trust the board.
- Dice is an interface with a seeded implementation, which keeps tests deterministic.
- Players sit in a queue; the current player is dequeued and re-enqueued unless they win.
- House rules live in TurnPolicy, so a variant game swaps one class.
Likely follow-ups
- · Add a rule where a snake bite sends you back to the start, where does it go?
- · Simulate 10,000 games to estimate the average game length.
- · Allow chained jumps where a ladder lands on another ladder, does validation change?
Dive Deeper
Snake and Ladder is an entry-level design question that rewards clean modeling. The signals are a single Jump abstraction covering both snakes and ladders, validation at construction, and an injectable Dice. Candidates who call a random number generator directly inside the turn loop can't write a deterministic test, and interviewers often ask for one next.