CellularAutomation(细胞自己主动机)

细胞自己主动机(英语:Cellular automaton)。又称格状自己主动机、元胞自己主动机,是一种离散模型,在可算性理论、数学及理论生物学都有相关研究。它是由无限个有规律、坚硬的方格组成。每格均处于一种有限状态。整个格网能够是不论什么有限维的。同一时候也是离散的。每格于t时的态由 t-1时的一集有限格(这集叫那格的邻域)的态决定。 每一格的“邻居”都是已被固定的。(一格能够是自己的邻居。)每次演进时。每格均遵从同一规矩一齐演进。

就形式而言,细胞自己主动机有三个特征:

平行计算(parallel computation):每一个细胞个体都同一时候同步的改变
局部的(local):细胞的状态变化仅仅受周遭细胞的影响。

一致性的(homogeneous):全部细胞均受相同的规则所支配

生命游戏

生命游戏中,对于随意细胞,规则例如以下:
每一个细胞有两种状态-存活或死亡,每一个细胞与以自身为中心的周围八格细胞产生互动。(如图,黑色为存活,白色为死亡)

当前细胞为存活状态时。当周围低于2个(不包括2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
当前细胞为存活状态时。当周围有2个或3个存活细胞时, 该细胞保持原样。

当前细胞为存活状态时。当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
当前细胞为死亡状态时。当周围有3个存活细胞时。该细胞变成存活状态。 (模拟生殖)
能够把最初的细胞结构定义为种子。当全部在种子中的细胞同一时候被以上规则处理后, 能够得到第一代细胞图。按规则继续处理当前的细胞图,能够得到下一代的细胞图。周而复始。

在这个游戏中。还能够设定一些更加复杂的规则。比如当前方格的状况不仅由父一代决定。并且还考虑祖父一代的情况。玩家还能够作为这个世界的“上帝”,随意设定某个方格细胞的死活。以观察对世界的影响。

在游戏的进行中,杂乱无序的细胞会逐渐演化出各种精致、有形的结构;这些结构往往有非常好的对称性。并且每一代都在变化形状。

一些形状已经锁定。不会逐代变化。有时。一些已经成形的结构会由于一些无序细胞的“入侵”而被破坏。可是形状和秩序经常能从杂乱中产生出来。

有个能够直接玩这个游戏的链接 - Game of Life

以下用Unity自己写一下。

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public enum State{
  5. Died,
  6. Living
  7. };
  8.  
  9. public class Cell
  10. {
  11. public State currentState;
  12. }
  13.  
  14. public class Earth : MonoBehaviour {
  15. public int width;
  16. public int height;
  17.  
  18. public string seed;
  19. public bool useRandomSeed;
  20.  
  21. public float updateInterval = 1.0f;
  22. float refreshTime = -1f;
  23.  
  24. [Range(0, 100)]
  25. public int randomFillPercent;
  26.  
  27. Cell[,] map;
  28. Cell[,] mapTmp;
  29.  
  30. // Use this for initialization
  31. void Start () {
  32. map = new Cell[width,height];
  33. mapTmp = new Cell[width, height];
  34.  
  35. for (int i = 0; i < width; i++)
  36. for (int j = 0; j < height; j++)
  37. {
  38. map[i,j] = new Cell();
  39. map[i, j].currentState = State.Died;
  40.  
  41. mapTmp[i, j] = new Cell();
  42. mapTmp[i, j].currentState = State.Died;
  43. }
  44. initEarth();
  45. }
  46.  
  47. // Update is called once per frame
  48. void Update () {
  49. if(Time.time - refreshTime > updateInterval)
  50. {
  51. UpdateEarth();
  52. refreshTime = Time.time;
  53. }
  54. }
  55.  
  56. void UpdateEarth()
  57. {
  58. for (int x = 0; x < width; x++)
  59. {
  60. for (int y = 0; y < height; y++)
  61. {
  62. mapTmp[x, y].currentState = map[x, y].currentState;
  63. int neighbourLiveCells = GetSurroundingLiveCells(x, y);
  64. if (map[x, y].currentState == State.Died && neighbourLiveCells == 3)
  65. {
  66. mapTmp[x, y].currentState = State.Living;
  67. }
  68. if (map[x, y].currentState == State.Living)
  69. {
  70. if(neighbourLiveCells < 2)
  71. {
  72. mapTmp[x, y].currentState = State.Died;
  73. }else if( neighbourLiveCells > 3)
  74. {
  75. mapTmp[x, y].currentState = State.Died;
  76. }
  77. else
  78. {
  79. mapTmp[x, y].currentState = State.Living;
  80. }
  81. }
  82. }
  83. }
  84.  
  85. for (int x = 0; x < width; x++)
  86. for (int y = 0; y < height; y++)
  87. {
  88. map[x, y].currentState = mapTmp[x, y].currentState;
  89. }
  90. }
  91.  
  92. int GetSurroundingLiveCells(int gridX, int gridY)
  93. {
  94. int count = 0;
  95. for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX++)
  96. {
  97. for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY++)
  98. {
  99. if (neighbourX >= 0 && neighbourX < width && neighbourY >= 0 && neighbourY < height)
  100. {
  101. if (neighbourX != gridX || neighbourY != gridY)
  102. {
  103. count += map[neighbourX, neighbourY].currentState == State.Living? 1 : 0;
  104. }
  105. }
  106. }
  107. }
  108.  
  109. return count;
  110. }
  111.  
  112. void initEarth()
  113. {
  114. if (useRandomSeed)
  115. {
  116. seed = Time.time.ToString();
  117. }
  118.  
  119. System.Random pseudoRandom = new System.Random(seed.GetHashCode());
  120.  
  121. for (int x = 0; x < width; x++)
  122. {
  123. for (int y = 0; y < height; y++)
  124. {
  125. if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
  126. {
  127. map[x, y].currentState = State.Living;
  128. }
  129. else
  130. {
  131. map[x, y].currentState = (pseudoRandom.Next(0, 100) < randomFillPercent) ? State.Living : State.Died;
  132. }
  133. }
  134. }
  135.  
  136. }
  137.  
  138. void OnDrawGizmos()
  139. {
  140. if (map != null)
  141. {
  142. for (int x = 0; x < width; x++)
  143. {
  144. for (int y = 0; y < height; y++)
  145. {
  146. if (map[x, y] != null)
  147. {
  148. Gizmos.color = (map[x, y].currentState == State.Living) ? Color.black : Color.white;
  149. Vector3 pos = new Vector3(-width / 2 + x + .5f, 0, -height / 2 + y + .5f);
  150. Gizmos.DrawCube(pos, Vector3.one);
  151. }
  152. }
  153. }
  154. }
  155. }
  156. }

