我的查询很难描述,所以我会尽量简洁地解释它。
在康威的生命游戏中,让我们说我有一张这样的地图:
_ _ _ _ _
_ _ _ _ _
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数组并执行规则:
任何有两三个活邻居的活细胞都会留在下一代。
到底有没有关系?我读了这么多帖子,似乎没有人提到这个话题。
感谢。
答案 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);
}