Reputation: 1005
I'm trying to create the game SeaBattle in Java, see the class diagram below.
The visual representation of the ships on the grid happens by giving the cells of the field the ship covers a dark color.
In order to place a ship, I will call it's segments place()-method and give it it's coordinates. To make it easy to fetch the right segment later on when it is selected by clicking on the cell it's placed on, I figured it would be best if the cell would contain a reference to this same segment.
The implementation problem I'm facing lies in the removal of ships: it should be possible to remove a ship on command of the ship (easy: loop through it's segments and unplace them, also remove their reference in the cell they were in), but it should also be possible to do so by clicking on the ship (that is: on one of it's segments in the grid). Whenever this happens I know what segment was clicked, but I need to figure out what ship this segment belongs to in order to unplace the other segments aswell.
I could take the clicked cells coordinates, loop through all the ships and their segments and check if the coordinates match, but I feel like there would be a better approach to this. Maybe it would even be better set up part of the class diagram differently.
Example of what the visual representation might look like:
Upvotes: 1
Views: 498
Reputation: 6081
We can add Ship
field to ShipSegment
and make ShipSegment
a subclass of Cell
. Here is one possible implementation:
public class Battlefield {
Cell[][] cells;
public Battlefield(int size) {
this.cells = new Cell[size][size];
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
cells[x][y] = new Cell();
}
}
}
public void add(Ship ship) {
int start = ship.horizontal ? ship.x : ship.y;
for (int i = 0; i < ship.size(); i++) {
cells[ship.horizontal ? i + start : ship.x][ship.horizontal ? ship.y : i + start] = ship.getSegment(i);
}
}
public void remove(Ship ship) {
int start = ship.horizontal ? ship.x : ship.y;
for (int i = start; i < start + ship.size(); i++) {
cells[ship.horizontal ? i : ship.x][ship.horizontal ? ship.y : i] = new Cell();
}
}
public boolean shoot(int x, int y) {
return cells[x][y].shoot();
}
}
public class Cell {
private boolean isShot;
public Cell() {
this.isShot = false;
}
public boolean isEmpty(){
return true;
}
public boolean isShot(){
return isShot;
}
public boolean shoot() {
isShot = true;
return isEmpty();
}
}
public class ShipSegment extends Cell {
Ship ship;
public ShipSegment(Ship ship) {
super();
this.ship = ship;
}
@Override
public boolean isEmpty() {
return false;
}
public Ship getShip() {
return ship;
}
}
public class Ship {
int x, y;
boolean horizontal;
ShipSegment[] segments;
public Ship(int x, int y, int size, boolean horizontal) {
this.x = x;
this.y = y;
this.horizontal = horizontal;
segments = new ShipSegment[size];
for (int i = 0; i < size; i++) {
segments[i] = new ShipSegment(this);
}
}
public int size() {
return segments.length;
}
public boolean isDestroyed() {
for (ShipSegment segment : segments) {
if (!segment.isShot()) {
return false;
}
}
return true;
}
public ShipSegment getSegment(int index){
return segments[index];
}
}
Upvotes: 1