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);
}
}
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();
}
}
楼主的无边框方案挺好的,但是我感觉还是有边框比较好,不仅容易实现,也符合人类目前的认知。
我个人认为,既然conway生命游戏默认了“生命”指的是细胞,那我们大可以把游戏场景想象为一个星球。这样的话,四个边界就是相连的——因此对于边界元素的处理,你可以轻松地用 取模运算 来做(对于 n x n 大小的星球, (0,0)的细胞,与(n-1,n-1), (0,n-1)这样的细胞相邻)。
仔细想一下,能允许生命无限增殖的空间,也就只有太空吧,那样就有点奇怪了,目前还未发现这种生物呢。 支持下原创 还带程序设计思路的,这个很赞 实在看不懂。头皮也很痒 就是个逻辑 而已但是距离真实相差十亿八千里 细胞运动速度是随机的 感谢分享,很有用 谢谢分享 非常适用的软件 感谢楼主分享 非常适用的软件 感谢楼主分享