Skip to content
Snippets Groups Projects
CellularAutomatonSimulation.java 3.49 KiB
Newer Older
  • Learn to ignore specific revisions
  • Guyslain's avatar
    Guyslain committed
    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>.
    
    Guyslain's avatar
    Guyslain committed
     */
    
    public class CellularAutomatonSimulation<S extends State<S>>
    
    Guyslain's avatar
    Guyslain committed
            implements Simulation {
    
        private final CellGrid<S> grid;
    
        private final Supplier<S> randomState;
    
    Guyslain's avatar
    Guyslain committed
        private final S defaultState;
        private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper();
    
        /**
    
         * Creates a new {@code CellularAutomataSimulation} instance for a given automaton.
    
    Guyslain's avatar
    Guyslain committed
         *
    
         * @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
    
    Guyslain's avatar
    Guyslain committed
         */
    
        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);
    
    Guyslain's avatar
    Guyslain committed
        }
    
    
    
        @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);
    
    Guyslain's avatar
    Guyslain committed
        }
    
        @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();
    
    Guyslain's avatar
    Guyslain committed
        }
    
        /**
         * Returns the generationNumber {@link ReadOnlyLongProperty}.
         *
         * @return the generationNumber {@link ReadOnlyLongProperty}
         */
        public ReadOnlyLongProperty generationNumberProperty() {
    
            return this.generationNumber.getReadOnlyProperty();
    
    Guyslain's avatar
    Guyslain committed
        }
    
    
        /**
         * Clears the current game.
         */
        public void clear() {
    
            this.grid.clear(this.defaultState);
            this.generationNumber.set(0);
    
    Guyslain's avatar
    Guyslain committed
        }
    
        /**
         * Clears the current game and randomly generates a new one.
         */
        public void reset() {
    
            this.clear();
            this.grid.fillRandomly(this.randomState);
    
    Guyslain's avatar
    Guyslain committed
        }
    
        @Override
        public Iterator<Coordinate> iterator() {
            return this.grid.coordinates().iterator();
        }
    }