前言:
博主在看新闻时,浏览到John Horton Conway因新型冠状病毒感染而去世。这场疫情带走了许多领域杰出的大师们,希望全人类早日战胜疫情。
John Horton Conway的生命游戏为不少数学家和码农所熟知,本篇主要介绍了Conway’s Game of Life以及基于C++的实现。
生命游戏模拟代码已上传,本文将根据此进行讲解:https://github.com/CreateSuccess/GHCGameLife
生命游戏规则:
1、 生命游戏规则有些类似与围棋,游戏背景为假设有无尽大的由正方形格子组成的空间,每一个正方形格子代表为一个细胞。
2、细胞的状态有二种,生存或者死亡;
3、在二维基础上加上时间,每个回合进行判断细胞下一个回合是生存还是死亡。
4、细胞生存还是死亡取决于其与周围八个相邻细胞的互动。
5、如果一个活细胞周围细胞只有0个活着1个,则该细胞下回合死亡。(一片区域内,种群成员过少导致该片区域无法繁衍)
6、如果一个活细胞周围细胞恰有2个或者3个,则该细胞下回合存活。
7、如果一个活细胞周围活细胞超过3个,则该细胞下回合死亡。(一片区域内,种群成员过多导致平均资源变少无法繁衍)
8、如果一个死细胞周围活细胞正好有3个,则该细胞下回合转为活细胞。(一片区域内,种群成员适中,资源过多,则种群规模扩大)
代码实现
1、生命游戏规则很简单,首先我们要制作一个棋盘用于存放,棋盘大小为变成为X的正方形空间,我们将这个空间存储在一个一维数组里;
// 创建一个m_ulMapSideLength边长的正方形空间
void GHCGameLife::CreateMap()
{
m_mapLife = (CoordinateStatus *)calloc(m_ulMapSideLength, m_ulMapSideLength * sizeof(CoordinateStatus));
m_mapNextTimeLife = (CoordinateStatus *)calloc(m_ulMapSideLength, m_ulMapSideLength * sizeof(CoordinateStatus));
}
2、现在我们定义空间中每个点可能出现的状态:(活细胞 | 死细胞)
enum CoordinateStatus
{
COORDINATE_STATUS_ALIVE = 1,
COORDINATE_STATUS_DEATH,
COORDINATE_STATUS_NON_SPACE,
COORDINATE_STATUS_NON_MAX,
};
3、我们对空间每个点的状态进行随机赋值
void GHCGameLife::RandomSetMap()
{
CoordinateStatus status[] = { COORDINATE_STATUS_ALIVE, COORDINATE_STATUS_DEATH };
int statusSize = sizeof(status) / sizeof(CoordinateStatus);
srand((unsigned)time(NULL));
for (unsigned long i = 0; i < m_ulMapSideLength * m_ulMapSideLength; i++)
{
m_mapLife[i] = status[rand() % statusSize];
}
}
4、此时我们已经初始化好生命游戏模型,每个点可以用X,Y坐标进行唯一定位。根据游戏规则,每个回合我们将计算每个点,其附近活细胞数量,以此来决定下个回合该点状态。
int GHCGameLife::WhetherAlive(unsigned long ulCoordinatesX, unsigned long ulCoordinatesY)
{
if (ulCoordinatesX <= 0 || ulCoordinatesX > m_ulMapSideLength ||
ulCoordinatesY <= 0 || ulCoordinatesY > m_ulMapSideLength)
{
return 0;
}
unsigned long site = ((ulCoordinatesY - 1) * m_ulMapSideLength) + (ulCoordinatesX - 1);
return m_mapLife[site] == COORDINATE_STATUS_ALIVE ? 1 : 0;
}
void GHCGameLife::SkipOneTime()
{
for (unsigned long i = 0; i < m_ulMapSideLength * m_ulMapSideLength; i++)
{
unsigned int uiAliveNum = 0;
unsigned long ulCoordinatesNodeX = 0, ulCoordinatesNodeY = 0;
ulCoordinatesNodeY = (i + 1) / m_ulMapSideLength + ( 0 == (i + 1) % m_ulMapSideLength ? 0 : 1);
ulCoordinatesNodeX = (i + 1) - m_ulMapSideLength * (ulCoordinatesNodeY - 1);
/* 收集细胞周围活细胞数量 */
uiAliveNum += WhetherAlive(ulCoordinatesNodeX + 1, ulCoordinatesNodeY);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX - 1, ulCoordinatesNodeY);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX, ulCoordinatesNodeY + 1);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX + 1, ulCoordinatesNodeY + 1);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX - 1, ulCoordinatesNodeY + 1);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX, ulCoordinatesNodeY - 1);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX + 1, ulCoordinatesNodeY - 1);
uiAliveNum += WhetherAlive(ulCoordinatesNodeX - 1, ulCoordinatesNodeY - 1);
if (m_mapLife[i] == COORDINATE_STATUS_NON_SPACE)
{
m_mapNextTimeLife[i] = COORDINATE_STATUS_NON_SPACE;
}
else if (uiAliveNum == 3)
{
m_mapNextTimeLife[i] = COORDINATE_STATUS_ALIVE;
}
else if (2 <= uiAliveNum && 3 > uiAliveNum && m_mapLife[i] == COORDINATE_STATUS_ALIVE)
{
m_mapNextTimeLife[i] = COORDINATE_STATUS_ALIVE;
}
else
{
m_mapNextTimeLife[i] = COORDINATE_STATUS_DEATH;
}
}
CoordinateStatus *pmapLife = m_mapNextTimeLife;
m_mapNextTimeLife = m_mapLife;
m_mapLife = pmapLife;
}
图像化展示生命游戏模型进程
L代表活细胞,空格代表死细胞,X代表非空间点(无法生存点)
初始化一个9X9的空间
第一回合模型:
第二回合模型:
。。。 。。。 第100回合模型:
L代表活细胞,空格代表死细胞,X代表非空间点(无法生存点)
初始化一个20X20的空间
第一回合模型:
第200回合模型
L代表活细胞,空格代表死细胞,X代表非空间点(无法生存点)
初始化一个20X20的空间,随机设置非空间点
第一回合模型:
第200回合模型:
结语
1、生命模型在测试过程能生成一些有趣的图案;
2、设置障碍后的生命模型往往能在后期拥有更多的活细胞,令人唏嘘。最近疫情,美国一直崇拜的自由反而造成了大面积感染,一味的自由对生命并不是好事。