Bird
Raised Fist0

Snake and Ladder Game

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
🏗️
Snake and Ladder Game
Design a classic Snake and Ladder game with board, dice, players, and rules for snakes and ladders.
mediumGame DesignFreq: medium
Prerequisites:OOP FundamentalsJava Concurrency BasicsDesign Patterns (Factory, Strategy)
⚙️
Functional Requirements
  • Dice generates random number between 1 and 6
  • Board contains cells with optional snakes or ladders
  • Player position updates according to dice roll and snakes/ladders
  • Game supports multiple players playing in turn order
  • Game detects and declares winner when a player reaches last cell
  • Players cannot move beyond last cell
  • Game enforces turn order and prevents concurrent moves
👤
Use Cases
  • Player rolls dice to move
  • GameMaster updates player position
  • GameMaster checks for snakes or ladders at new position
  • GameMaster declares winner when player reaches last cell
  • Multiple players take turns sequentially
🧑‍💻
Actors
  • Player
  • GameMaster
  • Dice
❓
Clarifying Questions to Ask
  • How many players can play concurrently? (Answer: multiple players but moves are sequential)
  • Are multiple dice rolls allowed per turn? (Answer: one roll per turn)
  • Should the game support concurrent threads for players or a single game thread? (Answer: multiple threads simulating players, but synchronized turn management)
  • Is there a pricing or scoring strategy? (Answer: no pricing, only position tracking)
  • What happens if dice roll moves player beyond last cell? (Answer: player stays in place, no move)
  • Are snakes and ladders fixed or dynamic? (Answer: fixed for game duration)
  • Should the game support pause/resume? (Answer: out of scope)
Out of Scope
✗ Networked multiplayer
✗ Graphical UI
✗ Customizable board size or rules
✗ AI players
🔢
Enumerations
enum CellType
NORMAL | SNAKE | LADDER
Defines cell types explicitly to avoid magic strings and enable exhaustive switch statements for cell behavior.
enum GameStatus
NOT_STARTED | IN_PROGRESS | COMPLETED
Tracks game lifecycle state to enforce valid transitions and prevent invalid moves.
enum PlayerState
WAITING | PLAYING | FINISHED
Represents player turn state to coordinate concurrency and turn sequencing.
📦
Board
2 fields
private final int sizeprivate final Cell[] cells
Represents the game board with cells, initializes snakes and ladders, provides cell lookup.
public int getSize()Returns the total number of cells on the board.
public Cell getCell(int position)Returns the cell object at the given position.
📦
Cell
3 fields
private final int positionprivate final CellType typeprivate final int jumpToPosition
Represents a single cell on the board, may be normal, snake, or ladder with jump position.
public int getPosition()Returns the cell's position on the board.
public CellType getType()Returns the type of the cell (NORMAL, SNAKE, LADDER).
public int getJumpToPosition()Returns the position to jump to if cell is snake or ladder; otherwise same position.
📦
Dice
1 fields
private final Random random
Generates random dice rolls between 1 and 6.
public synchronized int roll()Returns a random integer between 1 and 6 inclusive.
📦
Player
3 fields
private final String nameprivate volatile int positionprivate volatile PlayerState state
Represents a player with name, current position, and state in the game.
public synchronized int getPosition()Returns the current position of the player.
public synchronized void setPosition(int position)Updates the player's position atomically.
public PlayerState getState()Returns the current state of the player.
public void setState(PlayerState state)Sets the player's state.
📦
GameMaster
5 fields
private final Board boardprivate final Dice diceprivate final List<Player> playersprivate volatile int currentPlayerIndexprivate volatile GameStatus status
Controls game flow, enforces turn order, updates player positions, checks win condition.
public synchronized void startGame()Initializes game status and sets first player to PLAYING.
public synchronized boolean playTurn(Player player)Allows the current player to roll dice, move, and updates game state; returns true if move successful.
private synchronized void nextPlayer()Advances turn to next player who is not finished.
public boolean isGameOver()Checks if any player has reached the last cell.
🔗
Relationships
GameMaster◆──►Board[1 to 1]
compositionBoard lifecycle bound to GameMaster
GameMaster◆──►Dice[1 to 1]
compositionDice lifecycle bound to GameMaster
GameMaster◇──►Player[1 to many]
aggregationPlayers can exist independently of GameMaster
Board◆──►Cell[1 to many]
compositionCells lifecycle bound to Board
Cell──►CellType[1 to 1]
associationCellType is enum, shared

Practice

(1/5)
1. In designing the Airline Reservation System, should the Seat entity be modeled as an abstract class or an interface, and why?
easy
A. Abstract class, because seats share common state like seat number and class, and behavior like availability checks.
B. Interface, because it allows multiple inheritance and flexible seat type combinations.
C. Interface, because seats only define behavior without any shared state or implementation.
D. Abstract class, because interfaces cannot enforce method signatures for seat operations.

