using System; using UnityEngine; using Random = UnityEngine.Random; namespace DefaultNamespace.GameOfLife { public class GameOfLife : MonoBehaviour { [SerializeField] private Cell _cellPrefab; [SerializeField, Range(10, 999)] private int _rows = 50; [SerializeField, Range(10, 999)] private int _columns = 50; private Cell[] _cells; private int CalculateIndex(int x, int y) => x + y * _columns; private void Start() { _cells = new Cell[_rows * _columns]; for (int x = 0; x < _columns; x++) { for (int y = 0; y < _rows; y++) { Cell cell = Instantiate(_cellPrefab, transform); cell.name = $"{x:000} / {y:000}"; cell.transform.localPosition = new Vector3(x, y, 0.0f); _cells[CalculateIndex(x, y)] = cell; } } } private void SimulateStep() { // collect new states bool[] newStates = new bool[_rows * _columns]; // changing 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: equal to two or three neighbors => stay alive if (neighbors is 2 or 3) cellState = true; // 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; } } // transfer 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 currentX = column + dx; int currentY = row + dy; // exception: borders if (currentX < 0 || currentX >= _columns) continue; if (currentY < 0 || currentY >= _rows) continue; if (_cells[CalculateIndex(currentX, currentY)].IsAlive) count++; } } return count; } public void OnFillGridRandomlyButtonClick() { for (int i = 0; i < _cells.Length; i++) { _cells[i].IsAlive = Random.value < 0.1f; } } public void OnSimulateStepButtonClick() => SimulateStep(); public void OnResetGridButtonClick() { for (int i = 0; i < _cells.Length; i++) { _cells[i].IsAlive = false; } OnStopSimulationButtonClick(); } public void OnStartSimulationButtonClick() => InvokeRepeating(nameof(SimulateStep), 0.0f, 0.5f); public void OnStopSimulationButtonClick() => CancelInvoke(nameof(SimulateStep)); } }