diff --git a/src/main/java/SimulatorApplication.java b/src/main/java/SimulatorApplication.java index fb22b7fa214f754ce32107eeab41b537783adde7..0fed297543cac4bfb5ea3722d445cbc71aea4745 100644 --- a/src/main/java/SimulatorApplication.java +++ b/src/main/java/SimulatorApplication.java @@ -1,4 +1,5 @@ import controller.Controller; +import controller.Simulation; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; @@ -6,8 +7,9 @@ import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import model.CellularAutomatonSimulation; -import model.states.BriansBrainState; -import model.states.SeedsState; +import model.automata.BriansBrainAutomaton; +import model.automata.GameOfLifeAutomaton; +import model.automata.SeedsAutomaton; import java.io.IOException; import java.net.URL; @@ -26,10 +28,10 @@ public class SimulatorApplication extends Application { public static final Random GENERATOR = new Random(); - private static final String APP_NAME = "Game of Life"; + private static final String APP_NAME = "2D Cellular automata"; private static final String VIEW_RESOURCE_PATH = "/view/view.fxml"; - private final CellularAutomatonSimulation<SeedsState> gameOfLife; + private final Simulation simulation; private Stage primaryStage; private Parent view; @@ -37,12 +39,10 @@ public class SimulatorApplication extends Application { * Creates a new {@code GameOfLifeApplication} instance. */ public SimulatorApplication() { - this.gameOfLife = + this.simulation = new CellularAutomatonSimulation<>( - NUMBER_OF_COLUMNS, - NUMBER_OF_ROWS, - SeedsState.OFF, - SeedsState::random + new SeedsAutomaton(NUMBER_OF_COLUMNS,NUMBER_OF_ROWS), + GENERATOR ); } @@ -68,7 +68,7 @@ public class SimulatorApplication extends Application { loader.setLocation(location); view = loader.load(); Controller controller = loader.getController(); - controller.setSimulation(gameOfLife); + controller.setSimulation(simulation); } diff --git a/src/main/java/controller/Simulation.java b/src/main/java/controller/Simulation.java index cf784ea9b705261e6c5bfce6289366aea53f427a..674a0fd910b383cc55a0ba0e1245ce5309a45499 100644 --- a/src/main/java/controller/Simulation.java +++ b/src/main/java/controller/Simulation.java @@ -3,6 +3,7 @@ package controller; import datastruct.Coordinate; import javafx.beans.property.ReadOnlyLongProperty; import javafx.scene.paint.Color; +import model.OnChangeListener; public interface Simulation extends Iterable<Coordinate> { @@ -17,7 +18,7 @@ public interface Simulation extends Iterable<Coordinate> { Color getColor(Coordinate coordinate); - void setChangeListener(Coordinate coordinate, Runnable run); + void setChangeListener(Coordinate coordinate, Runnable listener); ReadOnlyLongProperty generationNumberProperty(); diff --git a/src/main/java/datastruct/Matrix.java b/src/main/java/datastruct/Matrix.java index dbe33a03b2dd82a50856d2626baf196b852e3ec6..9290fa6d835f82b5566626e33507713bf2bf1852 100644 --- a/src/main/java/datastruct/Matrix.java +++ b/src/main/java/datastruct/Matrix.java @@ -4,9 +4,11 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class Matrix<T> { +public class Matrix<T> implements Iterable<T> { private final List<List<T>> matrix; + + private final int width; private final int height; @@ -31,6 +33,13 @@ public class Matrix<T> { } } + public int width() { + return width; + } + + public int height() { + return height; + } public T get(int x, int y) { return this.matrix.get(x).get(y); } diff --git a/src/main/java/model/Cell.java b/src/main/java/model/Cell.java index 26bf67856b8a09a842e04b800699478daeb08089..7da6824291fbca70781a2ca2dadfdaba1b3bfb12 100644 --- a/src/main/java/model/Cell.java +++ b/src/main/java/model/Cell.java @@ -1,67 +1,50 @@ package model; -import javafx.beans.property.Property; -import javafx.beans.property.SimpleObjectProperty; -import javafx.scene.paint.Color; +import datastruct.Lens; + +import java.util.ArrayList; +import java.util.List; /** - * {@link Cell} instances represent the cells of <i>The Game of Life</i>. + * {@link Cell} instances represent the cells of the grid in a simulation of cellular automata. */ -public class Cell<S extends State<S>> { - private final Property<S> stateProperty; - - public Cell(S initialState) { - this.stateProperty = new SimpleObjectProperty<>(initialState); - } +public class Cell<T> implements Lens<T> { + private T content; + private final List<OnChangeListener<T>> listeners = new ArrayList<>(); - /** - * Determines the color associated with the state in which - * this {@link Cell} is. + /** Initialize a new cell with a given value. * - * @return the {@link Color} associated with the state in - * which this {@link Cell} is + * @param initialContent the value initially stored by the cell. */ - - public Color getColor() { - return this.getState().getColor(); + public Cell(T initialContent) { + this.content = initialContent; } - /** - * Sets the state of this {@link Cell}. - * - * @param state the new state of this {@link Cell} - */ - - public void setState(S state) { - getStateProperty().setValue(state); + public void addOnChangeListener(OnChangeListener<T> listener) { + this.listeners.add(listener); } /** - * Returns the current state of this {@link Cell}. + * Sets the content of this {@link Cell}. * - * @return the current state of this {@link Cell} - */ - - public S getState(){ - return getStateProperty().getValue(); - } - - /** - * Change the state of this {@link Cell} to the next possible state. + * @param value the new content of this {@link Cell} */ - - public void toggleState() { - setState(getState().next()); + public void set(T value) { + this.content = value; + for (OnChangeListener<T> listener : this.listeners) { + listener.valueChanged(this.content, value); + } } /** - * Returns this {@link Cell}'s state property. + * Returns the current content of this {@link Cell}. * - * @return this {@link Cell}'s state property. + * @return the current content of this {@link Cell} */ - public Property<S> getStateProperty() { - return stateProperty; + public T get(){ + return this.content; } + } diff --git a/src/main/java/model/CellGrid.java b/src/main/java/model/CellGrid.java deleted file mode 100644 index 5df1fb5322c6368e93a15f2d4bac4c32e4b65f10..0000000000000000000000000000000000000000 --- a/src/main/java/model/CellGrid.java +++ /dev/null @@ -1,160 +0,0 @@ -package model; - -import datastruct.Coordinate; -import datastruct.Lens; -import datastruct.Matrix; - -import java.util.Iterator; -import java.util.function.Supplier; - - -/** - * {@link CellGrid} instances represent the grid in <i>The Game of Life</i>. - */ -public class CellGrid<S extends State<S>> implements Iterable<Cell<S>> { - - private final int numberOfRows; - private final int numberOfColumns; - private final Matrix<Cell<S>> cells; - - /** - * Creates a new {@code Grid} instance given the number of rows and columns. - * - * @param numberOfColumns the number of columns - * @param numberOfRows the number of rows - * @throws IllegalArgumentException if {@code numberOfRows} or {@code numberOfColumns} are - * less than or equal to 0 - */ - public CellGrid(int numberOfColumns, int numberOfRows, S defaultState) { - this.numberOfRows = numberOfRows; - this.numberOfColumns = numberOfColumns; - this.cells = new Matrix<>(numberOfColumns, numberOfRows, coord -> new Cell<>(defaultState)); - } - - - public boolean contains(Coordinate coordinate) { - return (coordinate.x() >= 0) - && (coordinate.x() < this.numberOfColumns) - && (coordinate.y() > 0) - && (coordinate.y() <= this.numberOfRows); - } - - - /** - * Returns an iterator over the cells in this {@code Grid}. - * - * @return an iterator over the cells in this {@code Grid} - */ - @Override - public Iterator<Cell<S>> iterator() { - return this.cells.iterator(); - } - - public Iterable<Coordinate> coordinates() { - return this.cells.coordinates(); - } - - public Lens<S> at(Coordinate coord) { - return new CellLens<>(this.cellAt(coord)); - } - - - public Cell<S> cellAt(Coordinate coord) { - return this.cells.at(coord).get(); - } - - private Coordinate wrap(Coordinate coordinate) { - return new Coordinate( - modulo(coordinate.x(), getNumberOfColumns()), - modulo(coordinate.y(), getNumberOfRows()) - ); - } - - private static int modulo(int n, int d) { - int result = n % d; - return n < 0 ? result + d : result; - } - public Lens<S> atWrapped(Coordinate coord) { - return this.at(wrap(coord)); - } - - public Cell<S> cellAtWrapped(Coordinate coord) { - return this.cellAt(wrap(coord)); - } - - /** - * 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; - } - - - - - private Matrix<S> nextGenerationMatrix() { - return new Matrix<>( - this.numberOfColumns, - this.numberOfRows, - new NextGenerationInitializer<>(this) - ); - } - - /** - * 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> - */ - // TODO: Écrire une version correcte de cette méthode. - public void updateToNextGeneration() { - Matrix<S> nextStates = this.nextGenerationMatrix(); - for (Coordinate coordinate : this.coordinates()) { - this.cellAt(coordinate).setState(nextStates.get(coordinate)); - } - } - - - /** - * Sets all {@link Cell}s in this {@code Grid} as dead. - */ - // TODO: Écrire une version correcte de cette méthode. - public void clear(S clearState) { - for (Cell<S> cell : this) { - cell.setState(clearState); - } - } - - - /** - * Goes through each {@link Cell} in this {@code Grid} and sets it states with a - * state obtained from the supplier. - * - * @param supplier {@link Supplier} instance used to decide a state for each cell {@link Cell}. - * @throws NullPointerException if {@code supplier} is {@code null}. - */ - // TODO: Écrire une version correcte de cette méthode. - public void fillRandomly(Supplier<S> supplier) { - for (Cell<S> cell : this) { - cell.setState(supplier.get()); - } - } -} diff --git a/src/main/java/model/CellLens.java b/src/main/java/model/CellLens.java deleted file mode 100644 index f9ab4958ce59046b7ce83fb31d0699e695889872..0000000000000000000000000000000000000000 --- a/src/main/java/model/CellLens.java +++ /dev/null @@ -1,22 +0,0 @@ -package model; - -import datastruct.Lens; - -public class CellLens<S extends State<S>> implements Lens<S> { - - private final Cell<S> cell; - - public CellLens(Cell<S> cell) { - this.cell = cell; - } - - @Override - public S get() { - return cell.getState(); - } - - @Override - public void set(S value) { - cell.setState(value); - } -} diff --git a/src/main/java/model/CellularAutomaton.java b/src/main/java/model/CellularAutomaton.java new file mode 100644 index 0000000000000000000000000000000000000000..92b83c4e296bf10fcefd8d20e627871a2127a95e --- /dev/null +++ b/src/main/java/model/CellularAutomaton.java @@ -0,0 +1,10 @@ +package model; + +import java.util.Random; + +public interface CellularAutomaton<S extends State<S>> { + int numberOfColumns(); + int numberOfRows(); + S defaultState(); + S randomState(Random generator); +} diff --git a/src/main/java/model/CellularAutomatonSimulation.java b/src/main/java/model/CellularAutomatonSimulation.java index 8bd51b3b0b3dd8716d78b5e928b8d00054acfe75..aa7404c84cf17b1d4a7c926035892bb6451b0104 100644 --- a/src/main/java/model/CellularAutomatonSimulation.java +++ b/src/main/java/model/CellularAutomatonSimulation.java @@ -2,14 +2,15 @@ package model; import controller.Simulation; import datastruct.Coordinate; +import datastruct.Matrix; import javafx.beans.property.ReadOnlyLongProperty; import javafx.beans.property.ReadOnlyLongWrapper; import javafx.scene.paint.Color; - import java.util.Iterator; +import java.util.Random; import java.util.function.Supplier; -import static java.util.Objects.requireNonNull; + /** * {@link CellularAutomatonSimulation} instances run <i>The Game of Life</i>. @@ -17,69 +18,94 @@ import static java.util.Objects.requireNonNull; public class CellularAutomatonSimulation<S extends State<S>> implements Simulation { - private final CellGrid<S> grid; - private final Supplier<S> randomState; - private final S defaultState; + private final Matrix<Cell<S>> grid; private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper(); + private final CellularAutomaton<S> automaton; + private final Random generator; /** - * Creates a new {@code CellularAutomataSimulation} instance for a given automaton. + * Creates a new {@link CellularAutomatonSimulation} 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 + * @param automaton a description of the {@link CellularAutomaton} */ - 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); + public CellularAutomatonSimulation(CellularAutomaton<S> automaton, Random generator) { + this.automaton = automaton; + this.grid = new Matrix<>( + automaton.numberOfColumns(), + automaton.numberOfRows(), + new ConstantCellInitializer<>(automaton.defaultState()) + ); + this.generator = generator; } - + /** + * Goes through each {@link Cell} in this {@code CellGrid} and sets it states with a + * state obtained from the supplier. + * + * @param generator {@link Random} instance used to generate a random state for each cell + * {@link Cell}. + */ + public void fillRandomly(Random generator) { + for (Cell<S> cell : this.grid) { + cell.set(this.automaton.randomState(generator)); + } + } @Override public int numberOfColumns() { - return this.grid.getNumberOfColumns(); + return this.grid.width(); } @Override public int numberOfRows() { - return this.grid.getNumberOfRows(); + return this.grid.height(); + } + + public Cell<S> at(Coordinate coordinate) { + return this.grid.get(coordinate); } - /** - * Transitions into the next generationNumber. - */ - @Override public void updateToNextGeneration() { - this.grid.updateToNextGeneration(); this.generationNumber.set(getGenerationNumber() + 1); + Matrix<S> nextStates = this.nextGenerationMatrix(); + for (Coordinate coordinate : this.grid.coordinates()) { + this.at(coordinate).set(nextStates.get(coordinate)); + } + } + /** Computes the {link Matrix} of states obtained after a single step of updates + * of the simulation. + * + * @return the states of each cell after one generation + */ + private Matrix<S> nextGenerationMatrix() { + return new Matrix<S>( + this.grid.width(), + this.grid.height(), + new NextGenerationInitializer<>(this) + ); } - @Override public void next(Coordinate coordinate) { - this.grid.cellAt(coordinate).toggleState(); + S oldState = this.grid.get(coordinate).get(); + this.at(coordinate).set(oldState.next()); } @Override public void copy(Coordinate source, Coordinate destination) { - S state = this.grid.at(source).get(); - this.grid.at(destination).set(state); + System.out.println("bip (" + source + ") (" + destination + ")"); + S state = this.at(source).get(); + this.at(destination).set(state); } @Override public Color getColor(Coordinate coordinate) { - return this.grid.at(coordinate).get().getColor(); + return this.at(coordinate).get().getColor(); } @Override - public void setChangeListener(Coordinate coordinate, Runnable runnable) { - this.grid.cellAt(coordinate).getStateProperty().addListener( - (obs,oldV,newV) -> runnable.run() + public void setChangeListener(Coordinate coordinate, Runnable listener) { + this.at(coordinate).addOnChangeListener( + (oldValue, newValue) -> listener.run() ); } @@ -107,7 +133,9 @@ public class CellularAutomatonSimulation<S extends State<S>> * Clears the current game. */ public void clear() { - this.grid.clear(this.defaultState); + for (Cell<S> cell : this.grid) { + cell.set(this.automaton.defaultState()); + } this.generationNumber.set(0); } @@ -116,7 +144,7 @@ public class CellularAutomatonSimulation<S extends State<S>> */ public void reset() { this.clear(); - this.grid.fillRandomly(this.randomState); + this.fillRandomly(this.generator); } @Override diff --git a/src/main/java/model/ConstantCellInitializer.java b/src/main/java/model/ConstantCellInitializer.java new file mode 100644 index 0000000000000000000000000000000000000000..43edd965d7b331c4ff1a3a590836e8eb79069d42 --- /dev/null +++ b/src/main/java/model/ConstantCellInitializer.java @@ -0,0 +1,17 @@ +package model; + +import datastruct.Coordinate; +import datastruct.MatrixInitializer; + +public class ConstantCellInitializer<T> implements MatrixInitializer<Cell<T>> { + private final T defaultValue; + + public ConstantCellInitializer(T defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + public Cell<T> initialValueAt(Coordinate coordinate) { + return new Cell<>(defaultValue); + } +} diff --git a/src/main/java/model/NextGenerationInitializer.java b/src/main/java/model/NextGenerationInitializer.java index 787a3791dc7a69dce1e569cb014b3f1e3fb0a240..f344e93ff3a3ecf0bf6493603abe3e80d71e3d26 100644 --- a/src/main/java/model/NextGenerationInitializer.java +++ b/src/main/java/model/NextGenerationInitializer.java @@ -1,6 +1,7 @@ package model; import datastruct.Coordinate; +import datastruct.Matrix; import datastruct.MatrixInitializer; import java.util.ArrayList; @@ -8,19 +9,38 @@ import java.util.List; public class NextGenerationInitializer<S extends State<S>> implements MatrixInitializer<S> { - private final CellGrid<S> grid; + private final CellularAutomatonSimulation<S> simulation; - public NextGenerationInitializer(CellGrid<S> grid) { - this.grid = grid; + public NextGenerationInitializer(CellularAutomatonSimulation<S> simulation) { + this.simulation = simulation; } @Override public S initialValueAt(Coordinate coordinate) { List<State<S>> neighbours = new ArrayList<>(); for (Coordinate neighbourCoord : coordinate.orthodiagonalNeighbours()) { - neighbours.add(this.grid.cellAtWrapped(neighbourCoord).getState()); + Coordinate wrapped = wrap(neighbourCoord); + neighbours.add(this.simulation.at(wrapped).get()); } - S state = this.grid.cellAt(coordinate).getState(); + S state = this.simulation.at(coordinate).get(); return state.update(neighbours); } + + private Coordinate wrap(Coordinate coordinate) { + return new Coordinate( + modulo(coordinate.x(),this.simulation.numberOfColumns()), + modulo(coordinate.y(),this.simulation.numberOfRows()) + ); + } + + /** The non-negative remainder of n divided by d. + * + * @param n an arbitrary integer. + * @param d a non-zero integer. + * @return the remainder of {@code n/d}, between {@code 0} and {@code n-1}. + */ + private static int modulo(int n, int d) { + int result = n % d; + return n < 0 ? result + d : result; + } } diff --git a/src/main/java/model/OnChangeListener.java b/src/main/java/model/OnChangeListener.java new file mode 100644 index 0000000000000000000000000000000000000000..cc72432218567f609aee3de21867aa2c342d6fdc --- /dev/null +++ b/src/main/java/model/OnChangeListener.java @@ -0,0 +1,5 @@ +package model; + +public interface OnChangeListener<T> { + void valueChanged(T oldValue, T newValue); +} diff --git a/src/main/java/model/automata/AbstractAutomaton.java b/src/main/java/model/automata/AbstractAutomaton.java new file mode 100644 index 0000000000000000000000000000000000000000..818197ea65111fa8b59df1fbbaa6fb75691b4d04 --- /dev/null +++ b/src/main/java/model/automata/AbstractAutomaton.java @@ -0,0 +1,24 @@ +package model.automata; + +import model.CellularAutomaton; +import model.State; + +public abstract class AbstractAutomaton<S extends State<S>> implements CellularAutomaton<S> { + + private final int numberOfColumns; + private final int numberOfRows; + + + protected AbstractAutomaton(int numberOfColumns, int numberOfRows) { + this.numberOfColumns = numberOfColumns; + this.numberOfRows = numberOfRows; + } + + public int numberOfColumns() { + return numberOfColumns; + } + + public int numberOfRows() { + return numberOfRows; + } +} diff --git a/src/main/java/model/automata/BiColorAutomaton.java b/src/main/java/model/automata/BiColorAutomaton.java new file mode 100644 index 0000000000000000000000000000000000000000..7a1cb11974610f963918a930efdd1b572886310d --- /dev/null +++ b/src/main/java/model/automata/BiColorAutomaton.java @@ -0,0 +1,25 @@ +package model.automata; + +import model.CellularAutomaton; + +import java.util.Random; + +public class BiColorAutomaton extends AbstractAutomaton<BiColorState> { + + public BiColorAutomaton(int numberOfColumns, int numberOfRows) { + super(numberOfColumns, numberOfRows); + } + + @Override + public BiColorState defaultState() { + return BiColorState.DEAD; + } + + @Override + public BiColorState randomState(Random generator) { + return generator.nextBoolean()? BiColorState.DEAD: + generator.nextBoolean()? BiColorState.RED: + BiColorState.BLUE; + } + +} diff --git a/src/main/java/model/states/BiColorState.java b/src/main/java/model/automata/BiColorState.java similarity index 82% rename from src/main/java/model/states/BiColorState.java rename to src/main/java/model/automata/BiColorState.java index de0b791cf798b10b9a27b7d24582a63063b1cfec..bdeb690e2ddc48f4020b803ed69b0ebb8f28f281 100644 --- a/src/main/java/model/states/BiColorState.java +++ b/src/main/java/model/automata/BiColorState.java @@ -1,4 +1,4 @@ -package model.states; +package model.automata; import javafx.scene.paint.Color; import model.State; @@ -50,12 +50,4 @@ public enum BiColorState implements State<BiColorState> { DEAD; } - - private final static Random generator = new Random(); - - public static BiColorState random() { - return generator.nextBoolean()? DEAD: - generator.nextBoolean()? RED: - BLUE; - } } diff --git a/src/main/java/model/automata/BriansBrainAutomaton.java b/src/main/java/model/automata/BriansBrainAutomaton.java new file mode 100644 index 0000000000000000000000000000000000000000..f78771a7e5bb3ee4bd8dc9dfcc526cecb8331bff --- /dev/null +++ b/src/main/java/model/automata/BriansBrainAutomaton.java @@ -0,0 +1,22 @@ +package model.automata; + +import java.util.Random; + +public class BriansBrainAutomaton extends AbstractAutomaton<BriansBrainState> { + + public BriansBrainAutomaton(int numberOfColumns, int numberOfRows) { + super(numberOfColumns, numberOfRows); + } + + @Override + public BriansBrainState defaultState() { + return BriansBrainState.OFF; + } + + @Override + public BriansBrainState randomState(Random generator) { + return generator.nextInt(10) == 0 ? + BriansBrainState.ON: + BriansBrainState.OFF; + } +} diff --git a/src/main/java/model/states/BriansBrainState.java b/src/main/java/model/automata/BriansBrainState.java similarity index 86% rename from src/main/java/model/states/BriansBrainState.java rename to src/main/java/model/automata/BriansBrainState.java index a90286c47b4371a30e3ed7aa37a08d07f203250d..1f831b884bf0f3e64ba7115a9be31fe1ec350da9 100644 --- a/src/main/java/model/states/BriansBrainState.java +++ b/src/main/java/model/automata/BriansBrainState.java @@ -1,4 +1,4 @@ -package model.states; +package model.automata; import javafx.scene.paint.Color; import model.State; @@ -48,10 +48,4 @@ public enum BriansBrainState implements State<BriansBrainState> { } return count; } - - final static Random GENERATOR = new Random(); - - public static BriansBrainState random() { - return GENERATOR.nextInt(10) == 0 ? ON: OFF; - } } diff --git a/src/main/java/model/automata/GameOfLifeAutomaton.java b/src/main/java/model/automata/GameOfLifeAutomaton.java new file mode 100644 index 0000000000000000000000000000000000000000..cfe2b731614561bf6ed11d8b78e36831038ac9e1 --- /dev/null +++ b/src/main/java/model/automata/GameOfLifeAutomaton.java @@ -0,0 +1,24 @@ +package model.automata; + +import model.CellularAutomaton; + +import java.util.Random; + +public class GameOfLifeAutomaton extends AbstractAutomaton<GameOfLifeState> { + + protected GameOfLifeAutomaton(int numberOfColumns, int numberOfRows) { + super(numberOfColumns, numberOfRows); + } + + @Override + public GameOfLifeState defaultState() { + return GameOfLifeState.DEAD; + } + + @Override + public GameOfLifeState randomState(Random generator) { + return generator.nextBoolean()? + GameOfLifeState.ALIVE: + GameOfLifeState.DEAD; + } +} diff --git a/src/main/java/model/states/GameOfLifeState.java b/src/main/java/model/automata/GameOfLifeState.java similarity index 85% rename from src/main/java/model/states/GameOfLifeState.java rename to src/main/java/model/automata/GameOfLifeState.java index 6378a9224fb3975783bda7b3b67f8b9c0ca39514..8e4e5466832d3331cc851ebded9b4b6e7d7ea27d 100644 --- a/src/main/java/model/states/GameOfLifeState.java +++ b/src/main/java/model/automata/GameOfLifeState.java @@ -1,4 +1,4 @@ -package model.states; +package model.automata; import javafx.scene.paint.Color; import model.State; @@ -43,8 +43,4 @@ public enum GameOfLifeState implements State<GameOfLifeState> { return isAlive ? ALIVE : DEAD; } - private static final Random randomGen = new Random(); - public static GameOfLifeState random() { - return randomGen.nextBoolean() ? ALIVE : DEAD; - } } diff --git a/src/main/java/model/automata/SeedsAutomaton.java b/src/main/java/model/automata/SeedsAutomaton.java new file mode 100644 index 0000000000000000000000000000000000000000..9a9b4a3ba054933b21010e93b1e9e795dd9f4436 --- /dev/null +++ b/src/main/java/model/automata/SeedsAutomaton.java @@ -0,0 +1,21 @@ +package model.automata; + +import java.util.Random; + +public class SeedsAutomaton extends AbstractAutomaton<SeedsState> { + public SeedsAutomaton(int numberOfColumns, int numberOfRows) { + super(numberOfColumns, numberOfRows); + } + + @Override + public SeedsState defaultState() { + return SeedsState.OFF; + } + + @Override + public SeedsState randomState(Random generator) { + return generator.nextInt() == 0? + SeedsState.ON: + SeedsState.OFF; + } +} diff --git a/src/main/java/model/states/SeedsState.java b/src/main/java/model/automata/SeedsState.java similarity index 75% rename from src/main/java/model/states/SeedsState.java rename to src/main/java/model/automata/SeedsState.java index 08953724104aace1e7479d609265d7cc1cd4061e..ebfe4c36201d712956b74de5cbcaedb6b258a5a1 100644 --- a/src/main/java/model/states/SeedsState.java +++ b/src/main/java/model/automata/SeedsState.java @@ -1,12 +1,11 @@ -package model.states; +package model.automata; import javafx.scene.paint.Color; import model.State; import java.util.List; -import static model.states.BriansBrainState.GENERATOR; -import static model.states.BriansBrainState.countList; +import static model.automata.BriansBrainState.countList; public enum SeedsState implements State<SeedsState> { ON, OFF; @@ -34,7 +33,4 @@ public enum SeedsState implements State<SeedsState> { }; } - public static SeedsState random() { - return GENERATOR.nextInt(10)==0? ON: OFF; - } }