The Game Of Life(生命游戏,又称为细胞自动机)几乎是所有数据结构与算法导论教程前言的一个很经典的程序了。这是一个零玩家游戏,发生在一个平面网格里。每个格子的细胞都有死亡和存活两种状态,在代与代之间有两种状态,如果每一个细胞周围少于或等于1个细胞或多于4个细胞时,他会在下一代死亡;如果一个格子周围恰好有3个细胞,他将会重新活过来。

例如,当一种特别的状态被初始化后,会形成下列状态。

周期为4的轻量级飞船

也会有循环或者稳定的状态:

周期为3的脉冲星
周期为3的Cross

更有甚者发现的「滑行者枪」,可以源源不断地向外发射滑行者。

滑行者枪

接下来是一个用C++和控制台实现生命游戏的尝试。本可以很短小的,但上周闲下来的时候东增西补地加了许多东西,也算是当作初学面向对象的一个习题了吧,实现了一个可以自动运行,随机初始化和自定义规则的黑框框生命游戏。

运行效果

Source Code:

  1 #include "pch.h"
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <windows.h>
  6 constexpr int FIRST_INTRODUCTION = 0;
  7 constexpr int MANIPUNATE_INSTRUCTION = 1;
  8 constexpr int WITH_GENERATION_INFO = 1;
  9 constexpr int NO_GENERATION_INFO = 0;
 10 //Define rules;
 11 int BOTTOM_LIMIT = 1;
 12 int UPPER_LIMIT = 4;
 13 int REBIRTH_NUM = 3;
 14 //define characters to print
 15 const char LIVEC = '#';
 16 const char DIEC = '.';
 17 const int MAXL = 101;
 18 using namespace std;
 19 class LifeMap {
 20 public:
 21     int width;
 22     int height;
 23     int matrix[MAXL][MAXL] = { 0 };
 24     int surround[MAXL][MAXL] = { 0 };
 25     int generation = 0;
 26     void instructor(int type) {
 27         switch (type) {
 28         case FIRST_INTRODUCTION:
 29             cout << "Welcome to the Game of Life!" << endl << endl <<
 30                 "生命游戏是一个零玩家游戏,它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞。一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死了的细胞的数量。如果相邻方格活着的细胞数量过多,这个细胞会因为资源匮乏而在下一个时刻死去;相反,如果周围活细胞过少,这个细胞会因太孤单而死去。"
 31                 << endl << "实际中,你可以设定周围活细胞的数目怎样时才适宜该细胞的生存。如果这个数目设定过低,世界中的大部分细胞会因为找不到太多的活的邻居而死去,直到整个世界都没有生命;如果这个数目设定过高,世界中又会被生命充满而没有什么变化。所以我们把这个数目选取为2或者3;这样整个生命世界才不至于太过荒凉或拥挤,而是一种动态的平衡。"
 32                 << endl << "这样的话,游戏的规则就是:当一个方格周围有2或3个活细胞时,方格中的活细胞在下一个时刻继续存活;即使这个时刻方格中没有活细胞,在下一个时刻也会“诞生”活细胞。在这个游戏中,还可以设定一些更加复杂的规则,例如当前方格的状况不仅由父一代决定,而且还考虑祖父一代的情况。"
 33                 << endl << "你作为这个世界的上帝,随意设定某个方格细胞的死活,以观察对世界的影响。在游戏的进行中,杂乱无序的细胞会逐渐演化出各种精致、有形的结构;这些结构往往有很好的对称性,而且每一代都在变化形状。一些形状已经锁定,不会逐代变化。有时,一些已经成形的结构会因为一些无序细胞的“入侵”而被破坏。但是形状和秩序经常能从杂乱中产生出来。"
 34                 << endl << endl << " Please insert the width AND the height of the grid:" << endl << "(Max Length is " << MAXL - 2 << ")" << endl;
 35             break;
 36         case MANIPUNATE_INSTRUCTION:
 37             cout << endl << "Now you can insert \"L X Y\" (eg. L 2 3 or l 2 3 to set the cell located in the 2nd row, 3rd column) to set a cell to live,"
 38                 << endl << "insert \"D X Y\" to set a cell to die. insert \"P\" to print the current status."
 39                 << endl << "\"N\" for simply jump tp the next generation.\nN (optional)GENERATIONS (optional)INTERVAL_TIME for evolve multiple generation at a time."
 40                 << endl << "Insert \"R\" to reset your gird and \"Q\" to quit." << endl
 41                 << "Inset X to define rules."
 42                 << "Most interstingly, you can radomlize every cell by insert \"!\"" << endl << "You can set multiple cells' status in one line." << endl;
 43             break;
 44         }
 45
 46     }
 47     void initialize(int W, int H) {
 48         int i, j;
 49         for (i = 0; i < MAXL; i++) {
 50             for (j = 0; j < MAXL; j++) {
 51                 matrix[i][j] = 0;
 52                 surround[i][j] = 0;
 53             }
 54         }
 55         width = W;
 56         height = H;
 57         generation = 0;
 58     }
 59     void printer(int gen) {
 60         //gen = 1 for printing with generation info.
 61         if (gen == 1) {
 62             cout << "\n   Generation No." << generation << ":" << endl;
 63         }
 64         cout << endl;
 65         int i, j;
 66         cout << "  ";
 67         for (i = 0; i < width; i++) {
 68             printf("%2d ", i + 1);
 69         }
 70         cout << endl;
 71         for (i = 0; i < height; i++) {
 72             printf("%2d ", i + 1);
 73             for (j = 0; j < width; j++) {
 74                 if (matrix[i + 1][j + 1] == 0) printf("%c  ", DIEC);
 75                 else if (matrix[i + 1][j + 1] == 1) printf("%c  ", LIVEC);
 76             }
 77             cout << endl;
 78         }
 79         cout << endl;
 80         //print ratio
 81         if (gen == 1) {
 82             int liveCells = 0;
 83             for (i = 0; i < height; i++) {
 84                 for (j = 0; j < width; j++) {
 85                     if (matrix[i + 1][j + 1] == 1) liveCells++;
 86                 }
 87             }
 88             cout << "   Live cell ratio: " << (double)liveCells / (double)(width*height) * 100.0
 89                 << "% (" << liveCells << "/" << width * height << ")" << endl << endl;
 90         }
 91     }
 92     void SetLiving(int W, int H) {
 93         if (W <= 0 || W > width || H <= 0 || H > height)
 94             cout << "Unvalid input, please try again.\n";
 95         else {
 96             matrix[W][H] = 1;
 97             cout << "Cell (" << W << " ," << H << ") came alive." << endl;
 98         }
 99
100     }
101     void SetDying(int W, int H) {
102         if (W <= 0 || W > width || H <= 0 || H > height)
103             cout << "Unvalid input, please try again.\n";
104         else {
105             matrix[W][H] = 0;
106             cout << "Cell (" << W << " ," << H << ") has been dead." << endl;
107         }
108
109     }
110     void Radomlize() {
111         int i, j;
112         cout << "Randomlizing cell status..." << endl;
113         for (i = 0; i < height; i++) {
114             for (j = 0; j < width; j++) {
115                 //srand(time(NULL));
116                 if ((rand() % 2) == 1) matrix[i + 1][j + 1] = 0;
117                 else {
118                     matrix[i + 1][j + 1] = 1;
119                     cout << "Cell (" << i + 1 << " ," << j + 1 << ") came alive." << endl;
120                 }
121             }
122         }
123     }
124     void Next() {
125         int i, j;
126         //Initialize the surround matrix.
127         for (i = 0; i < MAXL; i++) {
128             for (j = 0; j < MAXL; j++) {
129                 surround[i][j] = 0;
130             }
131         }
132         //Calculate the surrounded live cells
133         for (i = 0; i < height; i++) {
134             for (j = 0; j < width; j++) {
135                 if (matrix[i][j] == 1) surround[i + 1][j + 1]++;
136                 if (matrix[i][j + 1] == 1) surround[i + 1][j + 1]++;
137                 if (matrix[i][j + 2] == 1) surround[i + 1][j + 1]++;
138                 if (matrix[i + 1][j] == 1) surround[i + 1][j + 1]++;
139                 if (matrix[i + 1][j + 2] == 1) surround[i + 1][j + 1]++;
140                 if (matrix[i + 2][j] == 1) surround[i + 1][j + 1]++;
141                 if (matrix[i + 2][j + 1] == 1) surround[i + 1][j + 1]++;
142                 if (matrix[i + 2][j + 2] == 1) surround[i + 1][j + 1]++;
143             }
144         }
145         //Rules
146         for (i = 0; i < height; i++) {
147             for (j = 0; j < width; j++) {
148                 if (surround[i + 1][j + 1] >= UPPER_LIMIT) matrix[i + 1][j + 1] = 0;
149                 if (surround[i + 1][j + 1] <= BOTTOM_LIMIT) matrix[i + 1][j + 1] = 0;
150                 if (surround[i + 1][j + 1] == REBIRTH_NUM) matrix[i + 1][j + 1] = 1;
151             }
152         }
153         generation++;
154     }
155     void Definer() {
156         int i, j, k;
157         cout << "Please insert three value to define the rules: (Defaul Configuration:1 4 3)" << endl
158             << "BOTTOM_LIMIT UPPER_LIMIT REBIRTH_NUM" << endl;
159     inputrule: cout << ">> "; cin >> i >> j >> k;
160         if (cin.fail() || i >= 8 || j >= 8 || k >= 8 || i < 0 || j < 0 || k < 0) {
161             cout << "Invalid input, please input three positive integers smaller than 8." << endl;
162             cin.clear();
163             while (cin.get() != '\n');
164             goto inputrule;
165         }
166         else {
167             BOTTOM_LIMIT = i;
168             UPPER_LIMIT = j;
169             REBIRTH_NUM = k;
170             printf("Rules have been defined to %d %d %d.\n", i, j, k);
171         }
172     }
173 };
174 int main()
175 {
176     LifeMap Map;
177     //These variables are used for manipunating.
178     int X, Y;
179     //these two labels are used for jumping for input that's too large and the reset command.
180 start: Map.instructor(FIRST_INTRODUCTION);
181 input: cin >> X >> Y;
182     while (cin.fail()) {
183         cout << "Unvalid input, please try again. Pleas type two integers." << endl;
184         cin.clear();
185         while (cin.get() != '\n') continue;
186         cin >> X >> Y;
187     }
188     while (X >= 100 || Y >= 100) {
189         cout << "Too long." << endl;
190         cin.clear();
191         goto input;
192     }
193     Map.instructor(MANIPUNATE_INSTRUCTION);
194     cout << "This is all the cells you have." << endl;
195     Map.initialize(X, Y);
196     Map.printer(NO_GENERATION_INFO);
197     cin.clear();
198     while (cin.get() != '\n') continue; // Clear datas in the cache.
199     char command;
200     while ((command = toupper(cin.get())) != 'Q') {
201         switch (command) {
202         case 'L':
203             cin >> X >> Y;
204             if (cin.fail()) {
205                 cout << "Unvalid input, please try again." << endl;
206                 cin.clear();
207                 while (cin.get() != '\n') continue;
208             }
209             else
210                 Map.SetLiving(X, Y);
211             break;
212         case 'D':
213             cin >> X >> Y;
214             if (cin.fail()) {
215                 cout << "Unvalid input, please try again." << endl;
216                 cin.clear();
217                 while (cin.get() != '\n') continue;
218             }
219             else
220                 Map.SetDying(X, Y);
221             break;
222         case 'P':
223             Map.printer(WITH_GENERATION_INFO);
224             break;
225         case 'N':
226             //gens mens the number of generations to evolve
227             //interval means the interval times between two evolutions
228             int i, gens, interval;
229             if (cin.get() != '\n') {
230                 cin >> gens;
231                 if (cin.get() == '\n') interval = 0;
232                 else cin >> interval;
233                 if (gens <= 0 || interval < 0) {
234                     cout << "Unvalid input, please enter positive integers." << endl;
235                     cin.clear();
236                     while (cin.get() != '\n') continue;
237                 }
238                 else {
239                     for (i = 0; i < gens; i++) {
240                         system("cls");
241                         Map.instructor(MANIPUNATE_INSTRUCTION);
242                         Map.Next();
243                         Map.printer(WITH_GENERATION_INFO);
244                         Sleep(interval);
245                     }
246                 }
247             }
248             else {
249                 system("cls");
250                 Map.instructor(MANIPUNATE_INSTRUCTION);
251                 Map.Next();
252                 Map.printer(WITH_GENERATION_INFO);
253             }
254             break;
255         case 'R':
256             system("cls");
257             goto start;
258             break;
259         case '!':
260             Map.Radomlize();
261             cout << "OK, now it's just chaos." << endl;
262             Map.printer(WITH_GENERATION_INFO);
263             break;
264         case 'X':
265             Map.Definer();
266         case '\n': break;
267         case ' ': break;
268         default:
269             cout << "Unknown Command:(" << endl;
270             //while (cin.get() != '\n') continue;
271         }
272     }
273     cout << "See you:)\n\n";
274     system("pause");
275     return 0;
276 }
277  

