Course content
Design Snakes and Ladders
Easy·Tagsllddesignsnakes-and-laddersgame-designturn-order
Problem Statement
Design the core engine for a Snakes and Ladders game. Players take turns rolling a single die; the first player to land exactly on `boardSize` wins.
Rules
- The board has positions `0..boardSize`. Every player starts at position `0` (off-board).
- A roll of `r` (1..6) moves the current player from `pos` to `pos + r`.
- If `pos + r > boardSize` the move would overshoot — the player stays at `pos`, and the turn still rotates to the next player.
- After moving, apply at most one ladder (bottom → top) and one snake (head → tail) at the new position. Order: ladder first, then snake. (Real-world games typically have only one of the two on any given square; this rule is a deterministic tiebreaker.)
- Reaching `boardSize` exactly ends the game; the moving player is the winner. No further turns are accepted.
API contract
```java
class SnakesAndLaddersGame {
public SnakesAndLaddersGame(int boardSize, List<String> playerIds);
// Throws IllegalArgumentException if boardSize < 2 or playerIds is empty.
public void addLadder(int bottom, int top); // 0 < bottom < top < boardSize
public void addSnake(int head, int tail); // 0 < tail < head < boardSize
// Both throw IllegalArgumentException for invalid coordinates.
/** The current player rolls. Returns the player's new position after applying overshoot,
* ladders, and snakes. Throws IllegalArgumentException for diceRoll outside 1..6.
Throws IllegalStateException if the game is already over. /
public int rollAndMove(int diceRoll);
public int getPosition(String playerId);
public String getCurrentPlayer(); // whose turn it is, or null after the game ends
public String getWinner(); // null while the game is in progress
public boolean isGameOver();
}
```
The validator runs three checks:
1. basic_movement_and_turns — 2-player game on a 30-square board, no snakes or ladders. Player A rolls 5 → position 5; getCurrentPlayer is now B. B rolls 3 → position 3; getCurrentPlayer is now A. Turn order rotates correctly.
2. snakes_and_ladders_apply — adding a ladder 4→25 and a snake 28→10, a player rolling 4 from start lands at 25 (climbed the ladder). A player at 25 rolls 3 (→28) and snakes back to 10.
3. winning_and_overshoot — on a 30-square board, a player at 25 rolling 5 lands exactly on 30 and wins (`isGameOver` true, `getWinner` returns that player). A player at 28 rolling 5 would land on 33 — overshoot — and stays at 28; the turn still rotates.
The stub class throws `UnsupportedOperationException` from every method, so it fails every check until you implement it.
Starter code and validators are available in Java, Python, and C++.
Examples
Example 1
Input
var g = new SnakesAndLaddersGame(30, List.of("A", "B")); g.rollAndMove(5); g.getPosition("A")Output
"5"Why
A starts at 0, rolls 5, lands at 5. Turn rotates to B.
Example 2
Input
g.addLadder(4, 25); g.rollAndMove(4); g.getPosition(currentPlayer)Output
"25"Why
Landing on 4 climbs the ladder to 25.
Example 3
Input
g at position 28 rolls 5 (board=30)Output
"stays at 28; turn rotates to next player"Why
28 + 5 = 33 > boardSize. Overshoot rule: player does not move.
Constraints
- •Constructor: SnakesAndLaddersGame(int boardSize, List<String> playerIds). boardSize >= 2; playerIds non-empty.
- •addLadder(bottom, top): 0 < bottom < top < boardSize.
- •addSnake(head, tail): 0 < tail < head < boardSize.
- •rollAndMove: diceRoll in 1..6 (throws IllegalArgumentException otherwise); throws IllegalStateException if the game is over.
- •Overshoot rule: if pos + diceRoll > boardSize, the player stays put. Turn still rotates.
- •Apply at most one ladder then at most one snake at the destination (no infinite chains).
- •First player to land exactly on boardSize wins; isGameOver becomes true and getCurrentPlayer returns null.
Hints
Stuck? Reveal a nudge toward the right pattern, one step at a time.
Hint 1
State: an int boardSize, a List<String> players, a Map<String, Integer> positions, an int currentPlayerIndex, a String winner (null while in-progress), and Map<Integer, Integer> snakes + ladders.
Hint 2
rollAndMove: validate diceRoll in 1..6 (throw IllegalArgumentException). Throw IllegalStateException if winner is non-null. Compute newPos = pos + diceRoll. If newPos > boardSize → newPos = pos (overshoot rule).
Hint 3
After computing newPos, apply ladders (if ladders.containsKey(newPos), newPos = ladders.get(newPos)). Then apply snakes (if snakes.containsKey(newPos), newPos = snakes.get(newPos)). Apply each at most once.
Hint 4
If newPos == boardSize, set winner = current player and rotate the turn pointer (or set currentPlayerIndex to a sentinel that makes getCurrentPlayer return null). The simplest: store winner and have getCurrentPlayer return null when winner != null.
Hint 5
Always rotate the turn after a roll, including after an overshoot. Only winning halts the rotation.