Newer
Older
/**
* {@code Grid} instances represent the grid in <i>The Game of Life</i>.
*/
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
public class Grid implements Iterable<Cell> {
private final int numberOfRows;
private final int numberOfColumns;
private final Cell[][] cells;
/**
* Creates a new {@code Grid} instance given the number of rows and columns.
*
* @param numberOfRows the number of rows
* @param numberOfColumns the number of columns
* @throws IllegalArgumentException if {@code numberOfRows} or {@code numberOfColumns} are
* less than or equal to 0
*/
public Grid(int numberOfRows, int numberOfColumns) {
this.numberOfRows = numberOfRows;
this.numberOfColumns = numberOfColumns;
this.cells = createCells();
}
@Override
public Iterator<Cell> iterator() {
return new GridIterator(this);
}
private Cell[][] createCells() {
Cell[][] cells = new Cell[getNumberOfRows()][getNumberOfColumns()];
for (int rowIndex = 0; rowIndex < getNumberOfRows(); rowIndex++) {
for (int columnIndex = 0; columnIndex < getNumberOfColumns(); columnIndex++) {
cells[rowIndex][columnIndex] = new Cell();
}
}
return cells;
}
/**
* Returns the {@link Cell} at the given index.
*
* <p>Note that the index is wrapped around so that a {@link Cell} is always returned.
*
* @param rowIndex the row index of the {@link Cell}
* @param columnIndex the column index of the {@link Cell}
* @return the {@link Cell} at the given row and column index
*/
public Cell getCell(int rowIndex, int columnIndex) {
return cells[getWrappedRowIndex(rowIndex)][getWrappedColumnIndex(columnIndex)];
}
private int getWrappedRowIndex(int rowIndex) {
return (rowIndex + getNumberOfRows()) % getNumberOfRows();
}
private int getWrappedColumnIndex(int columnIndex) {
return (columnIndex + getNumberOfColumns()) % getNumberOfColumns();
}
/**
* Returns the number of rows in this {@code Grid}.
*
* @return the number of rows in this {@code Grid}
*/
public int getNumberOfRows() {
return numberOfRows;
}
/**
* Returns the number of columns in this {@code Grid}.
*
* @return the number of columns in this {@code Grid}
*/
public int getNumberOfColumns() {
return numberOfColumns;
}
/**
* Transitions all {@link Cell}s in this {@code Grid} to the next generation.
*
* <p>The following rules are applied:
* <ul>
* <li>Any live {@link Cell} with fewer than two live neighbours dies, i.e. underpopulation.</li>
* <li>Any live {@link Cell} with two or three live neighbours lives on to the next generation.</li>
* <li>Any live {@link Cell} with more than three live neighbours dies, i.e. overpopulation.</li>
* <li>Any dead {@link Cell} with exactly three live neighbours becomes a live cell, i.e. reproduction.</li>
* </ul>
*/
void nextGeneration() {
goToNextState(calculateNextStates());
}
private boolean[][] calculateNextStates() {
boolean [][] nextState = new boolean[getNumberOfRows()][getNumberOfColumns()];
for(int rowIndex=0; rowIndex<getNumberOfRows(); rowIndex++){
for (int columnIndex = 0; columnIndex < getNumberOfColumns(); columnIndex++) {
nextState[rowIndex][columnIndex] = calculateNextState(rowIndex,columnIndex);
}
}
return nextState;
private boolean calculateNextState(int rowIndex, int columnIndex) {
Cell cell = getCell(rowIndex, columnIndex);
int numberOfAliveNeighbours = countAliveNeighbours(rowIndex, columnIndex);
return cell.isAliveInNextState(numberOfAliveNeighbours);
}
private int countAliveNeighbours(int rowIndex, int columnIndex) {
List<Cell> neighboursList = getNeighbours(rowIndex, columnIndex);
Iterator<Cell> iterator = neighboursList.iterator();
int counter = 0;
while(iterator.hasNext()) {
if(iterator.next().isAlive())
counter++;
}
return counter;
}
private boolean aliveNeighboursMajColor(int rowIndex, int columnIndex){
List<Cell> neighboursList = getNeighbours(rowIndex, columnIndex);
int count = countAliveNeighbours(rowIndex, columnIndex);
Iterator<Cell> iterator = neighboursList.iterator();
int redCount = 0;
while(iterator.hasNext()) {
Cell cell = iterator.next();
if (cell.isAlive() && cell.isRed())
redCount++;
}
return (redCount>(count/2));
}
private List<Cell> getNeighbours(int rowIndex, int columnIndex) {
List<Cell> neighboursList = new ArrayList<Cell>();
neighboursList.add(getCell(rowIndex, columnIndex+1));
neighboursList.add(getCell(rowIndex, columnIndex-1));
neighboursList.add(getCell(rowIndex+1, columnIndex));
neighboursList.add(getCell(rowIndex-1, columnIndex));
neighboursList.add(getCell(rowIndex+1, columnIndex+1));
neighboursList.add(getCell(rowIndex+1, columnIndex-1));
neighboursList.add(getCell(rowIndex-1, columnIndex+1));
neighboursList.add(getCell(rowIndex-1, columnIndex-1));
return neighboursList;
}
private void goToNextState(boolean[][] nextState) {
for(int rowIndex=0; rowIndex<this.numberOfRows; rowIndex++) {
for (int columnIndex = 0; columnIndex < this.numberOfColumns; columnIndex++) {
Cell cell = getCell(rowIndex, columnIndex);
if (nextState[rowIndex][columnIndex]) {
if(cell.isDead()) {
boolean redColor = aliveNeighboursMajColor(rowIndex, columnIndex);
cell.setisRed(redColor);
}
cell.setAlive();
}else{
cell.setDead();
}
}
}
}
/**
* Sets all {@link Cell}s in this {@code Grid} as dead.
*/
void clear() {
for (Iterator<Cell> gridIt = iterator(); gridIt.hasNext(); ) {
Cell cell = gridIt.next();
cell.setDead();
}
}
/**
* Goes through each {@link Cell} in this {@code Grid} and randomly sets it as alive or dead.
*
* @param random {@link Random} instance used to decide if each {@link Cell} is alive or dead
* @throws NullPointerException if {@code random} is {@code null}
*/
Iterator<Cell> gridIt = iterator();
while (gridIt.hasNext()) {
Cell cell = gridIt.next();
boolean randomStat = random.nextBoolean();
if (randomStat) {
cell.setAlive();
randomStat = random.nextBoolean();
if (randomStat)
cell.setisRed(true);
else
cell.setisRed(false);
}else {
cell.setDead();
}
}
// Spaceships Test
/*
Cell cell0 = getCell(1,1);
Cell cell1 = getCell(2,2);
Cell cell2 = getCell(1,3);
Cell cell3 = getCell(2,3);
Cell cell4 = getCell(3,2);
cell0.setAlive();cell1.setAlive();cell2.setAlive();cell3.setAlive();cell4.setAlive();
*/