From b560daf6faea04087e6369bf777eddfbd342b49f Mon Sep 17 00:00:00 2001
From: Leo Rangheard <leo.rangheard@etu.univ-amu.fr>
Date: Sun, 4 Oct 2020 20:04:15 +0200
Subject: [PATCH] TP3

---
 tp3/src/Cell.java          |  81 ++++++++++++++
 tp3/src/GameOfLife.java    |  87 +++++++++++++++
 tp3/src/GameOfLifeGUI.java |  49 ++++++++
 tp3/src/Grid.java          | 222 +++++++++++++++++++++++++++++++++++++
 tp3/src/GridIterator.java  |  31 ++++++
 tp3/src/Main.java          |  25 +++++
 6 files changed, 495 insertions(+)
 create mode 100644 tp3/src/Cell.java
 create mode 100644 tp3/src/GameOfLife.java
 create mode 100644 tp3/src/GameOfLifeGUI.java
 create mode 100644 tp3/src/Grid.java
 create mode 100644 tp3/src/GridIterator.java
 create mode 100644 tp3/src/Main.java

diff --git a/tp3/src/Cell.java b/tp3/src/Cell.java
new file mode 100644
index 0000000..4fe7383
--- /dev/null
+++ b/tp3/src/Cell.java
@@ -0,0 +1,81 @@
+/**
+ * {@link Cell} instances represent the cells of <i>The Game of Life</i>.
+ */
+
+public class Cell {
+    private boolean isAlive;
+    private char color;
+
+    public Cell(){
+        this.color='r';
+        this.isAlive = false;
+    }
+
+    /**
+     * Determines whether this {@link Cell} is alive or not.
+     *
+     * @return {@code true} if this {@link Cell} is alive and {@code false} otherwise
+     */
+
+    public boolean isAlive() {
+        return this.isAlive;
+    }
+    public char getColor(){return this.color;}
+    public void setColor(char color){this.color=color;}
+    /**
+     * Determines whether this {@link Cell} is dead or not.
+     *
+     * @return {@code true} if this {@link Cell} is dead and {@code false} otherwise
+     */
+
+    public boolean isDead() {
+        return !this.isAlive;
+    }
+
+    /**
+     * Sets the state of this {@link Cell} to alive.
+     *
+     * @param cellState the new state of this {@link Cell}
+     */
+
+    public void setAlive() {
+        this.isAlive = true;
+    }
+
+    /**
+     * Sets the state of this {@link Cell} to dead.
+     *
+     * @param cellState the new state of this {@link Cell}
+     */
+
+    public void setDead() {
+        this.isAlive = false;
+    }
+
+
+    /**
+     * Change the state of this {@link Cell} from ALIVE to DEAD or from DEAD to ALIVE.
+     */
+
+    public void toggleState() {
+        if(this.isAlive)
+            this.isAlive = false;
+        else
+            this.isAlive = true;
+    }
+
+    public boolean isAliveInNextState(int numberOfAliveNeighbours) {
+        if(isAlive()){
+            if (numberOfAliveNeighbours == 2 ||  numberOfAliveNeighbours == 3)
+                return true;
+            else
+                return false;
+        }
+        else{
+            if (numberOfAliveNeighbours == 3)
+                return true;
+            else
+                return false;
+        }
+    }
+}
diff --git a/tp3/src/GameOfLife.java b/tp3/src/GameOfLife.java
new file mode 100644
index 0000000..5d8b4aa
--- /dev/null
+++ b/tp3/src/GameOfLife.java
@@ -0,0 +1,87 @@
+import java.util.Random;
+
+/**
+ * {@link GameOfLife} instances run <i>The Game of Life</i>.
+ */
+public class GameOfLife {
+
+    private final Random random = new Random();
+    private final Grid grid;
+    private int generationNumber;
+
+    /**
+     * Creates a new {@code GameOfLife} instance given the underlying {@link Grid}.
+     *
+     * @param grid the underlying {@link Grid}
+     * @throws NullPointerException if {@code grid} is {@code null}
+     */
+    public GameOfLife(Grid grid) {
+        //        this.grid = requireNonNull(grid, "grid is null");
+        this.grid = grid;
+        grid.randomGeneration(random);
+    }
+
+    /**
+     * Transitions into the next generationNumber.
+     */
+    public void next() {
+        grid.nextGeneration();
+        generationNumber++;
+    }
+
+
+    /**
+     * Returns the current generationNumber.
+     *
+     * @return the current generationNumber
+     */
+    private int getGenerationNumber() {
+        return generationNumber;
+    }
+
+    /**
+     * Returns the {@link Grid}.
+     *
+     * @return the {@link Grid}
+     */
+    public Grid getGrid() {
+        return grid;
+    }
+
+    /**
+     * Plays the game.
+     */
+    public void play(int maxGenerations) {
+        for(int generation =0; generation < maxGenerations; generation++){
+            this.next();
+            System.out.println("generation : " + generation);
+        }
+
+
+    }
+
+    /**
+     * Pauses the game.
+     */
+    public void pause() {
+        //        timeline.pause();
+    }
+
+    /**
+     * Clears the current game.
+     */
+    public void clear() {
+        pause();
+        grid.clear();
+        generationNumber = 0;
+    }
+
+    /**
+     * Clears the current game and randomly generates a new one.
+     */
+    public void reset() {
+        clear();
+        grid.randomGeneration(random);
+    }
+
+}
diff --git a/tp3/src/GameOfLifeGUI.java b/tp3/src/GameOfLifeGUI.java
new file mode 100644
index 0000000..6677ad0
--- /dev/null
+++ b/tp3/src/GameOfLifeGUI.java
@@ -0,0 +1,49 @@
+import java.awt.*;
+import java.awt.Graphics;
+import javax.swing.*;
+
+public class GameOfLifeGUI extends JFrame {
+    private int squareSize = 7;
+    private int numberOfRows;
+    private int numberOfColumns;
+    private JLabel[][] labelGrid;
+    private GridLayout gridLayout;
+    private JPanel gridPanel;
+    private JFrame frame;
+
+    public GameOfLifeGUI(Grid g) {
+        this.numberOfRows = g.getNumberOfRows();
+        this.numberOfColumns = g.getNumberOfColumns();
+        gridLayout = new GridLayout(numberOfRows, numberOfColumns);
+        gridPanel = new JPanel(gridLayout);
+        labelGrid = new JLabel[numberOfRows][numberOfColumns];
+        for (int x = 0; x < numberOfColumns; x++)
+            for (int y = 0; y < numberOfRows; y++){
+                labelGrid[x][y] = new JLabel("*");
+                JLabel label;
+                if(g.getCell(x,y).isAlive())
+                    labelGrid[x][y].setForeground(Color.red);
+                else
+                    labelGrid[x][y].setForeground(Color.white);
+                gridPanel.add(labelGrid[x][y]);
+            }
+        frame = new JFrame("Game of Life");
+        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        frame.setContentPane(gridPanel);
+        frame.setSize(squareSize * numberOfRows, squareSize * numberOfColumns);
+        frame.setLocationByPlatform(true);
+        frame.setVisible(true);
+    }
+
+    public void update(Grid g){
+        for (int x = 0; x < numberOfColumns; x++)
+            for (int y = 0; y < numberOfRows; y++){
+                JLabel label = labelGrid[x][y];
+                if(g.getCell(x,y).isAlive())
+                    if(g.getCell(x,y).getColor()=='r'){label.setForeground(Color.red);}
+                    else{ label.setForeground(Color.blue);}
+                else
+                    label.setForeground(Color.white);
+            }
+    }
+}
diff --git a/tp3/src/Grid.java b/tp3/src/Grid.java
new file mode 100644
index 0000000..1a1ebff
--- /dev/null
+++ b/tp3/src/Grid.java
@@ -0,0 +1,222 @@
+import java.util.*;
+
+/**
+ * {@code Grid} instances represent the grid in <i>The Game of Life</i>.
+ */
+public class Grid implements Iterable<Cell> {
+
+    private final int numberOfRows;
+    private final int numberOfColumns;
+    private final Cell[][] cells;
+
+    /**
+     * Creates a new {@code Grid} instance given the number of rows and columns.
+     *
+     * @param numberOfRows    the number of rows
+     * @param numberOfColumns the number of columns
+     * @throws IllegalArgumentException if {@code numberOfRows} or {@code numberOfColumns} are
+     *                                  less than or equal to 0
+     */
+    public Grid(int numberOfRows, int numberOfColumns) {
+        this.numberOfRows = numberOfRows;
+        this.numberOfColumns = numberOfColumns;
+        this.cells = createCells();
+    }
+
+    @Override
+    public Iterator<Cell> iterator() {
+        return new GridIterator(this);
+    }
+
+    private Cell[][] createCells() {
+        Cell[][] cells = new Cell[getNumberOfRows()][getNumberOfColumns()];
+        for (int rowIndex = 0; rowIndex < getNumberOfRows(); rowIndex++) {
+            for (int columnIndex = 0; columnIndex < getNumberOfColumns(); columnIndex++) {
+                cells[rowIndex][columnIndex] = new Cell();
+            }
+        }
+        return cells;
+    }
+
+    /**
+     * Returns the {@link Cell} at the given index.
+     *
+     * <p>Note that the index is wrapped around so that a {@link Cell} is always returned.
+     *
+     * @param rowIndex    the row index of the {@link Cell}
+     * @param columnIndex the column index of the {@link Cell}
+     * @return the {@link Cell} at the given row and column index
+     */
+    public Cell getCell(int rowIndex, int columnIndex) {
+        return cells[getWrappedRowIndex(rowIndex)][getWrappedColumnIndex(columnIndex)];
+    }
+
+    private int getWrappedRowIndex(int rowIndex) {
+        return (rowIndex + getNumberOfRows()) % getNumberOfRows();
+    }
+
+    private int getWrappedColumnIndex(int columnIndex) {
+        return (columnIndex + getNumberOfColumns()) % getNumberOfColumns();
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * 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>
+     */
+    void nextGeneration() {
+        goToNextState(calculateNextStates());
+    }
+
+    private boolean[][] calculateNextStates() {
+        boolean[][] nextState = new boolean[this.getNumberOfRows()][this.getNumberOfColumns()];
+        for(int i = 0; i < this.getNumberOfRows(); i++){
+            for(int j = 0; j < this.getNumberOfColumns(); j++){
+                nextState[i][j] = calculateNextState(i,j,this.getCell(i,j));
+            }
+        }
+
+        return nextState;
+    }
+    private char getAverageNeighboursColor(int rowIndex,int columnIndex)
+    {
+        int redCount=0;
+        int blueCount=0;
+
+        List<Cell> neighbours = this.getNeighbours(rowIndex,columnIndex);
+
+        for(Cell currentCell : neighbours)
+        {
+            if(currentCell.isAlive())
+            {
+                if(currentCell.getColor()=='R'){redCount++;}
+                else{blueCount++;}
+            }
+        }
+
+        if(blueCount>redCount)
+        {
+            return 'B';
+        }
+
+        return 'R';
+    }
+
+    private boolean calculateNextState(int rowIndex, int columnIndex, Cell cell) {
+        int neighbours = this.countAliveNeighbours(rowIndex,columnIndex);
+        if(cell.isAlive()){
+            if(neighbours == 2 || neighbours == 3){
+                return true;
+            }
+
+        }
+        else{
+            if(neighbours == 3){
+                cell.setColor(this.getAverageNeighboursColor(rowIndex,columnIndex));
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private int countAliveNeighbours(int rowIndex, int columnIndex) {
+        int count = 0;
+        List<Cell> Neighbours = this.getNeighbours(rowIndex, columnIndex);
+        for(Cell cell : Neighbours){
+            if(cell.isAlive()){
+                count++;
+            }
+        }
+        return count;
+    }
+
+
+    private List<Cell> getNeighbours(int rowIndex, int columnIndex) {
+        List<Cell> Neighbours= new ArrayList<Cell>();
+        for(int i = rowIndex -1; i <= rowIndex + 1; i++) {
+            for (int j = columnIndex-1; j <= columnIndex + 1; j++) {
+                if(i != rowIndex || j != columnIndex){
+                    Neighbours.add(this.getCell(i,j));
+                }
+            }
+        }
+            return Neighbours;
+    }
+
+    private void goToNextState(boolean[][] nextState) {
+        for(int i = 0; i < this.getNumberOfRows(); i++){
+            for(int j = 0; j < this.getNumberOfColumns(); j++){
+                if(nextState[i][j]){
+                    this.getCell(i,j).setAlive();
+                }
+                else{
+                    this.getCell(i,j).setDead();
+                }
+            }
+        }
+    }
+
+    /**
+     * Sets all {@link Cell}s in this {@code Grid} as dead.
+     */
+    void clear() {
+        for(int i = 0; i < this.getNumberOfRows(); i++){
+            for(int j = 0; j < this.getNumberOfColumns(); j++){
+                this.getCell(i,j).setDead();
+            }
+        }
+    }
+
+    /**
+     * Goes through each {@link Cell} in this {@code Grid} and randomly sets it as alive or dead.
+     *
+     * @param random {@link Random} instance used to decide if each {@link Cell} is alive or dead
+     * @throws NullPointerException if {@code random} is {@code null}
+     */
+
+    void randomGeneration(Random random) {
+        for(int i = 0; i < this.getNumberOfRows(); i++){
+            for(int j = 0; j < this.getNumberOfColumns(); j++){
+                if(random.nextBoolean()){
+                    if(random.nextBoolean()){
+                        this.getCell(i,j).setColor('r');
+                    }
+                    else{
+                        this.getCell(i,j).setColor('b');
+                    }
+                    this.getCell(i,j).setAlive();
+                }
+                else{
+                    this.getCell(i,j).setDead();
+                }
+            }
+        }
+    }
+
+}
diff --git a/tp3/src/GridIterator.java b/tp3/src/GridIterator.java
new file mode 100644
index 0000000..19fc9e0
--- /dev/null
+++ b/tp3/src/GridIterator.java
@@ -0,0 +1,31 @@
+import java.util.Iterator;
+
+/**
+ * {@link GridIterator} instances are used to iterate over the cells of a grid.
+ */
+public class GridIterator implements Iterator<Cell> {
+    private int rowIndex;
+    private int columnIndex;
+    private Grid grid;
+
+    GridIterator(Grid grid) {
+        this.rowIndex = 0;
+        this.columnIndex = 0;
+        this.grid = grid;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return columnIndex < grid.getNumberOfColumns() && rowIndex < grid.getNumberOfRows();
+    }
+
+    @Override
+    public Cell next() {
+        final Cell result = grid.getCell(rowIndex, columnIndex);
+        columnIndex = (columnIndex +1) % grid.getNumberOfColumns();
+        if(columnIndex == 0){
+            rowIndex++;
+        }
+        return result;
+    }
+}
diff --git a/tp3/src/Main.java b/tp3/src/Main.java
new file mode 100644
index 0000000..c5ca292
--- /dev/null
+++ b/tp3/src/Main.java
@@ -0,0 +1,25 @@
+import java.io.*;
+import java.awt.*;
+import javax.swing.*;
+
+public class Main{
+    public static void main(String args[]) throws IOException {
+        int NUMBER_OF_ROWS = 64;
+        int NUMBER_OF_COLUMNS = 64;
+
+        GameOfLife gameOfLife = new GameOfLife(new Grid(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS));
+
+        GameOfLifeGUI gui = new GameOfLifeGUI(gameOfLife.getGrid());
+
+        for(int generation =0; generation < 1000; generation++){
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException ie) {
+
+            }
+            gameOfLife.next();
+            gui.update(gameOfLife.getGrid());
+        }
+
+    }
+}
-- 
GitLab