雪辉 发表于 2023-11-10 11:32

C#写康威的生命游戏

本帖最后由 雪辉 于 2023-11-16 09:35 编辑

最新抖音看到三体人列计算机解说,提到了康威的生命游戏,有点感兴趣,自己来开发一个生命游戏

游戏规则-思路
1、每个细胞有两种状态 - 存活1或死亡0,每个细胞与以自身为中心的周围八格细胞产生互动。
   得出需要创建二维数组记录细胞坐标信息的生死,状态只有0和1,并且需要偏移判断周围8格
2、当前细胞为存活状态1时,当周围细胞存活低于2个时,该细胞变成死亡状态。(模拟生命数量稀少,孤单而死)
    得出if count < 2 && state == 1 细胞为0
3、当前细胞为存活状态1时,当周围有2个或3个存活细胞时,该细胞保持原样。
    得出if (count == 2 or count == 3) && state == 1 细胞不变
4、当前细胞为存活状态1时,当周围有超过3个存活细胞时,该细胞变成死亡状态。(模拟生命数量过多,拥挤而死)
    得出if count > 3 && state == 1 细胞为0
5、当前细胞为死亡状态0时,当周围有3个存活细胞时,该细胞变成存活状态。(模拟繁殖,为啥3人才能?)
    得出if count == 3 && state == 0 细胞为1

总结下来就是当前活细胞周围存活为2-3个继续存活,否则为死亡
                  当前死细胞周围存活为3个时繁殖
通过二维数组完成细胞的坐标,使用位运算和偏移得出细胞生死。



头好痒,感觉要长脑子了

难点-真头疼点1、二维数组有边界,4个边界该如何判断后面的细胞?
目前大概想法,用字典套二位数组,判断边界是否有状态1,如果有则生成新二维数组套入字典,但是又该怎么判断这2个二维数组的连接对应?

2、目前是通过GDI绘画完成细胞生死显示,所有控件终究是有边界的,该如何解决?
目前大概想法有2个,都是使用pictureBox控件放置细胞,
1、写出pictureBox拖动方法,并生成其他四边的picturebox。(生成其他picturebox套入第一个问题生成新的二维数组,该怎么判断picturebox1和picturebox2的关联呢)
2、写出pictureBox伪拖动,实际为拉伸边框操作。(拉伸边框,让二维数组四边扩大一倍,后续的想法到这就断断续续了)


无边框解决方案-长脑子中
1、建立个方法,每次更新生死前判断边界是否有状态为1的值
2、给二维数组扩容
3、给画板扩容,上扩容和左扩容需要移动画板位置,实现扩容后视觉位置不变
4、给画板增加拖动效果
5、增加双缓冲,解决绘画卡顿问题
⑴、BUG:有时画板扩容后,移动位置错误

      public void GetBoardState()
      {
            int sum_top = 0;
            int sum_bottom = 0;
            int sum_left = 0;
            int sum_rigth = 0;
            for (int i = 0; i < m; i++)
            {
                sum_top += (board & 1);
                sum_bottom += (board & 1);
            }
            for (int i = 0; i < n; i++)
            {
                sum_left += (board & 1);
                sum_rigth += (board & 1);
            }
            if (sum_top > 0 || sum_bottom > 0 || sum_left > 0 || sum_rigth > 0)
            {
                int[,] board_new = (int[,])board.Clone();
                int k = board_new.GetLength(0);
                int g = board_new.GetLength(1);
                if (sum_top > 0)
                  g += base_hnum;
                if (sum_bottom > 0)
                  g += base_hnum;
                if (sum_left > 0)
                  k += base_wnum;
                if (sum_rigth > 0)
                  k += base_wnum;
                board = new int;
                for (int i = 0; i < m; i++)
                {
                  for (int j = 0; j < n; j++)
                  {
                        if (sum_top > 0 && sum_left > 0)
                            board = board_new;
                        else if (sum_top > 0)
                            board = board_new;
                        else if (sum_left > 0)
                            board = board_new;
                        else
                            board = board_new;
                  }
                }
                m = board.GetLength(0);
                n = board.GetLength(1);
                pictureBox1.Size = new Size(m * base_size + 3, n * base_size + 3);
                int x = pictureBox1.Location.X;
                int y = pictureBox1.Location.Y;
                if (sum_top > 0)
                  y -= board_new.GetLength(1) * base_size;
                if (sum_left > 0)
                  x -= board_new.GetLength(0) * base_size;
                pictureBox1.Location = new Point(x, y);
            }
      }

