康威生命游戏_学习记录
康威生命游戏(英语:Conway‘s Game of Life),又称康威生命棋,是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
它最初于1970年10月在《科学美国人》杂志上马丁·葛登能的“数学游戏”专栏出现。
规则
生命游戏中,对于任意细胞,规则如下:
- 每个细胞有两种状态 - 存活或死亡,每个细胞与以自身为中心的周围八格细胞产生互动(如图,黑色为存活,白色为死亡)
- 当前细胞为存活状态时,当周围的存活细胞低于2个时(不包含2个),该细胞变成死亡状态。(模拟生命数量稀少)
- 当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。
- 当前细胞为存活状态时,当周围有超过3个存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
- 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。(模拟繁殖)
可以把最初的细胞结构定义为种子,当所有在种子中的细胞同时被以上规则处理后,可以得到第一代细胞图。按规则继续处理当前的细胞图,可以得到下一代的细胞图,周而复始。
概述
生命游戏是一个零玩家游戏。它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。实际中,玩家可以设定周围活细胞的数目怎样时才适宜该细胞的生存。如果这个数目设定过高,世界中的大部分细胞会因为找不到太多的活的邻居而死去,直到整个世界都没有生命;如果这个数目设定过低,世界中又会被生命充满而没有什么变化。
实际中,这个数目一般选取2或者3;这样整个生命世界才不至于太过荒凉或拥挤,而是一种动态的平衡。这样的话,游戏的规则就是:当一个方格周围有2或3个活细胞时,方格中的活细胞在下一个时刻继续存活;即使这个时刻方格中没有活细胞,在下一个时刻也会“诞生”活细胞。
在这个游戏中,还可以设定一些更加复杂的规则,例如当前方格的状况不仅由父一代决定,而且还考虑祖父一代的情况。玩家还可以作为这个世界的“上帝”,随意设定某个方格细胞的死活,以观察对世界的影响。
在游戏的进行中,杂乱无序的细胞会逐渐演化出各种精致、有形的结构;这些结构往往有很好的对称性,而且每一代都在变化形状。一些形状已经锁定,不会逐代变化。有时,一些已经成形的结构会因为一些无序细胞的“入侵”而被破坏。但是形状和秩序经常能从杂乱中产生出来。
这个游戏被许多计算机程序实现了。Unix世界中的许多骇客喜欢玩这个游戏,他们用字符代表一个细胞,在一个计算机屏幕上进行演化。比较著名的例子是,GNU Emacs编辑器中就包括这样一个小游戏。
以上介绍规则及概述载自 https://zh.wikipedia.org/wiki/康威生命游戏
以上介绍规则及概述载自 https://zh.wikipedia.org/wiki/康威生命游戏
以上介绍规则及概述载自 https://zh.wikipedia.org/wiki/康威生命游戏
以下为我根据规则编写的C语言代码
技术不佳,用的是最笨拙的,逐个下标循环的方式 ,具体函数功能已在代码注释中表示
实现逻辑
- main 函数中 使用while循环输入初试图形坐标,循环次数及像素点数,须自行判断较为麻烦;在将初试坐标的数据使用 enterMap(x,y)函数传入数组地图数据后,同时使用gotoxy(x,y)与gotoprint(x,y)配合在命令行中打印预览初始图像
2.接下来进入一个无限的循环(直到手动终止)中 该循环调用 printLife() 及使用Delay(a) 函数来控制延时 ,合理的控制延时可以更轻松的观赏 生命游戏的演化过程
2-1.printLife() 函数为整张地图显示判断的主要函数 其逻辑为: 先将map[][]地图数组数据 传入map1[][],以下对规则判断修改使用map1[][](其原因是因为,倘若使用map直接作为修改数组会影响修改后附近的存亡数,这将不符合游戏规则,修改增删必须以一次完全体的更改) 使用双重循环遍历map[][]地图数组中的数据 用其坐标载入 life(x,y) 函数 得出附近存活数,后使用count变量存储及开始对规则进行判断 判断得值使用 map1[][]地图数组进行修改,最后在修改后的map1数据传回map数组中作为下次遍历的地图数组
#include<stdio.h> #include<windows.h> #include<stdlib.h> #define Mx 50 //定义基础地图的x轴大小 #define My 50 //定义基础地图的y轴大小 char map[Mx][My]; //map数组 用于存储初始地图数据,以及每次循环的固态(是指循环时不对该数组进行实时更改)数据 char map1[Mx][My]; //map1数组 用于存储在遍历地图时,对数据的实时更改,但是不作为,游戏地图规则的判断数组,仅仅作为临时记录 void Delay(int a){ //用于控制延时(具体数值不明,须自己尝试) while (a--); } void gotoxy(int x, int y){ //用于设置命令行光标位置 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(handle, pos); } void gotodelete(int x, int y){ //用于清除命令行指定坐标的显示值 gotoxy(x, y); printf(" "); } void gotoprint(int x, int y){ //用于在指定命令行坐标进行打印 “o”值,是游戏中变化的直观表现 gotoxy(x, y); printf("o"); } void delMap(int x, int y) { //用于更改map数组中,指定坐标的值变为“ ”空字符 map[x][y] = ‘ ‘; } void enterMap(int x, int y) { //用于更改map数组中,指定坐标的值变为"o" map[x][y] = ‘o‘; } void delMap1(int x, int y) { //用于更改map1数组中,指定坐标的值变为“ ”空字符 map1[x][y] = ‘ ‘; } void enterMap1(int x, int y) { //用于更改map数组中,指定坐标的值变为"o" map1[x][y] = ‘o‘; } int life(int x, int y) { //用于判断每个坐标点,对齐附近“存活”数进行返回 int i = 0; if (map[x - 1][y - 1] == ‘o‘) i++; if (map[x - 1][y] == ‘o‘) i++; if (map[x - 1][y + 1] == ‘o‘) i++; if (map[x][y - 1] == ‘o‘) i++; if (map[x][y + 1] == ‘o‘) i++; if (map[x + 1][y - 1] == ‘o‘) i++; if (map[x + 1][y] == ‘o‘) i++; if (map[x + 1][y + 1] == ‘o‘) i++; return i; } void copyMap() { //用于遍历前将map数组的值,复制给map1数组 for (int i = 1; i < Mx - 1; i++) { for (int s = 1; s < My - 1; s++) { map1[i][s] = map[i][s]; } } } void copyMap1() { //用于遍历后将map1数组的值,复制给map数组 for (int i = 1; i < Mx - 1; i++) { for (int s = 1; s < My - 1; s++) { map[i][s] = map1[i][s]; } } } void printLife() { //主体进行函数 int count = 0; copyMap(); for (int i = 1; i < Mx - 1; i++) { for (int s = 1; s < My - 1; s++) { count = life(i, s); if (map[i][s] == ‘o‘) { if (count < 2) { gotodelete(s, i); delMap1(i, s); } else if (count == 2 || count == 3) { continue; } else if (count > 3) { gotodelete(s, i); delMap1(i, s); } } else { if (count == 3) { gotoprint(s, i); enterMap1(i, s); } } } } copyMap1(); } int main() { system("mode con: cols=60 lines=50"); int x, y, z = 1; gotoxy(51, 1); while (z <= 5) { gotoxy(51, z++); scanf_s("%d %d", &x, &y); enterMap(x, y); gotoprint(y, x); } //system("cls"); while (1) { Delay(99999999999); printLife(); } }