GitHub:https://github.com/BillChen2000/LearnigRepo/blob/master/Course/数据结构与算法/LifeGame/

图源:https://www.guokr.com/article/439770/

另外这里还有一个LifeWiki有详细的整理和介绍:http://www.conwaylife.com/wiki/

来源:https://billc.io/2019/02/the-game-of-life/

转载于:https://www.cnblogs.com/BillChen2000/p/the-game-of-life.html

The Game Of Life – 数据结构与算法的敲门砖相关推荐

  1. Python3-Cookbook总结 - 第一章:数据结构和算法

    第一章:数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. ...

  2. 推荐一个关于.NET平台数据结构和算法的好项目

    http://www.codeplex.com/NGenerics 这是一个类库,它提供了标准的.NET框架没有实现的通用的数据结构和算法.值得大家研究. 转载于:https://www.cnblog ...

  3. 数据结构和算法:(3)3.1线性表的顺序存储结构

    -----------------------1.线性表基础操作------------------------ 线性表:(List)由零个或多个数据元素组成的有限序列. 首先他是一个序列,元素之间是 ...

  4. weiss数据结构和算法书的使用说明

    <数据结构与算法分析 C语言描述>Mark Allen Weiss著,冯舜玺译,机械工业出版社.Weiss教授的经典教材三部曲之一,其中的C语言描述版本,也就是本书,被称为20世纪最重要的 ...

  5. 数据结构和算法 -- 学习导图

    数据结构和算法 是作为程序员写出高效代码的基础,为了今后的两年在高效代码之路上持续精进,将按照此学习导图进行 算法和数据结构的刻意练习,同时也希望为同样有高效代码追求的伙伴们提供一条学习路径,共同进步 ...

  6. Java数据结构与算法(第四章栈和队列)

    2019独角兽企业重金招聘Python工程师标准>>> 本章涉及的三种数据存储类型:栈.队列和优先级队列. 不同类型的结构 程序员的工具 数组是已经介绍过的数据存储结构,和其他结构( ...

  7. python数据结构与算法总结

    python常用的数据结构与算法就分享到此处,本月涉及数据结构与算法的内容有如下文章: <数据结构和算法对python意味着什么?> <顺序表数据结构在python中的应用> ...

  8. 学习JavaScript数据结构与算法(一):栈与队列

    本系列的第一篇文章: 学习JavaScript数据结构与算法(一),栈与队列 第二篇文章:学习JavaScript数据结构与算法(二):链表 第三篇文章:学习JavaScript数据结构与算法(三): ...

  9. MySQL索引背后的数据结构及算法原理【转】

    http://blog.codinglabs.org/articles/theory-of-mysql-index.html MySQL索引背后的数据结构及算法原理[转] 摘要 本文以MySQL数据库 ...

  10. 数据结构与算法:22 精选练习50

    精选练习50 马上就要期末考试或者考研了.为了大家复习的方便,我精选了有关数据结构与算法的50道选择题,大家可以抽空练习一下.公众号后台回复"答案"可以获取该50道题目的答案. 0 ...

最新文章

  1. 线阵相机和面阵相机的区别及应用
  2. 如何实现动态加载删除android,关于android:融云IMKit-动态删除或添加plugin-的实现...
  3. python歌星大奖赛_在歌星大奖赛中,有10个评委为参赛选手打分,分数为1到100分。...
  4. hdu5693 D gamehdu 5712 D++ game
  5. 最近30分钟合约市场爆仓702万美元 BTC爆仓281万美元
  6. opencl编程简单的入门知识
  7. 小红伞杀毒软件|小红伞杀毒软件下载
  8. Luarocks的使用
  9. 全网最全Linux命令总结!!(史上最全,建议收藏)
  10. 关于Ubuntu下firefox无法观看视频的解决
  11. Simulink 快速入门(二)--创建简单模型
  12. Java抓取网页图片
  13. oracle box怎么全屏,Oracle VM VirtualBox 虚拟机设置全屏与共享
  14. PHY--PDCCH
  15. LNMP架构动态网页
  16. js vue 获取 (昨天、今天、明天) 时间
  17. android homme2016款,#攻势来袭#Android Homme 2016 x DEAL线下预定全面开启
  18. echarts 双y轴设置
  19. 从零开始学java(二十六)--多维数组,多维数组存储表格数据
  20. 前端开发——Ionic 3.0【爱创课堂专业前端培训】

热门文章

  1. 2021 年 4 月程序员工资统计,这太可怕了……
  2. IntelliJ IDEA 调试技巧,比 Eclipse 强太多了!
  3. 再谈如何成为一名优秀CTO
  4. 「做点事」科技公司成立了!
  5. Android Studio 2.0来啦
  6. 电子书下载:MySQL5权威指南(第3版)
  7. R语言--字符串操作
  8. 德国Vue.js2终极开发教程024--32
  9. 二维码QR码的“疯狂”广告
  10. IE无法执行JavaScript解决办法