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

More refactoring, several simulations added

parent 669a2a62
Branches
Tags
No related merge requests found
Pipeline #19847 passed
......@@ -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