├── img.png ├── src └── main │ └── java │ └── com │ └── uditagarwal │ └── game │ └── battleship │ ├── io │ ├── input │ │ ├── IInputProvider.java │ │ ├── PlayerInput.java │ │ └── SysInInputProvider.java │ └── output │ │ ├── IOutputPrinter.java │ │ └── SysOutOutputPrinter.java │ ├── exceptions │ ├── CoordinateOutOfBoundaryException.java │ └── InvalidInputException.java │ ├── strategy │ ├── IWinnerStrategy.java │ ├── IPlayerPickingStrategy.java │ ├── IChanceGenerationStrategy.java │ ├── RoundRobinPlayerPickingStrategy.java │ ├── DefaultWinnerStrategy.java │ └── LocalChanceGeneration.java │ ├── model │ ├── boundary │ │ ├── IBoundary.java │ │ └── RectangularBoundary.java │ ├── PlayerChanceTarget.java │ ├── Coordinate.java │ ├── BoardItem.java │ ├── player │ │ └── Player.java │ └── Board.java │ ├── GameLoop.java │ └── Main.java ├── README.md ├── .gitignore ├── pom.xml └── problem-statement.md /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anomaly2104/battleship-game-low-level-design/HEAD/img.png -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/io/input/IInputProvider.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.io.input; 2 | 3 | public interface IInputProvider { 4 | 5 | PlayerInput takeInput(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/exceptions/CoordinateOutOfBoundaryException.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.exceptions; 2 | 3 | public class CoordinateOutOfBoundaryException extends RuntimeException { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/strategy/IWinnerStrategy.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.strategy; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | 5 | import java.util.List; 6 | 7 | public interface IWinnerStrategy { 8 | 9 | Player getWinner(List playerList); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/exceptions/InvalidInputException.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.exceptions; 2 | 3 | public class InvalidInputException extends RuntimeException { 4 | 5 | public InvalidInputException() { 6 | } 7 | 8 | public InvalidInputException(NumberFormatException exception) { 9 | super(exception); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/boundary/IBoundary.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model.boundary; 2 | 3 | import com.uditagarwal.game.battleship.model.Coordinate; 4 | import lombok.NonNull; 5 | 6 | import java.util.List; 7 | 8 | public interface IBoundary { 9 | 10 | boolean contains(@NonNull Coordinate coordinate); 11 | List allCoordinates(); 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Battleship Game - Low level system design 2 | 3 | ## Connect with me and my offerings: 4 | https://enginebogie.com/u/anomaly2104 5 | 6 | ## Video Explanation 7 | https://youtu.be/yGXzJrBr-3s 8 | 9 | ## Problem Statements 10 | [Problem Statement](problem-statement.md) 11 | 12 | ## Further enhancements 13 | * Write unit tests. 14 | * Add more validations. 15 | * Add history of moves for each player. 16 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/PlayerChanceTarget.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | @AllArgsConstructor 9 | public class PlayerChanceTarget { 10 | 11 | final Player targetPlayer; 12 | final Coordinate target; 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | .idea 26 | *.iml 27 | target 28 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/Coordinate.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.ToString; 7 | 8 | @Getter 9 | @AllArgsConstructor 10 | @EqualsAndHashCode 11 | @ToString 12 | public class Coordinate { 13 | 14 | private final int x; 15 | private final int y; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/strategy/IPlayerPickingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.strategy; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | 5 | import java.util.List; 6 | 7 | public interface IPlayerPickingStrategy { 8 | 9 | Integer firstPlayer(List allPlayers); 10 | Integer pickNextPlayer(Integer currentPlayerIndex, List allPlayers); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/strategy/IChanceGenerationStrategy.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.strategy; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | import com.uditagarwal.game.battleship.model.PlayerChanceTarget; 5 | 6 | import java.util.List; 7 | 8 | public interface IChanceGenerationStrategy { 9 | 10 | PlayerChanceTarget getPlayerChanceTarget(List opponents); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/io/input/PlayerInput.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.io.input; 2 | 3 | import com.uditagarwal.game.battleship.model.Coordinate; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | 7 | @Getter 8 | @AllArgsConstructor 9 | public class PlayerInput { 10 | 11 | private final Integer playerNum; 12 | private final Integer targetX; 13 | private final Integer targetY; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/io/output/IOutputPrinter.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.io.output; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | 5 | import java.util.List; 6 | 7 | public interface IOutputPrinter { 8 | 9 | void printMsg(String msg); 10 | void printWinner(Player player); 11 | void printSelfBoard(Player player); 12 | void printOpponentBoard(List allPlayers, Player currentPlayer); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/strategy/RoundRobinPlayerPickingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.strategy; 2 | 3 | import com.uditagarwal.game.battleship.exceptions.InvalidInputException; 4 | import com.uditagarwal.game.battleship.model.player.Player; 5 | 6 | import java.util.List; 7 | 8 | public class RoundRobinPlayerPickingStrategy implements IPlayerPickingStrategy { 9 | 10 | @Override 11 | public Integer firstPlayer(List allPlayers) { 12 | if (allPlayers.size() == 0) { 13 | throw new InvalidInputException(); 14 | } 15 | return 0; 16 | } 17 | 18 | @Override 19 | public Integer pickNextPlayer(Integer currentPlayerIndex, List allPlayers) { 20 | return (currentPlayerIndex + 1) % allPlayers.size(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/strategy/DefaultWinnerStrategy.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.strategy; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | import lombok.NonNull; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class DefaultWinnerStrategy implements IWinnerStrategy { 10 | 11 | @Override 12 | public Player getWinner(@NonNull final List playerList) { 13 | final List alivePlayers = new ArrayList<>(); 14 | for (Player player : playerList) { 15 | if (!player.areAllShipsKilled()) { 16 | alivePlayers.add(player); 17 | } 18 | } 19 | if (alivePlayers.size() == 1) { 20 | return alivePlayers.get(0); 21 | } 22 | return null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | battleship-game 9 | 1.0-SNAPSHOT 10 | 11 | 12 | org.projectlombok 13 | lombok 14 | RELEASE 15 | compile 16 | 17 | 18 | 19 | 20 | 15 21 | 15 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/BoardItem.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model; 2 | 3 | import com.uditagarwal.game.battleship.model.boundary.IBoundary; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NonNull; 7 | import lombok.ToString; 8 | 9 | import java.util.List; 10 | 11 | @Getter 12 | @AllArgsConstructor 13 | @ToString 14 | public class BoardItem { 15 | 16 | private final String name; 17 | private final IBoundary boundary; 18 | 19 | public boolean isKilled(@NonNull final List hitLocations) { 20 | final List shipCoordinates = boundary.allCoordinates(); 21 | for (Coordinate shipCoordinate: shipCoordinates) { 22 | if (!hitLocations.contains(shipCoordinate)) { 23 | return false; 24 | } 25 | } 26 | return true; 27 | } 28 | 29 | public boolean containsCoordinate(@NonNull final Coordinate coordinate) { 30 | return this.boundary.contains(coordinate); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/io/input/SysInInputProvider.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.io.input; 2 | 3 | import com.uditagarwal.game.battleship.exceptions.InvalidInputException; 4 | import lombok.SneakyThrows; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.InputStreamReader; 8 | 9 | public class SysInInputProvider implements IInputProvider { 10 | 11 | @SneakyThrows 12 | @Override 13 | public PlayerInput takeInput() { 14 | final InputStreamReader inputStreamReader = new InputStreamReader(System.in); 15 | final BufferedReader br = new BufferedReader(inputStreamReader); 16 | final String line = br.readLine(); 17 | 18 | //FutureImprovement: We can move this string line parsing logic to separate class when multiple input types are 19 | //supported. 20 | String[] s = line.split(" "); 21 | if (s.length != 3) { 22 | throw new InvalidInputException(); 23 | } 24 | 25 | final int playerNum = Integer.parseInt(s[0]); 26 | final int targetX = Integer.parseInt(s[1]); 27 | final int targetY = Integer.parseInt(s[2]); 28 | 29 | return new PlayerInput(playerNum, targetX, targetY); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/boundary/RectangularBoundary.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model.boundary; 2 | 3 | import com.uditagarwal.game.battleship.model.Coordinate; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NonNull; 7 | import lombok.ToString; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Getter 13 | @AllArgsConstructor 14 | @ToString 15 | public class RectangularBoundary implements IBoundary { 16 | private final Coordinate topLeft; 17 | private final Coordinate bottomRight; 18 | 19 | public List allCoordinates() { 20 | List coordinates = new ArrayList<>(); 21 | for (int i = topLeft.getX(); i <= bottomRight.getX(); i++) { 22 | for (int j = topLeft.getY(); j >= bottomRight.getY(); j--) { 23 | coordinates.add(new Coordinate(i, j)); 24 | } 25 | } 26 | return coordinates; 27 | } 28 | 29 | public boolean contains(@NonNull final Coordinate coordinate) { 30 | return coordinate.getX() >= topLeft.getX() && coordinate.getX() <= bottomRight.getX() 31 | && coordinate.getY() >= bottomRight.getY() && coordinate.getY() <= topLeft.getY(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/player/Player.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model.player; 2 | 3 | import com.uditagarwal.game.battleship.model.Board; 4 | import com.uditagarwal.game.battleship.model.Coordinate; 5 | import com.uditagarwal.game.battleship.model.PlayerChanceTarget; 6 | import com.uditagarwal.game.battleship.strategy.IChanceGenerationStrategy; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | import lombok.NonNull; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | @Getter 15 | @AllArgsConstructor 16 | public class Player { 17 | 18 | private final Board board; 19 | private final int id; 20 | private final IChanceGenerationStrategy chanceGenerationStrategy; 21 | 22 | public PlayerChanceTarget takeChance(List allPlayers) { 23 | List opponents = new ArrayList<>(); 24 | for (Player player: allPlayers) { 25 | if (player.getId() != getId()) { 26 | opponents.add(player); 27 | } 28 | } 29 | return chanceGenerationStrategy.getPlayerChanceTarget(opponents); 30 | } 31 | 32 | public boolean areAllShipsKilled() { 33 | return board.areAllShipsKilled(); 34 | } 35 | 36 | public void takeHit(@NonNull final Coordinate coordinate) { 37 | board.takeHit(coordinate); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/strategy/LocalChanceGeneration.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.strategy; 2 | 3 | import com.uditagarwal.game.battleship.io.input.IInputProvider; 4 | import com.uditagarwal.game.battleship.io.input.PlayerInput; 5 | import com.uditagarwal.game.battleship.model.player.Player; 6 | import com.uditagarwal.game.battleship.exceptions.InvalidInputException; 7 | import com.uditagarwal.game.battleship.model.Coordinate; 8 | import com.uditagarwal.game.battleship.model.PlayerChanceTarget; 9 | import lombok.AllArgsConstructor; 10 | import lombok.NonNull; 11 | 12 | import java.util.List; 13 | 14 | @AllArgsConstructor 15 | public class LocalChanceGeneration implements IChanceGenerationStrategy { 16 | 17 | private final IInputProvider inputProvider; 18 | 19 | @Override 20 | public PlayerChanceTarget getPlayerChanceTarget(@NonNull final List opponents) { 21 | final PlayerInput playerInput = inputProvider.takeInput(); 22 | Player targetPlayer = null; 23 | for (Player player: opponents) { 24 | if (player.getId() == playerInput.getPlayerNum()) { 25 | targetPlayer = player; 26 | } 27 | } 28 | 29 | if (targetPlayer == null) { 30 | throw new InvalidInputException(); 31 | } 32 | return new PlayerChanceTarget(targetPlayer, new Coordinate(playerInput.getTargetX(), playerInput.getTargetY())); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/io/output/SysOutOutputPrinter.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.io.output; 2 | 3 | import com.uditagarwal.game.battleship.model.player.Player; 4 | import lombok.NonNull; 5 | 6 | import java.util.List; 7 | 8 | public class SysOutOutputPrinter implements IOutputPrinter { 9 | 10 | @Override 11 | public void printMsg(String msg) { 12 | System.out.println(msg); 13 | } 14 | 15 | @Override 16 | public void printWinner(@NonNull final Player player) { 17 | System.out.println("Game Finished!"); 18 | System.out.println("Player: " + player.getId() + " won"); 19 | } 20 | 21 | private void printPlayerInfo(@NonNull final Player player) { 22 | printMsg("Player: " + player.getId()); 23 | } 24 | 25 | @Override 26 | public void printSelfBoard(@NonNull final Player player) { 27 | printMsg("Your board status: "); 28 | printPlayerInfo(player); 29 | printMsg("Board boundary: " + player.getBoard().getBoundary()); 30 | printMsg("Ships: " + player.getBoard().getShips()); 31 | printMsg("Hit locations: " + player.getBoard().hitLocations()); 32 | printMsg("Missed locations: " + player.getBoard().missLocations()); 33 | } 34 | 35 | private void printOpponentBoard(@NonNull final Player player) { 36 | printMsg("\nOpponent board status: "); 37 | printPlayerInfo(player); 38 | printMsg("Board boundary: " + player.getBoard().getBoundary()); 39 | printMsg("Hit locations: " + player.getBoard().hitLocations()); 40 | printMsg("Missed locations: " + player.getBoard().missLocations()); 41 | } 42 | 43 | @Override 44 | public void printOpponentBoard(@NonNull final List allPlayers, @NonNull final Player currentPlayer) { 45 | 46 | for (Player player : allPlayers) { 47 | if (player.getId() != currentPlayer.getId()) { 48 | printOpponentBoard(player); 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/GameLoop.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship; 2 | 3 | import com.uditagarwal.game.battleship.exceptions.CoordinateOutOfBoundaryException; 4 | import com.uditagarwal.game.battleship.model.player.Player; 5 | import com.uditagarwal.game.battleship.model.PlayerChanceTarget; 6 | import com.uditagarwal.game.battleship.io.output.IOutputPrinter; 7 | import com.uditagarwal.game.battleship.strategy.IWinnerStrategy; 8 | import com.uditagarwal.game.battleship.strategy.IPlayerPickingStrategy; 9 | import lombok.NonNull; 10 | 11 | import java.util.List; 12 | 13 | public class GameLoop { 14 | 15 | private final List players; 16 | private final IWinnerStrategy winnerStrategy; 17 | private final IOutputPrinter printer; 18 | private final IPlayerPickingStrategy nextPlayerStrategy; 19 | 20 | public GameLoop(@NonNull final List players, @NonNull final IWinnerStrategy winnerStrategy, 21 | @NonNull final IOutputPrinter printer, @NonNull final IPlayerPickingStrategy nextPlayerStrategy) { 22 | this.players = players; 23 | this.winnerStrategy = winnerStrategy; 24 | this.printer = printer; 25 | this.nextPlayerStrategy = nextPlayerStrategy; 26 | } 27 | 28 | public void start() { 29 | int currentPlayerIndex = nextPlayerStrategy.firstPlayer(this.players); 30 | printer.printMsg("Starting game!"); 31 | while (true) { 32 | final Player currentPlayer = players.get(currentPlayerIndex); 33 | printer.printMsg("\n\nPlayer: " + currentPlayer.getId() + " chance:"); 34 | final PlayerChanceTarget playerChanceTarget = currentPlayer.takeChance(this.players); 35 | 36 | try { 37 | playerChanceTarget.getTargetPlayer().takeHit(playerChanceTarget.getTarget()); 38 | } catch (CoordinateOutOfBoundaryException exception) { 39 | printer.printMsg("Hit was out of bounds."); 40 | } 41 | 42 | printer.printSelfBoard(currentPlayer); 43 | printer.printOpponentBoard(players, currentPlayer); 44 | 45 | final Player winner = winnerStrategy.getWinner(players); 46 | if (winner != null) { 47 | printer.printWinner(winner); 48 | break; 49 | } 50 | currentPlayerIndex = nextPlayerStrategy.pickNextPlayer(currentPlayerIndex, this.players); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/model/Board.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship.model; 2 | 3 | import com.uditagarwal.game.battleship.exceptions.CoordinateOutOfBoundaryException; 4 | import com.uditagarwal.game.battleship.model.boundary.IBoundary; 5 | import lombok.Getter; 6 | import lombok.NonNull; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | @Getter 12 | public class Board { 13 | 14 | private final List ships; 15 | private final IBoundary boundary; 16 | private final List allBombLocations; 17 | 18 | public Board(@NonNull final List ships, @NonNull final IBoundary boundary) { 19 | // TODO: Validate whether ships in board's boundary 20 | this.ships = ships; 21 | this.boundary = boundary; 22 | this.allBombLocations = new ArrayList<>(); 23 | } 24 | 25 | public void takeHit(@NonNull final Coordinate coordinate) { 26 | if (!boundary.contains(coordinate)) { 27 | throw new CoordinateOutOfBoundaryException(); 28 | } 29 | 30 | allBombLocations.add(coordinate); 31 | } 32 | 33 | public boolean areAllShipsKilled() { 34 | for (BoardItem ship : ships) { 35 | if (!ship.isKilled(allBombLocations)) { 36 | return false; 37 | } 38 | } 39 | return true; 40 | } 41 | 42 | public List hitLocations() { 43 | final List result = new ArrayList<>(); 44 | 45 | for (Coordinate coordinate: allBombLocations) { 46 | for (BoardItem ship: ships) { 47 | if (ship.containsCoordinate(coordinate)) { 48 | result.add(coordinate); 49 | break; 50 | } 51 | } 52 | } 53 | 54 | return result; 55 | } 56 | 57 | public List missLocations() { 58 | final List result = new ArrayList<>(); 59 | 60 | for (Coordinate coordinate: allBombLocations) { 61 | boolean doesBelongToShip = false; 62 | for (BoardItem ship: ships) { 63 | if (ship.containsCoordinate(coordinate)) { 64 | doesBelongToShip = true; 65 | break; 66 | } 67 | } 68 | if (!doesBelongToShip) { 69 | result.add(coordinate); 70 | } 71 | } 72 | 73 | return result; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /problem-statement.md: -------------------------------------------------------------------------------- 1 | ### Problem Statement: Battleship Game 2 | 3 | Write code for design of Battleship Game: https://en.wikipedia.org/wiki/Battleship_(game) 4 | 5 | #### Rules of the Game 6 | 1. There are 2 players in the game. 7 | 1. Each Person has two boards, one where he places his own ships, one where he tracks 8 | the missiles he has fired. Each board is of size 10x10. 9 | 1. Each person can place 5 ships on his board 10 | 1. Carrier of length 5 11 | 1. Battleship of length 4 12 | 1. Cruiser of length 3 13 | 1. Submarine of length 3 14 | 1. Destroyer of length 2 15 | 1. Players take a turn to fire missiles at the opposing player. If the missile hits a ship, then 16 | the opposing player informs the initial mover of a hit, else he says it’s a miss. If all the 17 | spots on a ship are hit, then ship is sunk. 18 | 1. The first player to sink all 5 ships of the opposing player wins the game. 19 | 20 | This is the view of one player 21 | 1. Left-hand side is the ships as placed by the player. Red spots represent where the 22 | enemy successfully struck the player’s ships. 23 | 2. White/Green spots are where the enemy player missed. 24 | 3. The right-hand side is where the player has launched missiles against the enemy. 25 | 4. The player has sunk 3 of the enemy ship. 26 | 27 | ![img.png](img.png) 28 | 29 | ###### Bonus Requirement: 30 | You don’t need to code this up, but explain how will you extend your design to 31 | allow people to play over the network (p2p without having a central server). 32 | 33 | #### Guidelines 34 | 1. We will be looking for the Low-Level Design including good class structure, entities and 35 | how they interact, good abstraction, good separation of concerns, etc 36 | 2. You will need to code the “Game Loop”. 37 | 3. You don’t need to bother with the code that “draws” the game or UI interactions, you can 38 | mock the function for eg. “drawBoard(List ships)” and assume it draws the board 39 | with the ships on it. You can also assume a “takeInput(Player player)” function that gets 40 | the play that the current player wishes to make. 41 | 1. Bonus: Take the input from the console. For eg. player can say “Fire C5” and you 42 | fire a missile at C5 or “Draw Board” and you print the current state of the board to 43 | the player. 44 | 4. You can choose any language, however, it needs to be a runnable code. 45 | 46 | #### Assumptions 47 | Please make the required assumptions, for instance, players can only join before the 48 | game starts, but MAKE SURE YOU LIST THEM IN A README FILE along with the code. 49 | -------------------------------------------------------------------------------- /src/main/java/com/uditagarwal/game/battleship/Main.java: -------------------------------------------------------------------------------- 1 | package com.uditagarwal.game.battleship; 2 | 3 | import com.uditagarwal.game.battleship.io.input.IInputProvider; 4 | import com.uditagarwal.game.battleship.io.input.SysInInputProvider; 5 | import com.uditagarwal.game.battleship.model.boundary.RectangularBoundary; 6 | import com.uditagarwal.game.battleship.model.player.Player; 7 | import com.uditagarwal.game.battleship.io.output.SysOutOutputPrinter; 8 | import com.uditagarwal.game.battleship.model.Board; 9 | import com.uditagarwal.game.battleship.model.boundary.IBoundary; 10 | import com.uditagarwal.game.battleship.model.Coordinate; 11 | import com.uditagarwal.game.battleship.model.BoardItem; 12 | import com.uditagarwal.game.battleship.strategy.DefaultWinnerStrategy; 13 | import com.uditagarwal.game.battleship.strategy.LocalChanceGeneration; 14 | import com.uditagarwal.game.battleship.strategy.RoundRobinPlayerPickingStrategy; 15 | import lombok.NonNull; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | public class Main { 21 | 22 | public static void main(String[] args) { 23 | 24 | final IInputProvider inputProvider = new SysInInputProvider(); 25 | List players = new ArrayList<>(); 26 | players.add(getPlayer1(inputProvider)); 27 | players.add(getPlayer2(inputProvider)); 28 | GameLoop gameLoop = new GameLoop( 29 | players, 30 | new DefaultWinnerStrategy(), 31 | new SysOutOutputPrinter(), 32 | new RoundRobinPlayerPickingStrategy()); 33 | gameLoop.start(); 34 | } 35 | 36 | private static Player getPlayer1(@NonNull final IInputProvider inputProvider) { 37 | final IBoundary boardBoundary = new RectangularBoundary(new Coordinate(0, 10), new Coordinate(10, 0)); 38 | 39 | BoardItem ship1 = new BoardItem("Carrier", new RectangularBoundary(new Coordinate(0, 7), new Coordinate(4,7))); 40 | BoardItem ship2 = new BoardItem("Battleship", new RectangularBoundary(new Coordinate(4, 1), new Coordinate(4,4))); 41 | BoardItem ship3 = new BoardItem("Cruiser", new RectangularBoundary(new Coordinate(7, 3), new Coordinate(7, 5))); 42 | BoardItem ship4 = new BoardItem("Destroyer", new RectangularBoundary(new Coordinate(4, 9), new Coordinate(6,9))); 43 | BoardItem ship5 = new BoardItem("Submarine", new RectangularBoundary(new Coordinate(3, 6), new Coordinate(4,3))); 44 | 45 | ArrayList ships = new ArrayList<>(); 46 | ships.add(ship1); 47 | ships.add(ship2); 48 | ships.add(ship3); 49 | ships.add(ship4); 50 | ships.add(ship5); 51 | 52 | Board board = new Board(ships, boardBoundary); 53 | 54 | return new Player(board, 1, new LocalChanceGeneration(inputProvider)); 55 | } 56 | 57 | private static Player getPlayer2(@NonNull final IInputProvider inputProvider) { 58 | final IBoundary boardBoundary = new RectangularBoundary(new Coordinate(0, 10), new Coordinate(10, 0)); 59 | 60 | BoardItem ship1 = new BoardItem("Carrier", new RectangularBoundary(new Coordinate(0, 7), new Coordinate(4,7))); 61 | BoardItem ship2 = new BoardItem("Battleship", new RectangularBoundary(new Coordinate(4, 1), new Coordinate(4,4))); 62 | BoardItem ship3 = new BoardItem("Cruiser", new RectangularBoundary(new Coordinate(7, 3), new Coordinate(7, 5))); 63 | BoardItem ship4 = new BoardItem("Destroyer", new RectangularBoundary(new Coordinate(4, 9), new Coordinate(6,9))); 64 | BoardItem ship5 = new BoardItem("Submarine", new RectangularBoundary(new Coordinate(3, 6), new Coordinate(4,3))); 65 | 66 | ArrayList ships = new ArrayList<>(); 67 | ships.add(ship1); 68 | ships.add(ship2); 69 | ships.add(ship3); 70 | ships.add(ship4); 71 | ships.add(ship5); 72 | 73 | Board board = new Board(ships, boardBoundary); 74 | 75 | return new Player(board, 2, new LocalChanceGeneration(inputProvider)); 76 | } 77 | } 78 | --------------------------------------------------------------------------------