Solution

  1. Step 1: Analyze seat characteristics

    Seats have shared state (seat number, class) and common behavior (availability, booking), which suggests code reuse.
  2. Step 2: Abstract class vs interface

    Abstract class allows shared state and default behavior implementation, while interface cannot hold state and only defines method signatures.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Shared state + behavior -> abstract class [check]
Hint: Shared state needs abstract class, interfaces lack fields [check]
Common Mistakes:
2. In designing a collection class that supports iteration, should the iterator interface be an abstract class or an interface in Java, and why?
easy
A. Interface, because it enforces immutability of the collection during iteration.
B. Abstract class, because it allows sharing state and default implementation for iteration methods.
C. Abstract class, because Java interfaces cannot have methods with parameters.
D. Interface, because it defines behavior without state, allowing multiple implementations and better flexibility.

Solution

  1. Step 1: Understand Java interface vs abstract class

    Interfaces define behavior contracts without state, allowing multiple implementations. Abstract classes can hold state but restrict multiple inheritance.
  2. Step 2: Apply to iterator design

    Iterator interface defines traversal methods (e.g., hasNext(), next()) without state, enabling different iterator implementations per collection type.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Iterator as interface enables flexible, stateless traversal contracts [check]
Hint: Iterator interface defines behavior, no state needed [check]
Common Mistakes:
3. In the Meeting Scheduler, the RoomBookingManager class has a bookRoom() method that checks if a room is available and then marks it booked. Without synchronizing bookRoom(), which exact sequence of events between Thread 1 and Thread 2 causes a double-booking race condition?
medium
A. Thread 1 reads availability as false; Thread 2 reads availability as true; both proceed to book.
B. Thread 1 and Thread 2 both wait on a lock, causing deadlock and no booking.
C. Thread 1 books room; Thread 2 reads availability after booking and cancels its booking.
D. Thread 1 checks isAvailable() -> true, context switch before booking; Thread 2 checks isAvailable() -> true, both book simultaneously.

Solution

  1. Step 1: Identify check-then-act gap

    Without synchronization, Thread 1 reads availability as true but is preempted before booking; Thread 2 also reads true and proceeds.
  2. Step 2: Both threads book simultaneously causing double-booking

    Because the availability check and booking are not atomic, both threads can book the same room concurrently.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Unsynchronized check-then-act -> double-booking race [check]
Hint: Check-then-act without sync -> double-booking race [check]
Common Mistakes:
4. In the ESPNcricinfo system, the Scorecard class has a recordBall() method that checks if the ball is valid and then updates the score. Without synchronizing recordBall(), what exact sequence of Thread 1 and Thread 2 causes double-counting of runs?
medium
A. Thread 1 and Thread 2 both call recordBall() simultaneously and both update the score atomically.
B. Thread 1 checks ball validity -> valid, context switch; Thread 2 checks ball validity -> valid; both update score causing double-count.
C. Thread 1 updates score, then Thread 2 reads stale score and overwrites it with old value.
D. Thread 1 and Thread 2 both wait on a lock causing deadlock and no score update.

Solution

  1. Step 1: Identify check-then-act race condition

    Both threads check ball validity before updating score; without synchronization, both see valid state.
  2. Step 2: Trace interleaving causing double-count

    Thread 1 checks valid -> context switch; Thread 2 checks valid -> both proceed to update score independently causing double-count.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap without sync -> double update [check]
Hint: Check-then-act gap -> both threads proceed -> double update [check]
Common Mistakes:
5. Adding a WeekendFeeStrategy to the parking lot pricing requires which minimum change to comply with SOLID principles?
medium
A. Modify the existing FeeCalculator class to add weekend logic with an if-else block.
B. Add a boolean isWeekend flag to Vehicle and change pricing logic accordingly.
C. Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes.
D. Combine all fee strategies into one large class with multiple methods for each pricing rule.

Solution

  1. Step 1: Identify the SOLID principle involved

    The Open-Closed Principle (OCP) requires that classes be open for extension but closed for modification.
  2. Step 2: Evaluate options against OCP

    Create a new WeekendFeeStrategy class implementing FeeStrategy and inject it without modifying existing classes. respects OCP by adding a new strategy class without modifying existing code. Add a boolean isWeekend flag to Vehicle and change pricing logic accordingly. violates OCP by modifying Vehicle state, which is unrelated to pricing and causes tight coupling.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    New strategy class -> OCP-compliant extension [check]
Hint: OCP: add new class, don't modify existing ones [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard