Low Level Design - Snake and Ladder Game
This post can help you to design a snake and ladder game based on a given requirement
Requirement
The game should be able to take input - number of players, size of the dice and board, snake, and ladder count
Snake should take the player down and the ladder should take the players up
Make sure there is no snake mouth in the first 10 spots and there is no ladder going up in the last 10 spots of the board.
Each player should take one turn to roll the dice and change the position of the player accordingly
A player is not supposed to move outside of the board.
The game will end when all the players reach the end position
At the end, the Game should display the names of the players in the order they win
Bonus - At the end Game should display all the positions each player went through
Design
Class diagram
Code
Dice class
This can be a simple class that can store the maximum value of a dice. By default, it’s 6 in real life. It also has a method to roll() which can provide us a number between 1 and the maximum size (6).
class Dice {
private final int size;
public Dice(int size) {
this.size = size;
}
public int roll() {
return new Random().nextInt(size) + 1;
}
}Player class
This class stores all the Player’s related information. Like:
Name of the player
Current position of the player
A flag to check if the player has won the game or not
List of integers to store the past positions of the player
We will create one instance of each based on the number of players.
class Player {
protected final String name;
int position;
protected boolean won;
protected final List<Integer> positionHistory;
public Player(String name) {
this.name = name;
positionHistory = new ArrayList<>();
position = 0;
positionHistory.add(position);
}
public void increasePosition(int steps) {
position += steps;
positionHistory.add(position);
}
}Board class
This class contains the following:
Size of the board - number of spots (generally 100)
A map to store the snake’s start and end positions.
A map to store the ladder’s start and end positions.
This class has a constructor which will initiate all the above attributes. Apart from that the class also has some public methods to help us run the game:
boolean isLadderPresent(int position)
int getLadderEnd(int position)
boolean isSnameMouth(int position)
int getSnakeEnd(int position)
class Board {
protected final int size;
protected final Map<Integer, Integer> snakeMap;
protected final Map<Integer, Integer> ladderMap;
private final Set<Integer> usedSpots = new HashSet<>();
public Board(int size, int snakeCount, int ladderCount) {
System.out.println("=== START - Initializing the board ===");
this.size = size;
snakeMap = new HashMap<>();
ladderMap = new HashMap<>();
// build snake and ladders
for (int i = 0; i < snakeCount; i++) {
int mouth = getRandom(11, size - 1); // snake should not be there in first 10 spots
int tail = getRandom(1, mouth - 10); // snake length should be at least 10
snakeMap.put(mouth, tail);
}
for (int i = 0; i < ladderCount; i++) {
int start = getRandom(0, size - 10); // no point having a ladder start in the last 10 spots
int end = getRandom(start + 10, size - 1); // ladder length should be at least 10
ladderMap.put(start, end);
}
System.out.println();
System.out.println("=== END - Initializing the board ===");
}
public boolean isSnakeMouth(int position) {
return snakeMap.containsKey(position);
}
public int getSnakeEnd(int position) {
return snakeMap.get(position);
}
public boolean isLadderPresent(int position) {
return ladderMap.containsKey(position);
}
public int getLadderEnd(int position) {
return ladderMap.get(position);
}
private int getRandom(int min, int max) {
while (true) {
System.out.print(".");
int num = new Random().nextInt(max);
if (num >= min && !usedSpots.contains(num)) {
usedSpots.add(num);
return num;
}
}
}
}Game class
The Game class contains the following fields that will be initialized from a constructor:
Board object
Dice object
List of Player objects
List of winner Player objects
The main method is start() which will start the game. This method will contain the following steps:
Running a while loop, until all the players reach the end of the board.
Run a for-loop for each player in the list.
If the player has won, don’t do anything (continue;).
Roll the dice and get the steps.
if the player is close to the end and adding the steps will move them out of the board, then don’t do anything (continue;).
change the position of the player based on the dice number.
if the player has reached the end of the board, then:
mark it won, and add the winner’s list.
if all the players won, then return and end the game.
Check if the new position of the player has a snake or latter, then get the end position from the snake or ladder map and move the player to the new position.
class Game {
private final Board board;
private final Dice dice;
private final List<Player> players;
protected final List<String> winners;
public Game(String[] playerNames, int diceSize, int boardSize, int snakeCount, int ladderCount) {
// build players list
players = new ArrayList<>();
winners = new ArrayList<>();
for (String name : playerNames) {
players.add(new Player(name));
}
// build dice
dice = new Dice(diceSize);
// build board
board = new Board(boardSize, snakeCount, ladderCount);
printBoard();
}
public void printPositions() {
System.out.println("=== Final Positions ===");
for (Player p : players) {
System.out.println(p.name + " is at position: " + p.position);
System.out.println("Past positions: " + p.positionHistory);
}
}
public void printBoard() {
System.out.println("=== Board ===");
System.out.println("Snake map: " + board.snakeMap);
System.out.println("Ladder map: " + board.ladderMap);
}
public void start() {
while (true) {
for (Player p : players) {
if (p.won) {
continue;
}
System.out.println("============ " + p.name + " is rolling the dice =============");
System.out.println("Start Position: " + p.position);
int steps = dice.roll();// roll the dice
System.out.println("Dice value: " + steps);
if (p.position + steps > board.size) {
System.out.println("* Cant reach " + board.size);
continue; // if the player cant reach the end position then he stays there.
}
p.increasePosition(steps);
if (p.position == board.size) {
p.won = true;
winners.add(p.name);
if (winners.size() == players.size()) {
return; // return when all the players are in the winner list.
}
}
// check for snake map and ladder map
if (board.isSnakeMouth(p.position)) {
System.out.println("Snake got >>> " + p.name);
p.position = board.getSnakeEnd(p.position);
} else if (board.isLadderPresent(p.position)) {
System.out.println("Ladder got >>> " + p.name);
p.position = board.getLadderEnd(p.position);
}
System.out.println("End Position: " + p.position);
}
}
}
}Main SnakeAndLadder class - Running the Game
Run the main method by passing the desired inputs like this:
public class SnakeAndLadder {
public static void main(String[] args) {
String[] players = new String[]{"Amar", "Akbar", "Anthony"};
Game game = new Game(players, 6, 100, 5, 5);
game.start();
game.printBoard();
game.printPositions();
System.out.println("*** The Winner order is *** " + game.winners);
}
}The console will print the following information:
=== Board ===
Snake map: {25=5, 58=29, 59=47, 95=33, 31=7}
Ladder map: {18=49, 50=74, 22=77, 62=98, 78=94}
=== Final Positions ===
Amar is at position: 100
Past positions: [0, 1, 4, 9, 14, 20, 23, 29, 33, 35, 40, 43, 46, 51, 53, 57, 58, 31, 13, 19, 23, 27, 31, 12, 16, 20, 24, 27, 29, 35, 36, 40, 41, 42, 47, 51, 52, 58, 34, 37, 43, 49, 53, 54, 60, 65, 68, 70, 72, 78, 100]
Akbar is at position: 100
Past positions: [0, 3, 4, 6, 10, 13, 15, 16, 19, 25, 7, 12, 14, 16, 19, 24, 29, 35, 36, 39, 41, 42, 44, 47, 49, 51, 52, 54, 60, 62, 99, 100]
Anthony is at position: 100
Past positions: [0, 1, 6, 7, 10, 14, 16, 22, 83, 87, 91, 93, 98, 99, 100]
*** The Winner order is *** [Anthony, Akbar, Amar]Anthony is the winner in this run.
You can download and run the code from this link SnakeAndLadder.java