backaxe 发表于 2023-11-11 09:58

using System;
using System.Threading;

class GameOfLife
{
    private const int Width = 10;
    private const int Height = 10;
    private bool[,] grid = new bool;

    public GameOfLife()
    {
      InitializeRandomGrid();
    }

    private void InitializeRandomGrid()
    {
      Random random = new Random();
      for (int x = 0; x < Width; x++)
      {
            for (int y = 0; y < Height; y++)
            {
                grid = random.Next(2) == 1;
            }
      }
    }

    public void Run()
    {
      while (true)
      {
            PrintGrid();
            UpdateGrid();
            Thread.Sleep(1000);
      }
    }

    private void PrintGrid()
    {
      Console.Clear();
      for (int y = 0; y < Height; y++)
      {
            for (int x = 0; x < Width; x++)
            {
                Console.Write(grid ? "1 " : "0 ");
            }
            Console.WriteLine();
      }
    }

    private void UpdateGrid()
    {
      bool[,] newGrid = new bool;

      for (int x = 0; x < Width; x++)
      {
            for (int y = 0; y < Height; y++)
            {
                int aliveNeighbors = CountAliveNeighbors(x, y);

                if (grid)
                {
                  newGrid = aliveNeighbors == 2 || aliveNeighbors == 3;
                }
                else
                {
                  newGrid = aliveNeighbors == 3;
                }
            }
      }

      grid = newGrid;
    }

    private int CountAliveNeighbors(int x, int y)
    {
      int count = 0;

      for (int i = -1; i <= 1; i++)
      {
            for (int j = -1; j <= 1; j++)
            {
                if (i == 0 && j == 0) continue; // Skip the cell itself

                int nx = x + i, ny = y + j;

                // Check the bounds
                if (nx >= 0 && ny >= 0 && nx < Width && ny < Height)
                {
                  if (grid)
                  {
                        count++;
                  }
                }
            }
      }

      return count;
    }

    static void Main(string[] args)
    {
      GameOfLife game = new GameOfLife();
      game.Run();
    }
}

bot4o7 发表于 2023-11-22 14:22

楼主的无边框方案挺好的,但是我感觉还是有边框比较好,不仅容易实现,也符合人类目前的认知。

我个人认为,既然conway生命游戏默认了“生命”指的是细胞,那我们大可以把游戏场景想象为一个星球。这样的话,四个边界就是相连的——因此对于边界元素的处理,你可以轻松地用 取模运算 来做(对于 n x n 大小的星球, (0,0)的细胞,与(n-1,n-1), (0,n-1)这样的细胞相邻)。

仔细想一下,能允许生命无限增殖的空间,也就只有太空吧,那样就有点奇怪了,目前还未发现这种生物呢。

blindcat 发表于 2023-11-10 12:23

支持下原创

lookfeiji 发表于 2023-11-10 12:32

还带程序设计思路的,这个很赞

chukr11 发表于 2023-11-10 12:47

实在看不懂。头皮也很痒

感觉不到风 发表于 2023-11-10 13:25

就是个逻辑 而已但是距离真实相差十亿八千里 细胞运动速度是随机的

fuermoxi 发表于 2023-11-10 13:34

感谢分享,很有用

雨之幽 发表于 2023-11-10 13:59

谢谢分享

林火火 发表于 2023-11-10 14:40

非常适用的软件 感谢楼主分享

NINE09 发表于 2023-11-10 15:41

非常适用的软件 感谢楼主分享
页: [1] 2 3
查看完整版本: C#写康威的生命游戏