Below problem statement was given to me and expectation was to come up with a proper working code for it.
BattleShip Game
Design and implement a battleship game to be played between two players until one comes out
as the winner.
Requirements:
● The game will be played in a square area of the sea with NxN grids which will be called
a battlefield. “N” should be taken as input in your code.
● The battlefield will be divided in half between both the players. So in a NxN battlefield,
NxN/2 grids will belong to PlayerA and the other NxN/2 grids will belong to playerB
● The size and location of each ship will be taken as input. Each ship will be assumed to
be of Square shape. Both the players should be assigned equal fleet.
● The location of each ship in the NxN grids has to be taken as input (X, Y). X and Y
should be integers. For eg. if a ship “SH1” is at (2, 2) and has the size of 4, its corners
will be at (0, 0), (0, 4), (4, 0) and (4,4)
● Ships will remain stationary. No two ships should overlap with each other. However they
can touch boundaries with each other.
● Each player will fire one missile towards the enemy field during his turn using the
“random coordinate fire” strategy, which means the missile will hit at a random
coordinate of the opponent’s field. It might hit or miss the opponent ship. In either case
the turn is then transferred to the other player.
○ In case of a hit, the opponent’s ship is destroyed.
○ In case of a miss, nothing happens.
● No two missiles should ever be fired at the same coordinates throughout the course
of the game.
● When all the ships of a particular player has been destroyed, he loses the game.
The following APIs have to be implemented:
Mandatory:
● initGame(N)
This will initialize the game with a battlefield of size NxN. Where the left half of
N/2xN will be assigned to PlayerA and the right half will be assigned to PlayerB
● addShip(id, size, x position PlayerA, y position PlayerA, x position PlayerB, y position
PlayerB)
This will add a ship of given size at the given coordinates in both the player’s
fleet.
● startGame()
This will begin the game, where PlayerA will always take the first turn. The output
of each step should be printed clearly in the console.
For eg.
PlayerA’s turn: Missile fired at (2, 4). “Hit”. PlayerB’s ship with id “SH1”
destroyed.
PlayerB’s turn: Missile fired at (6, 1). “Miss”
Optional
● viewBattleField()
This will display the battlefield as a NxN grid and all the ships along with the grids
occupied by each ship. PlayerA’s ship with id SH1 will be marked as A-SH1, with
id SH2 as A-SH2 and so on. Whereas PlayerB’s ships will be marked as B-SH1,
B-SH2 and so on.
Note: It should mark all the grids occupied by a ship and not just the center
coordinate.
Here is Java code for above problem. And I was asked to come up with schema and data base design as well.
import java.util.*;
class Ship {
private String name;
private int size;
private int x, y;
private Set<String> coordinates;
public Ship(String name, int size, int x, int y) {
this.name = name;
this.size = size;
this.x = x;
this.y = y;
this.coordinates = new HashSet<>();
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
coordinates.add((x + i) + "," + (y + j));
}
}
}
public Set<String> getCoordinates() {
return coordinates;
}
public String getName() {
return name;
}
}
class Player {
private String name;
private List<Ship> ships;
public Player(String name) {
this.name = name;
this.ships = new ArrayList<>();
}
public void addShip(Ship ship) {
ships.add(ship);
}
public String getName() {
return name;
}
public List<Ship> getShips() {
return ships;
}
}
class BattleShip {
private int N;
private char[][] battleField;
private Player playerA;
private Player playerB;
private boolean gameStarted;
public BattleShip() {
this.gameStarted = false;
}
public void initGame(int N) {
this.N = N;
this.battleField = new char[N][N];
for (char[] row : battleField) {
Arrays.fill(row, '.');
}
int half = N / 2;
playerA = new Player("Player A");
playerB = new Player("Player B");
gameStarted = false;
}
public Player getPlayerA() {
return playerA;
}
public Player getPlayerB() {
return playerB;
}
public void addShip(String id, int size, int xa, int ya, int xb, int yb) {
if (gameStarted) {
System.out.println("Game already started");
return;
}
Ship shipA = new Ship(id, size, xa, ya);
Ship shipB = new Ship(id, size, xb, yb);
playerA.addShip(shipA);
playerB.addShip(shipB);
for (String coord : shipA.getCoordinates()) {
String[] parts = coord.split(",");
int x = Integer.parseInt(parts[0]);
int y = Integer.parseInt(parts[1]);
battleField[x][y] = 'A';
}
for (String coord : shipB.getCoordinates()) {
String[] parts = coord.split(",");
int x = Integer.parseInt(parts[0]);
int y = Integer.parseInt(parts[1]);
battleField[x][y] = 'B';
}
}
public void startGame() {
if (!gameStarted) {
gameStarted = true;
System.out.println("Game started!");
} else {
System.out.println("Game already started!");
}
}
public void fireMissile(Player attacker, Player opponent) {
if (!gameStarted) {
System.out.println("Game has not started yet.");
return;
}
Random rand = new Random();
int x = rand.nextInt(N);
int y = rand.nextInt(N);
System.out.print(attacker.getName() + " fires missile at (" + x + "," + y + "). ");
boolean hit = false;
for (Ship ship : opponent.getShips()) {
for (String coord : ship.getCoordinates()) {
String[] parts = coord.split(",");
int shipX = Integer.parseInt(parts[0]);
int shipY = Integer.parseInt(parts[1]);
if (shipX == x && shipY == y) {
hit = true;
System.out.println("Hit! " + opponent.getName() + "'s ship with id " + ship.getName() + " destroyed.");
break;
}
}
if (hit) {
break;
}
}
if (!hit) {
System.out.println("Miss!");
}
}
public void viewBattleField() {
System.out.println("BattleField :");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(battleField[i][j] + " ");
}
System.out.println();
}
}
}
public class Main {
public static void main(String[] args) {
BattleShip game = new BattleShip();
game.initGame(10);
game.addShip("SH1", 2, 1, 1, 4, 4);
game.addShip("SH2", 3, 3, 3, 7, 7);
game.startGame();
Player playerA = game.getPlayerA();
Player playerB = game.getPlayerB();
game.fireMissile(playerA, playerB);
game.fireMissile(playerB, playerA);
game.viewBattleField();
}
}