Instructions
Objective
Write a program to create a snake and ladder game in java.
Requirements and Specifications
Create an application to simulate the game of snake and ladder.
Rules of the game
- The game is played on a board with numbered, gridded squares. In an example illustrated above, the board has 36 positions in total, and a few ladders and snakes that will be explained later.
- Two or more players will play the game. Each player starts from position 0
- Each player takes turns rolling a single die to move their token by the number of squares indicated by the die roll.
- A random number from 1 to 6 is generated by a dice. If the dice is 5 and one player is at position 10, the player will move to position 15 (10 + 5)
- A player wins if it exactly reaches the end position (aka position 36 in the example above) and the game ends.
- If a player is supposed to move outside the board, for example dice is 5 and the player is at position 34, the player will stay at current position 34 because 34 + 5 > 36.
- About Ladder: when a player ends up at a position of the start of one ladder, the player will move to the position of the end of the ladder. E.g. moving from position 3 to 16.
- About Snake: when a player ends up at a position of the head of one snake, the player will move to the position of the tail of the snake. E.g. moving from position 30 to 4.
- There could be another snake or ladder at the end position of the ladder or snake, and then the player will have to move up or down accordingly again.
- No snake head at the end position
- No multiple snakes or ladders have same head position
- Snakes and ladders should not form an infinite loop
- Snake should have its tail at a smaller number than its head
- Ladder should have its end position at a larger number than its start position
- Print every movement of each player in the following format.
- When someone wins the game, print that the player won the game.
Constraints and Validations
The application should consider the following constraints:
Logging
The application should be able to print the following messages, either to console or to file
Format: <player name> rolled a <dice value> and moved from <initial position> to <final position>
Format: <player name> wins the game
Source Codeimport logic.*;
import java.util.Locale;
import java.util.Scanner;
public class Driver {
/**
* Plays a text-based game
*/
public static void main(String[] args) {
try(Scanner scanner = new Scanner(System.in)) {
GameBuilder gameBuilder = new GameBuilder();
while (true) {
try {
gameBuilder = gameBuilder.boardSize(readIntChoice(scanner, "Please, enter board size: "));
break;
} catch (GameConfigurationException e) {
System.out.println(e.getMessage());
}
}
System.out.println();
while (true) {
try {
gameBuilder = gameBuilder.playersNum(readIntChoice(scanner, "Please, enter number of players: "));
break;
} catch (GameConfigurationException e) {
System.out.println(e.getMessage());
}
}
System.out.println();
while(readBoolChoice(scanner, "Do you want to add ladder? (y/n): ")) {
try {
int head = readIntChoice(scanner, "Please, enter ladder head: ");
int tail = readIntChoice(scanner, "Please, enter ladder tail: ");
gameBuilder = gameBuilder.ladder(new Ladder(head, tail));
System.out.println("Ladder added successfully");
}
catch (GameConfigurationException e) {
System.out.println(e.getMessage());
}
System.out.println();
}
while(readBoolChoice(scanner, "Do you want to add snake? (y/n): ")) {
try {
int head = readIntChoice(scanner, "Please, enter snake head: ");
int tail = readIntChoice(scanner, "Please, enter snake tail: ");
gameBuilder = gameBuilder.snake(new Snake(head, tail));
System.out.println("Snake added successfully");
}
catch (GameConfigurationException e) {
System.out.println(e.getMessage());
}
System.out.println();
}
System.out.println("Starting the game:");
Game game = gameBuilder.build();
while(!game.isOver()) {
System.out.print("Please, hit 'Enter' to roll the die: ");
scanner.nextLine();
game.makeMove();
}
}
}
private static int readIntChoice(Scanner scanner, String prompt) {
while(true) {
try {
System.out.print(prompt);
return Integer.parseInt(scanner.nextLine());
}
catch (NumberFormatException e) {
System.out.println("Invalid input");
}
}
}
private static boolean readBoolChoice(Scanner scanner, String prompt) {
while(true) {
System.out.print(prompt);
String input = scanner.nextLine().trim().toLowerCase();
if (input.equals("y")) {
return true;
}
if (input.equals("n")) {
return false;
}
System.out.println("Invalid input");
}
}
}
GAME
package logic;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
public class Game {
private final int length;
private final Collection<Action> actions;
private final IDie die;
private final Player[] players;
private int playerToMove;
private Player winner;
/**
* Creates a square game board.
*
* @param length the width and height.
*/
Game(int length, int playersNum, Collection<Action> actions, IDie die) {
this.length = length;
this.actions = new ArrayList<>(actions);
this.die = die;
this.players = new Player[playersNum];
for (int i = 0; i < playersNum; i++) {
players[i] = new Player(i + 1);
}
this.winner = null;
this.playerToMove = 0;
}
/**
* The size of the current game.
*
* @return this is both the width and the height.
*/
public int getLength() {
return length;
}
public void makeMove() {
makeMove(playerToMove);
playerToMove = (playerToMove + 1) % players.length;
}
public void makeMove(int currPlayer) {
Player player = players[currPlayer];
int dieScore = die.rollDie();
int currPosition = player.getPosition();
int nextPosition = (currPosition + dieScore > length) ? currPosition : currPosition + dieScore;
while(true) {
int nextPositionTmp = nextPosition;
Action action = actions.stream().filter(a -> a.getHeadIndex() == nextPositionTmp).findAny().orElse(null);
if (action == null) {
break;
}
nextPosition = action.getTailIndex();
}
player.updatePosition(nextPosition);
logMove(player, dieScore, currPosition, nextPosition);
if (nextPosition == length) {
winner = player;
logWinner(player);
}
}
private void logMove(Player player, int die, int from, int to) {
System.out.printf("%s rolled a %d and moved from %d to %d%n", "Player " + player.getId(), die, from, to);
}
private void logWinner(Player player) {
System.out.printf("%s wins the game%n", "Player " + player.getId());
}
public boolean isOver() {
return winner != null;
}
}
LADDER
package logic;
public class Ladder extends Action {
public Ladder(int headIndex, int tailIndex) throws GameConfigurationException {
super(headIndex, tailIndex);
if (headIndex >= tailIndex) {
throw new GameConfigurationException("Ladder has tail at a smaller number, than its head");
}
}
@Override
public String toString() {
return "Ladder{head=" + getHeadIndex() + " tail=" + getTailIndex() + "}";
}
}