Simple implementation of unity game of life

Rendering:
Gosper Glider Gun:
insert image description here
Through the basic rules + initial state can produce many surprising performances
Basic rules:

(1) When the current cell is in the dead state, when there are 3 surviving cells around, the cell will become alive after the iteration (simulated reproduction); if it was alive before, it will remain unchanged.
(2) When the current cell is in the living state, when the surrounding neighbor cells are less than two (not including two) alive, the cell becomes dead (the number of simulated life is scarce).
(3) When the current cell is in a living state, when there are two or three living cells around, the cell remains the same.
(4) When the current cell is in the living state, when there are more than 3 surviving cells around, the cell will become dead (simulating too many lives).

There is a video at Station B, which introduces many different structures: [Game of Life|Episode 1] Several squares evolve into a world_哔哩哔哩_bilibili
project package: Unity Game of Life
The code is very simple:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LifeGame : MonoBehaviour
{
    
    
    public class CellInfo
    {
    
    
        public CellInfo(Image imgParam)
        {
    
    
            img = imgParam;
            SetState(false);
        }
        public Image img;
        public bool state;
        public void SetState(bool live)
        {
    
    
            state = live;
            img.color = live ? Color.white : Color.black;
        }
        public bool IsDead()
        {
    
    
            return state == false;
        }
        public void SetTmpState(bool bState)
        {
    
    
            tmpState = bState;
        }
        public bool tmpState;
    }
    public int CellLength = 100;
    public Image ImagePrefab;
    public Transform CellsParent;
    public float speed = 1;

    List<List<CellInfo>> Cells = new List<List<CellInfo>>();
    int width;
    int height;
    int round = 0;
    // Start is called before the first frame update
    void Start()
    {
    
    
        width = Screen.width / CellLength;
        height = Screen.height / CellLength;
        var size = new Vector2(CellLength-1, CellLength-1);
        for(int i=0;i<height;++i)
        {
    
    
            List<CellInfo> curCells = new List<CellInfo>();
            Cells.Add(curCells);
            for (int j=0;j< width; ++j)
            {
    
    
                var img = Instantiate(ImagePrefab, CellsParent);
                var rectTrans = (img.transform as RectTransform);
                rectTrans.sizeDelta = size;
                rectTrans.anchoredPosition = new Vector2(j * CellLength, i * CellLength);
                curCells.Add(new CellInfo(img));
            }
        }
    }

    public void ClearState()
    {
    
    
        for (int i = 0; i < height; ++i)
        {
    
    
            for (int j = 0; j < width; ++j)
            {
    
    
                Cells[i][j].SetState(false);
            }
        }
        round = 0;
    }

    public void NextRound()
    {
    
    
        ++round;
        for (int i = 0; i < height; ++i)
        {
    
    
            for (int j = 0; j < width; ++j)
            {
    
    
                UpdateState(i, j);
            }
        }
        ChangeTmpState();
    }
    List<Vector2> roundMap = new List<Vector2>
    {
    
    
        new Vector2(-1,-1),
        new Vector2(0,-1),
        new Vector2(1,-1),
        new Vector2(-1,0),
        new Vector2(1,0),
        new Vector2(-1,1),
        new Vector2(0,1),
        new Vector2(1,1)
    };
    void UpdateState(int y,int x)
    {
    
    
        // 周围存活细胞个数
        int count = 0;
        foreach(var map in roundMap)
        {
    
    
            int mx = x + ((int)map.x);
            int my = y + ((int)map.y);
            if(mx >= 0 && mx < width && my >=0 && my < height)
            {
    
    
                count += Cells[my][mx].state ? 1 : 0;
            }
        }
        var cell = Cells[y][x];
        var newState = cell.state;
        //当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
        if (cell.IsDead() && count == 3) newState = true;
        else if(!cell.IsDead())
        {
    
    
            //当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
            if (count < 2) newState = false;
            //当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
            if (count == 2 || count == 3) newState = cell.state;
            //当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。
            if (count > 3) newState = false;
        }
        cell.SetTmpState(newState);
    }

    void ChangeTmpState()
    {
    
    
        for (int i = 0; i < height; ++i)
        {
    
    
            for (int j = 0; j < width; ++j)
            {
    
    
                var cell = Cells[i][j];
                cell.SetState(cell.tmpState);
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
    
    
        if(Input.GetMouseButtonDown(0))
        {
    
    
            var mousePos = Input.mousePosition;
            int x = Mathf.FloorToInt(mousePos.x / CellLength);
            int y = Mathf.FloorToInt(mousePos.y / CellLength);
            if (x >= 0 && x < width && y >= 0 && y < height)
                Cells[y][x].SetState(!Cells[y][x].state);
        }

        AutoUpdate();
    }
    float lastTime;
    bool isAuto = false;
    void AutoUpdate()
    {
    
    
        if(isAuto)
        {
    
    
            if(Time.time - lastTime >= speed)
            {
    
    
                lastTime = Time.time;
                NextRound();
            }
        }
    }
    private void OnGUI()
    {
    
    
        GUI.Label(new Rect(Screen.width - 300, 0, 400, 40), $"Round {
      
      round}");
        if (GUI.Button(new Rect(Screen.width - 100, 0, 100, 40), "Reset"))
        {
    
    
            ClearState();
            isAuto = false;
        }
        if (GUI.Button(new Rect(Screen.width - 200, 00, 100, 40), "Next"))
        {
    
    
            NextRound();
        }
        if (GUI.Button(new Rect(Screen.width - 300, 00, 100, 40), "Auto"))
        {
    
    
            isAuto = !isAuto;
        }
    }
}

Guess you like

Origin blog.csdn.net/fztfztfzt/article/details/125815221