算法 - 关于Conways生命游戏的极端细节

时间:2016-07-29 14:11:04

标签: algorithm conways-game-of-life

我的查询很难描述,所以我会尽量简洁地解释它。

在康威的生命游戏中,让我们说我有一张这样的地图:

_   _   _   _   _
_   _   _   _   _
U   _   R   Y   _
_   T   _   X   _
_   Z   _   C   _

不是循环遍历每一个单元格,包括那些不可能变得相关的死亡单元格,而是说我将每个活着的单元格置于LinkedList内的第0代。在每一代更新后,我将遍历整个LinkedList并执行Conway生命游戏中每个规则的规则。这样我就可以避免无缘无故地迭代大范围的死细胞。

其中一条规则指出a dead cell with 3 living neighbors becomes living。由于我只在我的算法中迭代生活单元格,所以我可以通过查看死细胞中的唯一方式查看死细胞的邻居LinkedList。我必须为我的LinkedList中的每个项目循环遍历该单元格的所有相邻单元格,并且对于每个相邻单元格,我将不得不环顾该单元格,计算它是否有三个邻居,然后将其设置为alive然后将其添加为LinkedList内的活细胞。

我的问题:

显然,我的LinkedList会很快变得杂乱无章,并且位于左上角 - >右下方的顺序了。例如,在我上面提供的图中,linkedList中的第一个单元格可能是C,第二个单元格可能是R,第三个单元格可能是T。当新细胞诞生时,我会将它们添加到我的LinkedList中,并按照它们被添加的顺序在下一代中迭代它们。

游戏规则是否合法,还是需要从左上角到右下角遍历整个2D阵列?这些规则非常含糊不清。

  

任何活着的邻居少于两个的活细胞都会死亡,就像人口不足一样。

     

任何有两三个活邻居的活细胞都会生活在下一代。

     

任何有三个以上活着的邻居的活细胞都会死亡,好像人口过多一样。

     

任何有三个活着的邻居的死细胞都会成为活细胞,好像通过繁殖一样。

我是否需要遍历整个2D阵列,执行规则:

  

任何活的邻居少于两个的活细胞都会死亡,好像是由于人口不足造成的。

然后再次遍历整个2D数组并执行规则:

  

任何有两三个活邻居的活细胞都会留在下一代。

到底有没有关系?我读了这么多帖子,似乎没有人提到这个话题。

感谢。

2 个答案:

答案 0 :(得分:2)

在康威的生活游戏中,整个矩阵应该只循环一次:所有变化都是同时完成的。

这实际上会导致需要两个矩阵:旧状态和新状态。对于旧状态中的每个单元,您计算一个活动邻居计数。然后,如果细胞存活并且有2或3个邻居,它将继续存在于新矩阵中。如果细胞不活着并且有3个邻居,它会产生。否则就死了。

链表的问题是查找邻居计数。由于必须搜索整个列表以计算邻居,因此生成下一代的活动单元数量为O(n^2)。此外,您必须检查链表中单元格的每个邻居,因为它们会产生。

答案 1 :(得分:0)

您应该每次移动都重新创建链接列表。 Conway的生命游戏是轮流处理的,所有生活的死细胞都不算生活在当前转弯处,所有死亡的活细胞在当前转弯时都算不上死亡。因此,使用LinkedList方法,您可以拥有两个列表(我会说哈希表,因为您需要一个快速函数来检查对象是否已经在列表中),一个表示当前的活细胞集,其他代表收集的一组细胞,它们将在下一回合活着。然后,遍历第一组单元格,抓取当前单元格的相邻单元格,将它们填入下一轮的“邻居”等于1的列表中,并增加每个处理的活细胞的值。此外,当前的活细胞应该被添加到具有“活”标志集和邻居0的集合中。伪代码:

ArrayCollection.<Cell> existing; // currently alive cells
ArrayCollection.<Cell> next; // next turn
void processTurn() {
    next.clear();
    for each (Cell cell in existing) {
        Cell nextTC=next.getByParameters(cell); // check presence by X and Y
        if (nextTC) nextTC.alive=true; else   
            next.addNewCell(cell.x,cell.y,0,true); // add a new element
            // 0 is current neighbors, true is alive flag
        for each (Cell neigh in cell.neighbors) {
            nextTC=next.getByParameters(neigh);
            if (nextTC) nextTC.neighbors++; else   
                next.addNewCell(cell.x,cell.y,1,false); // add a new element
                // added a dead cell with 1 neighbor - currently processed alive cell
        }
    }
    for each (cell in next) {
        if (!cell.alive && (cell.neighbors==3)) cell.alive=true; else
        if (cell.alive && ((cell.neighbors==2) || (cell.neighbors==3))) ; // no change
        else next.remove(cell); // dead cell that either was alive or failed to become alive
    }
    swap(current,next);
}