Update Getting iterateable neighbours is pretty easy when you introduce a NullObject for nonexisting cells. (This is also helpful at other places.)
public class Grid
{
//...
protected Cell getCell(int x, int y) {
if (x < 1 || x > getWidth())
return Cell.NULL;
if (y < 1 || y > getHeight())
return Cell.NULL;
return cells[x][y];
}
protected boolean placeBomb(int x, int y) {
if (!getCell(x, y).placeBomb())
return false;
for (Cell c : getNeighbours(x, y))
c.incrementBombCount();
return true;
}
public Set<Cell> getNeighbours(int x, int y) {
Set<Cell> neighbours = new HashSet<>();
neighbours.add(getCell(x - 1, y - 1));
neighbours.add(getCell(x, y - 1));
neighbours.add(getCell(x + 1, y - 1));
neighbours.add(getCell(x - 1, y));
neighbours.add(getCell(x + 1, y));
neighbours.add(getCell(x - 1, y + 1));
neighbours.add(getCell(x, y + 1));
neighbours.add(getCell(x + 1, y + 1));
neighbours.remove(Cell.NULL);
return neighbours;
}
}
And the cell class:
public class Cell {
public static Cell NULL = new NullCell();
public static class NullCell extends Cell {
private NullCell() {
super(null, -1, -1);
}
@Override
public Set<Cell> getNeighbours() {
return Collections.emptySet();
}
@Override
public boolean placeBomb() {
return false;
}
//...
}
private final Grid grid;
private final int x;
private final int y;
private VisualState state = VisualState.HIDDEN;
private boolean bomb = false;
private int bombCount = 0;
public Cell(Grid grid, int x, int y) {
this.grid = grid;
this.x = x;
this.y = y;
}
public Set<Cell> getNeighbours() {
return grid.getNeighbours(x, y);
}
//...
}