代码事实上就是依照前面算法的描写叙述实现出来。

初始的细胞分布用了Unity自带的随机来生成,然后在OnDrawGizmos函数中绘制出来。

执行起来是这种:

能够将初始状态设置为经典的glider,改动 initEarth() 函数就能够了。

  1. //Glider
  2. map[20, 20].currentState = State.Living;
  3. map[20, 21].currentState = State.Living;
  4. map[20, 22].currentState = State.Living;
  5. map[21, 22].currentState = State.Living;
  6. map[22, 21].currentState = State.Living;

程序生成地形

程序生成有非常多中方法,利用细胞自己主动机主要用生成地牢等相似的地形,经常使用于Roguelike类的游戏。

基本的算法就是还是利用细胞生存的规则,比方如今规定仅仅要细胞周围有四个以上的细胞,该细胞就存活,否则死去。

  1. for (int x = 0; x < width; x++)
  2. {
  3. for (int y = 0; y < height; y++)
  4. {
  5. int neighbourWallTiles = GetSurroundingWallCount(x, y);
  6.  
  7. if (neighbourWallTiles > 4)
  8. map[x, y] = 1;
  9. else if (neighbourWallTiles < 4)
  10. map[x, y] = 0;
  11.  
  12. }
  13. }

不断迭代,就能够得到一张地图。当然首先还是要在画布上随机分布一些细胞。迭代5次,终于生成地图例如以下

    

