Machine Coding Problem

Snake & Ladder

maco30maco60macoAllgamesentity-modelinggame-loop
Commonly Asked By:AmazonFlipkartMicrosoftGrab

Functional Scope (In-Scope)

  • Dynamic Board Config: The board must accept customizable size and configurable head-to-tail Snakes and base-to-top Ladders.
  • Turn-Based Flow: Support N sequential players managed in a round-robin turn order.
  • Modular Dice Control: Allow rolling M concurrent dice of configurable sides (default single 6-sided die).
  • Strict Win Condition: Win occurs only on exact landing on cell 100. Overshoots are rejected, leaving player position unchanged.

Explicit Boundaries (Out-of-Scope)

  • No UI Render Loop: Outputs status text sequentially via command-line logger.
  • No Game Lobby Network Logic: Run locally within a single synchronous app thread.

Modular clean implementations in all 3 target languages:

// ─── JAVA BLUEPRINT ──────────────────────────────────────────────────────────
import java.util.*;

interface DiceStrategy {
    int roll();
}

class StandardDice implements DiceStrategy {
    private final int sides;
    private final Random random = new Random();

    public StandardDice(int sides) {
        this.sides = sides;
    }

    @Override
    public int roll() {
        return random.nextInt(sides) + 1;
    }
}

class Player {
    private final String name;
    private int position;

    public Player(String name) {
        this.name = name;
        this.position = 0; // Starts off-board or at 0
    }

    public String getName() { return name; }
    public int getPosition() { return position; }
    public void setPosition(int position) { this.position = position; }
}

class Board {
    private final int size;
    private final Map<Integer, Integer> specialCells = new HashMap<>(); // Holds snakes & ladders

    public Board(int size) {
        this.size = size;
    }

    public int getSize() { return size; }

    public void addSnake(int head, int tail) {
        if (head <= tail) throw new IllegalArgumentException("Snake head must be above tail.");
        specialCells.put(head, tail);
    }

    public void addLadder(int start, int end) {
        if (start >= end) throw new IllegalArgumentException("Ladder start must be below end.");
        specialCells.put(start, end);
    }

    public int getNextPosition(int position) {
        if (specialCells.containsKey(position)) {
            int destination = specialCells.get(position);
            if (destination < position) {
                System.out.println("[Board] Swallowed by Snake at " + position + " -> slid down to " + destination);
            } else {
                System.out.println("[Board] Climbed Ladder at " + position + " -> went up to " + destination);
            }
            return destination;
        }
        return position;
    }
}

class GameManager {
    private final Board board;
    private final DiceStrategy dice;
    private final Queue<Player> players = new LinkedList<>();
    private Player winner = null;

    public GameManager(Board board, DiceStrategy dice, List<Player> initialPlayers) {
        this.board = board;
        this.dice = dice;
        this.players.addAll(initialPlayers);
    }

    public boolean isGameOver() {
        return winner != null;
    }

    public void takeTurn() {
        if (isGameOver()) return;

        Player currentPlayer = players.poll();
        int roll = dice.roll();
        int currentPos = currentPlayer.getPosition();
        int nextPos = currentPos + roll;

        System.out.println("[Game] " + currentPlayer.getName() + " rolled a " + roll + " (Current: " + currentPos + ")");

        if (nextPos > board.getSize()) {
            System.out.println("[Game] " + currentPlayer.getName() + " overshoot! Needs exact roll to win. Turn skipped.");
            nextPos = currentPos;
        } else {
            nextPos = board.getNextPosition(nextPos);
        }

        currentPlayer.setPosition(nextPos);
        System.out.println("[Game] " + currentPlayer.getName() + " moves to cell: " + nextPos);

        if (nextPos == board.getSize()) {
            winner = currentPlayer;
            System.out.println("[Victory] Player " + currentPlayer.getName() + " has won the game!");
            return;
        }

        players.add(currentPlayer); // Re-queue for next turn
    }

    public Player getWinner() { return winner; }
}

public class Main {
    public static void main(String[] args) {
        Board board = new Board(100);
        
        // Setup snakes
        board.addSnake(14, 4);
        board.addSnake(37, 17);
        board.addSnake(62, 19);
        board.addSnake(96, 56);

        // Setup ladders
        board.addLadder(3, 38);
        board.addLadder(9, 31);
        board.addLadder(40, 59);
        board.addLadder(75, 95);

        DiceStrategy standardDice = new StandardDice(6);
        List<Player> players = Arrays.asList(
            new Player("Alice"),
            new Player("Bob"),
            new Player("Charlie")
        );

        GameManager game = new GameManager(board, standardDice, players);

        System.out.println("--- Snake & Ladder Game Starting ---");
        int turnCount = 0;
        while (!game.isGameOver() && turnCount < 100) {
            game.takeTurn();
            turnCount++;
        }
        System.out.println("--- Simulation Ended. Total Turns: " + turnCount + " ---");
    }
}