Skip to content
Snippets Groups Projects
Commit a152b729 authored by Guyslain's avatar Guyslain
Browse files

More refactoring, several simulations added

parent 669a2a62
No related branches found
No related tags found
No related merge requests found
......@@ -23,5 +23,5 @@ test {
}
application {
mainClassName = "GameOfLifeApplication"
mainClassName = "SimulatorApplication"
}
\ No newline at end of file
......@@ -5,12 +5,13 @@ import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import model.CellGrid;
import model.CellularAutomataSimulation;
import model.GameOfLifeState;
import model.CellularAutomatonSimulation;
import model.states.BriansBrainState;
import model.states.SeedsState;
import java.io.IOException;
import java.net.URL;
import java.util.Random;
import static java.util.Objects.requireNonNull;
......@@ -18,38 +19,33 @@ import static java.util.Objects.requireNonNull;
* Entry point for <i>The Game of Life</i> application.
*
*/
public class GameOfLifeApplication extends Application {
public class SimulatorApplication extends Application {
private static final int NUMBER_OF_ROWS = 40;
private static final int NUMBER_OF_COLUMNS = 70;
public static final int NUMBER_OF_ROWS = 40;
public static final int NUMBER_OF_COLUMNS = 70;
public static final Random GENERATOR = new Random();
private static final String APP_NAME = "Game of Life";
private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
private final CellularAutomataSimulation<GameOfLifeState> gameOfLife;
private final CellularAutomatonSimulation<SeedsState> gameOfLife;
private Stage primaryStage;
private Parent view;
/**
* Creates a new {@code GameOfLifeApplication} instance.
*/
public GameOfLifeApplication() {
this(new CellularAutomataSimulation<GameOfLifeState>(
new CellGrid<>(NUMBER_OF_COLUMNS, NUMBER_OF_ROWS, GameOfLifeState.ALIVE),
GameOfLifeState.DEAD,
GameOfLifeState::random
));
public SimulatorApplication() {
this.gameOfLife =
new CellularAutomatonSimulation<>(
NUMBER_OF_COLUMNS,
NUMBER_OF_ROWS,
SeedsState.OFF,
SeedsState::random
);
}
/**
* Creates a new {@code GameOfLifeApplication} instance given a {@link CellularAutomataSimulation} instance.
*
* @param cellularAutomataSimulation the {@link CellularAutomataSimulation} instance
* @throws NullPointerException if {@code gameOfLife} is {@code null}
*/
private GameOfLifeApplication(CellularAutomataSimulation<GameOfLifeState> cellularAutomataSimulation) {
this.gameOfLife = requireNonNull(cellularAutomataSimulation, "game of life is null");
}
@Override
public void start(Stage primaryStage) throws IOException {
......@@ -68,7 +64,7 @@ public class GameOfLifeApplication extends Application {
private void initializeView() throws IOException {
FXMLLoader loader = new FXMLLoader();
URL location = GameOfLifeApplication.class.getResource(VIEW_RESOURCE_PATH);
URL location = SimulatorApplication.class.getResource(VIEW_RESOURCE_PATH);
loader.setLocation(location);
view = loader.load();
Controller controller = loader.getController();
......
......@@ -11,7 +11,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.util.Duration;
import model.CellularAutomataSimulation;
import model.CellularAutomatonSimulation;
import view.MatrixPane;
import static java.util.Objects.requireNonNull;
......@@ -52,9 +52,9 @@ public class Controller {
/**
* Sets {@link CellularAutomataSimulation} instance.
* Sets {@link CellularAutomatonSimulation} instance.
*
* @param simulation {@link CellularAutomataSimulation} instance
* @param simulation {@link CellularAutomatonSimulation} instance
* @throws NullPointerException if {@code gameOfLife} is {@code null}
*/
......
......@@ -50,7 +50,7 @@ public class Matrix<T> {
public Iterator<T> iterator() {
Iterator<Coordinate> coordIterator = this.coordinatesIterator();
return new MatrixIterator(this, coordIterator);
return new MatrixIterator<>(this, coordIterator);
}
public Iterable<Coordinate> coordinates() {
......
......@@ -107,7 +107,7 @@ public class CellGrid<S extends State<S>> implements Iterable<Cell<S>> {
return new Matrix<>(
this.numberOfColumns,
this.numberOfRows,
new OneStepMatrixInitializer<>(this)
new NextGenerationInitializer<>(this)
);
}
......
......@@ -12,29 +12,31 @@ import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
/**
* {@link CellularAutomataSimulation} instances run <i>The Game of Life</i>.
* {@link CellularAutomatonSimulation} instances run <i>The Game of Life</i>.
*/
public class CellularAutomataSimulation<S extends State<S>>
public class CellularAutomatonSimulation<S extends State<S>>
implements Simulation {
private final CellGrid<S> grid;
private final Supplier<S> supplier;
private final Supplier<S> randomState;
private final S defaultState;
private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper();
/**
* Creates a new {@code GameOfLife} instance given the underlying {@link CellGrid}.
* Creates a new {@code CellularAutomataSimulation} instance for a given automaton.
*
* @param grid the underlying {@link CellGrid}
* @param defaultState the state value to use when clearing the grid
* @param supplier a {@Link Supplier} to produce values to initialize or reset the grid
* @throws NullPointerException if {@code grid} is {@code null}
* @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 CellularAutomataSimulation(CellGrid<S> grid, S defaultState, Supplier<S> supplier) {
this.grid = requireNonNull(grid, "grid is null");
this.supplier = requireNonNull(supplier, "supplier is null");
this.defaultState = requireNonNull(defaultState, "defaultState is null");
grid.fillRandomly(this.supplier);
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);
}
......@@ -54,8 +56,8 @@ public class CellularAutomataSimulation<S extends State<S>>
*/
@Override
public void updateToNextGeneration() {
grid.updateToNextGeneration();
generationNumber.set(getGenerationNumber() + 1);
this.grid.updateToNextGeneration();
this.generationNumber.set(getGenerationNumber() + 1);
}
@Override
......@@ -88,7 +90,7 @@ public class CellularAutomataSimulation<S extends State<S>>
* @return the current generationNumber
*/
private long getGenerationNumber() {
return generationNumber.get();
return this.generationNumber.get();
}
/**
......@@ -97,7 +99,7 @@ public class CellularAutomataSimulation<S extends State<S>>
* @return the generationNumber {@link ReadOnlyLongProperty}
*/
public ReadOnlyLongProperty generationNumberProperty() {
return generationNumber.getReadOnlyProperty();
return this.generationNumber.getReadOnlyProperty();
}
......@@ -105,16 +107,16 @@ public class CellularAutomataSimulation<S extends State<S>>
* Clears the current game.
*/
public void clear() {
grid.clear(defaultState);
generationNumber.set(0);
this.grid.clear(this.defaultState);
this.generationNumber.set(0);
}
/**
* Clears the current game and randomly generates a new one.
*/
public void reset() {
clear();
grid.fillRandomly(supplier);
this.clear();
this.grid.fillRandomly(this.randomState);
}
@Override
......
......@@ -6,11 +6,11 @@ import datastruct.MatrixInitializer;
import java.util.ArrayList;
import java.util.List;
public class OneStepMatrixInitializer<S extends State<S>> implements MatrixInitializer<S> {
public class NextGenerationInitializer<S extends State<S>> implements MatrixInitializer<S> {
private final CellGrid<S> grid;
public OneStepMatrixInitializer(CellGrid<S> grid) {
public NextGenerationInitializer(CellGrid<S> grid) {
this.grid = grid;
}
......
package model.states;
import javafx.scene.paint.Color;
import model.State;
import java.util.List;
import java.util.Random;
public enum BiColorState implements State<BiColorState> {
BLUE, RED, DEAD;
@Override
public Color getColor() {
return switch (this) {
case BLUE -> Color.BLUE;
case RED -> Color.RED;
case DEAD -> Color.WHITE;
};
}
@Override
public BiColorState next() {
return switch (this) {
case BLUE -> RED;
case RED -> DEAD;
case DEAD -> BLUE;
};
}
@Override
public BiColorState update(List<State<BiColorState>> neighbours) {
int countBlue = 0;
int countRed = 0;
for (State<BiColorState> neighbour : neighbours) {
if (neighbour == RED) {
countRed++;
}
if (neighbour == BLUE) {
countBlue++;
}
}
if (this == DEAD) {
return (countBlue + countRed != 3)? DEAD:
countBlue > countRed? BLUE:
RED;
}
return 2 <= countBlue + countRed && countBlue + countRed <= 3? this:
DEAD;
}
private final static Random generator = new Random();
public static BiColorState random() {
return generator.nextBoolean()? DEAD:
generator.nextBoolean()? RED:
BLUE;
}
}
package model.states;
import javafx.scene.paint.Color;
import model.State;
import java.util.List;
import java.util.Random;
public enum BriansBrainState implements State<BriansBrainState> {
ON, OFF, DYING;
@Override
public Color getColor() {
return switch (this) {
case ON -> Color.WHITE;
case OFF -> Color.BLACK;
case DYING -> Color.BLUE;
};
}
@Override
public BriansBrainState next() {
return switch (this) {
case ON -> DYING;
case OFF -> ON;
case DYING -> OFF;
};
}
@Override
public BriansBrainState update(List<State<BriansBrainState>> neighbours) {
return switch (this) {
case ON -> DYING;
case DYING -> OFF;
case OFF -> {
int count = countList(ON, neighbours);
yield count==2 ? ON : OFF;
}
};
}
static <T> int countList(T value, List<T> elements) {
int count = 0;
for (T v : elements) {
if (v.equals(value)) {
count++;
}
}
return count;
}
final static Random GENERATOR = new Random();
public static BriansBrainState random() {
return GENERATOR.nextInt(10) == 0 ? ON: OFF;
}
}
package model;
package model.states;
import javafx.scene.paint.Color;
import model.State;
import java.util.List;
import java.util.Random;
......
package model.states;
import javafx.scene.paint.Color;
import model.State;
import java.util.List;
import static model.states.BriansBrainState.GENERATOR;
import static model.states.BriansBrainState.countList;
public enum SeedsState implements State<SeedsState> {
ON, OFF;
@Override
public Color getColor() {
return switch (this) {
case ON -> Color.WHITE;
case OFF -> Color.BLACK;
};
}
@Override
public SeedsState next() {
return switch (this) {
case ON -> OFF;
case OFF -> ON;
};
}
@Override
public SeedsState update(List<State<SeedsState>> neighbours) {
return switch (this) {
case ON -> OFF;
case OFF -> countList(ON,neighbours) == 2 ? ON: OFF;
};
}
public static SeedsState random() {
return GENERATOR.nextInt(10)==0? ON: OFF;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment