Newer
Older
package model;
import controller.Simulation;
import datastruct.Coordinate;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.scene.paint.Color;
import java.util.Iterator;
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
/**
* {@link CellularAutomatonSimulation} instances run <i>The Game of Life</i>.
public class CellularAutomatonSimulation<S extends State<S>>
private final Supplier<S> randomState;
private final S defaultState;
private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper();
/**
* Creates a new {@code CellularAutomataSimulation} instance for a given automaton.
* @param width an {@code int} representing the number of columns
* @param height an {@code int} representing the number of rows
* @param defaultState a state {@code S} used to fill the grid when using
* the clear action
* @param randomState a generator of states {@code} used to fill the grid
* when using the reset action
public CellularAutomatonSimulation(int width, int height, S defaultState, Supplier<S> randomState) {
this.grid = new CellGrid<>(width, height, defaultState);
this.defaultState = defaultState;
this.randomState = randomState;
grid.fillRandomly(randomState);
}
@Override
public int numberOfColumns() {
return this.grid.getNumberOfColumns();
}
@Override
public int numberOfRows() {
return this.grid.getNumberOfRows();
}
/**
* Transitions into the next generationNumber.
*/
@Override
public void updateToNextGeneration() {
this.grid.updateToNextGeneration();
this.generationNumber.set(getGenerationNumber() + 1);
}
@Override
public void next(Coordinate coordinate) {
this.grid.cellAt(coordinate).toggleState();
}
@Override
public void copy(Coordinate source, Coordinate destination) {
S state = this.grid.at(source).get();
this.grid.at(destination).set(state);
}
@Override
public Color getColor(Coordinate coordinate) {
return this.grid.at(coordinate).get().getColor();
}
@Override
public void setChangeListener(Coordinate coordinate, Runnable runnable) {
this.grid.cellAt(coordinate).getStateProperty().addListener(
(obs,oldV,newV) -> runnable.run()
);
}
/**
* Returns the current generationNumber.
*
* @return the current generationNumber
*/
private long getGenerationNumber() {
return this.generationNumber.get();
}
/**
* Returns the generationNumber {@link ReadOnlyLongProperty}.
*
* @return the generationNumber {@link ReadOnlyLongProperty}
*/
public ReadOnlyLongProperty generationNumberProperty() {
return this.generationNumber.getReadOnlyProperty();
}
/**
* Clears the current game.
*/
public void clear() {
this.grid.clear(this.defaultState);
this.generationNumber.set(0);
}
/**
* Clears the current game and randomly generates a new one.
*/
public void reset() {
this.clear();
this.grid.fillRandomly(this.randomState);