代码清单

  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class MapGenerator : MonoBehaviour {
  5. public int width;
  6. public int height;
  7.  
  8. public string seed;
  9. public bool useRandomSeed;
  10.  
  11. [Range(0, 100)]
  12. public int randomFillPercent;
  13.  
  14. int[,] map;
  15. // Use this for initialization
  16. void Start () {
  17. GenerateMap();
  18. }
  19.  
  20. // Update is called once per frame
  21. void Update () {
  22. if (Input.GetMouseButtonDown(0))
  23. {
  24. GenerateMap();
  25. }
  26. }
  27.  
  28. void GenerateMap()
  29. {
  30. map = new int[width, height];
  31. RandomFillMap();
  32.  
  33. for (int i = 0; i < 5; i++)
  34. {
  35. SmoothMap();
  36. }
  37. }
  38.  
  39. void RandomFillMap()
  40. {
  41. if (useRandomSeed)
  42. {
  43. seed = Time.time.ToString();
  44. }
  45.  
  46. System.Random pseudoRandom = new System.Random(seed.GetHashCode());
  47.  
  48. for (int x = 0; x < width; x++)
  49. {
  50. for (int y = 0; y < height; y++)
  51. {
  52. if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
  53. {
  54. map[x, y] = 1;
  55. }
  56. else
  57. {
  58. map[x, y] = (pseudoRandom.Next(0, 100) < randomFillPercent) ? 1 : 0;
  59. }
  60. }
  61. }
  62. }
  63.  
  64. void SmoothMap()
  65. {
  66. for (int x = 0; x < width; x++)
  67. {
  68. for (int y = 0; y < height; y++)
  69. {
  70. int neighbourWallTiles = GetSurroundingWallCount(x, y);
  71.  
  72. if (neighbourWallTiles > 4)
  73. map[x, y] = 1;
  74. else if (neighbourWallTiles < 4)
  75. map[x, y] = 0;
  76.  
  77. }
  78. }
  79. }
  80.  
  81. int GetSurroundingWallCount(int gridX, int gridY)
  82. {
  83. int wallCount = 0;
  84. for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX++)
  85. {
  86. for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY++)
  87. {
  88. if (neighbourX >= 0 && neighbourX < width && neighbourY >= 0 && neighbourY < height)
  89. {
  90. if (neighbourX != gridX || neighbourY != gridY)
  91. {
  92. wallCount += map[neighbourX, neighbourY];
  93. }
  94. }
  95. else
  96. {
  97. wallCount++;
  98. }
  99. }
  100. }
  101. return wallCount;
  102. }
  103.  
  104. void OnDrawGizmos()
  105. {
  106. if (map != null)
  107. {
  108. for (int x = 0; x < width; x++)
  109. {
  110. for (int y = 0; y < height; y++)
  111. {
  112. Gizmos.color = (map[x, y] == 1) ?
  113.  
  114. Color.black : Color.white;
  115. Vector3 pos = new Vector3(-width / 2 + x + .5f, 0, -height / 2 + y + .5f);
  116. Gizmos.DrawCube(pos, Vector3.one);
  117. }
  118. }
  119. }
  120. }
  121. }

參考

细胞自己主动机wiki - https://zh.wikipedia.org/wiki/%E7%B4%B0%E8%83%9E%E8%87%AA%E5%8B%95%E6%A9%9F

Game of Life - http://www.bitstorm.org/gameoflife/

Procedural Cave Generation Project Icon - https://unity3d.com/learn/tutorials/projects/procedural-cave-generation-tutorial

CellularAutomation(细胞自己主动机)的更多相关文章

  1. POJ 2778 DNA Sequence (AC自己主动机 + dp)

    DNA Sequence 题意:DNA的序列由ACTG四个字母组成,如今给定m个不可行的序列.问随机构成的长度为n的序列中.有多少种序列是可行的(仅仅要包括一个不可行序列便不可行).个数非常大.对10 ...

  2. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

  3. 【UVA】1449-Dominating Patterns(AC自己主动机)

    AC自己主动机的模板题.须要注意的是,对于每一个字符串,须要利用map将它映射到一个结点上,这样才干按顺序输出结果. 14360841 1449 option=com_onlinejudge& ...

  4. POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)

    http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...

  5. HDU 2896 病毒侵袭 AC自己主动机题解

    本题是在text里面查找key word的增强版.由于这里有多个text. 那么就不能够简单把Trie的叶子标志记录改动成-1进行加速了,能够使用其它技术.我直接使用个vis数组记录已经訪问过的节点, ...

  6. NYOJ 1085 数单词 (AC自己主动机模板题)

    数单词 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描写叙述 为了可以顺利通过英语四六级考试,如今大家每天早上都会早起读英语. LYH本来以为自己在6月份的考试中能够通过六 ...

  7. hdu 4057 AC自己主动机+状态压缩dp

    http://acm.hdu.edu.cn/showproblem.php?pid=4057 Problem Description Dr. X is a biologist, who likes r ...

  8. Keywords Search (ac 自己主动机)

    Keywords Search Problem Description In the modern time, Search engine came into the life of everybod ...

  9. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

随机推荐

  1. Python中的socket网络编程(TCP/IP,UDP)讲解

    在网络编程中的一个基本组件就是套接字(socket).套接字基本上是两个端点的程序之间的"信息通道".程序可能分布在不同的计算机上,通过套接字互相发送信息.套接字包括两个:服务器套 ...

  2. POJ 2955 区间DP Brackets

    求一个括号的最大匹配数,这个题可以和UVa 1626比较着看. 注意题目背景一样,但是所求不一样. 回到这道题上来,设d(i, j)表示子序列Si ~ Sj的字符串中最大匹配数,如果Si 与 Sj能配 ...

  3. python基础学习笔记——collections模块

    在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict.namedtuple和Ord ...

  4. URI URL URN 关系

    我们一起来看下面这个虚构的例子.这是一个URI: http://bitpoetry.io/posts/hello.html#intro 我们开始分析 http:// 是定义如何访问资源的方式.另外 b ...

  5. 【SaltStack】一些常用模块举例

    一.用户和用户组模块 说明:该sls文件用来在Minion端创建nginx用户和nginx用户组,当创建nginx用户时,对nginx用户组是否已存在做判断! (1)  /srv/salt/creat ...

  6. docker+Battery Historian 环境搭建(电量分析)

    docker 安装(windows) 1.  下载 https://docs.docker.com/docker-for-windows/install/  和 安装和添加环境变量(...) 2. 安 ...

  7. H5系列之History(必知必会)

    H5系列之History(必知必会)   目录 概念 兼容性 属性 方法 H5方法       概念     理解History Api的使用方式 目的是为了解决哪些问题   作用:ajax获取数据时 ...

  8. 七、docker基本命令

    Docker 基本命令 docker的基本命令 docker version :查看docker的版本号,包括客户端.服务端.依赖的Go等 [root@centos7 ~]# docker versi ...

  9. liunx 根目录介绍

    1. /bin binary二进制 存放系统许多可执行程序文件 执行的相关指令,例如ls pwd whoami,后台的支持文件目录 2. /sbin super binary超级的二进制 存放系统许多 ...

  10. 图论trainning-part-1 F. Highways

    F. Highways Time Limit: 1000ms Memory Limit: 10000KB 64-bit integer IO format: %lld      Java class ...