using UnityEngine; namespace DefaultNamespace.GameOfLife { public class GameOfLife : MonoBehaviour { [SerializeField] private Cell _cellPrefab; [SerializeField, Range(5, 100)] private int _rows = 10; [SerializeField, Range(5, 100)] private int _columns = 10; private Cell[] _cells; private int CalculateIndex(int column, int row) => row * _columns + column; private void Start() { _cells = new Cell[_rows * _columns]; for (int x = 0; x < _columns; x++) { for (int y = 0; y < _rows; y++) { int index = CalculateIndex(x, y); Cell cell = Instantiate(_cellPrefab, transform); cell.name = $"{x:000} / {y:000} (index: {index})"; cell.transform.localPosition = new Vector3(x, y, 0.0f); _cells[index] = cell; } } } private void SimulateStep() { // collect new states bool[] newStates = new bool[_cells.Length]; // change states - apply rules for (int x = 0; x < _columns; x++) { for (int y = 0; y < _rows; y++) { int index = CalculateIndex(x, y); bool cellState = _cells[index].IsAlive; int neighbors = CountNeighbors(x, y); if (cellState) { // cell is alive // rule 1: less than two neighbors => die if (neighbors < 2) cellState = false; // rule 2: two or three neighbors => stay live // if (neighbors == 2 || neighbors == 3) cellState = true; if (neighbors is 2 or 3) cellState = true; // both conditions are the same // rule 3: more than three neighbors => die if (neighbors > 3) cellState = false; } else { // cell is dead // rule 4: equal to three neighbors => birth if (neighbors == 3) cellState = true; } newStates[index] = cellState; } } // apply new states for (int i = 0; i < _cells.Length; i++) { _cells[i].IsAlive = newStates[i]; } } private int CountNeighbors(int column, int row) { int count = 0; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { // exception: own cell if (dx == 0 && dy == 0) continue; int currentColumn = column + dx; int currentRow = row + dy; // exceptions: borders if (currentColumn < 0 || currentColumn >= _columns) continue; if (currentRow < 0 || currentRow >= _rows) continue; if (_cells[CalculateIndex(currentColumn, currentRow)].IsAlive) count++; } } return count; } public void OnSimulateButtonClick() => SimulateStep(); public void OnResetButtonClick() { for (int i = 0; i < _cells.Length; i++) { _cells[i].IsAlive = false; } CancelInvoke(nameof(SimulateStep)); } public void OnStartSimulationButtonClick() => InvokeRepeating(nameof(SimulateStep), 0f, 0.5f); public void OnStopSimulationButtonClick() => CancelInvoke(nameof(SimulateStep)); } }