Javascript 康威';s生命游戏-超越网格
好吧,有很多“康威的人生游戏”的问题,但这一个是相当具体的。我将首先向您抛出一堆代码,将其分解并向您展示问题所在 到目前为止,这里是我的Conway的生命游戏实现,现在它仅限于用于调试的控制台(JSFIDLE--启动它,打开您的控制台): 注意:AliveJavascript 康威';s生命游戏-超越网格,javascript,conways-game-of-life,Javascript,Conways Game Of Life,好吧,有很多“康威的人生游戏”的问题,但这一个是相当具体的。我将首先向您抛出一堆代码,将其分解并向您展示问题所在 到目前为止,这里是我的Conway的生命游戏实现,现在它仅限于用于调试的控制台(JSFIDLE--启动它,打开您的控制台): 注意:AliveShadowCells将不会被垃圾收集,因为它们与其他单元格一起存储在一个数组中(我通过调试确定这一点,请参阅控制台输出中的单元格计数,并对可见单元格进行计数) 由于某种原因,ShadowCell类似乎会导致邻居报告不正确。我曾试图通过追踪每一
ShadowCell
s将不会被垃圾收集,因为它们与其他单元格一起存储在一个数组中(我通过调试确定这一点,请参阅控制台输出中的单元格计数,并对可见单元格进行计数)
由于某种原因,ShadowCell
类似乎会导致邻居报告不正确。我曾试图通过追踪每一代细胞的创建、删除和计数邻居来调试它,但我的大脑在它能够把所有这些都放在一起之前就死了。对于我所有的调试工作,我不明白为什么会发生这种行为ShadowCell
与使用它的所有其他单元(它们使用完全相同的位置函数等)的单元几乎相同,但它没有被渲染的事实不应该是造成这种情况的原因
对于第4代,我通过记录阴影贴图的创建来获得以下输出,我可以看到每一代都创建一次阴影贴图(注意:该类不会显示,因为我使用了utils.extend()
来创建阴影贴图的快照):
像这样登录第152行:
if (!shadowCellHash[key]) {
neighbour = shadowCellHash[key] = new ShadowCell(coords[0], coords[1]);
neighbour.neighbourCoords = cell.neighbourCoords;
console.log(utils.extend({}, neighbour));
} else {
shadowCellHash
在开始在每个单元格中循环查找邻居之前,不会使用所有的ShadowCell
初始化。当循环检查[5,-1]
邻居时,它找不到[6,-1]
,因为它不在shadowCellHash
中。由于未找到[6,-1]
,因此会创建一个新的死[6,-1]
,并且[5,-1]
不会生成,因为它没有足够的活邻居
我想我已经解决了你的问题,我急切地在每个世界的开头重新填充shadowCellHash
。勾选
//每次勾选后,此哈希都会超出范围,从而允许垃圾收集任何死掉的阴影单元格
如果(!this.settings.wrap){
var shadowCellHash={};
for(var i=0;i
(我的坐标:左上角为[0,0],右下角为正)。基于其他阴影单元创建阴影单元是否会有问题?考虑<代码> GE4,[ 5,-1 ] < /代码>。这个细胞需要Gen3,[6,-1]
,一个阴影细胞才能存活。如果[5,-1]
永远不会诞生,你的第五代场景就会发生。@Nathan,这是可能的,尽管在每一代开始时处于活动状态的阴影单元
与其他单元
类从同一数组中提取,并执行相同的功能(它们共享一个基于每个单元格坐标的动态定位功能)。我已经记录了其中一些的诞生,并且可以确认(至少有一些)是被创建的,但由于某些原因,它们与周围环境的交互不太友好。@Nathan Scratch我的最后一条评论-我在第4代中为它们的创建添加了一些日志输出。当然!我没有想到邻居会在散列之前寻找活细胞……很高兴看到算法工作:)只是快速更新。。。我使用另一个保持被引用的散列实现了这个修复(对象死后会被取消分配),因为如果我能帮助的话,我有循环恐惧症。非常感谢。
// This hash goes out of scope after each tick allowing any dead shadowCells to be garbage collected
if (!this.settings.wrap) {
var shadowCellHash = {};
}
for (var i = 0, iLen = this.lifeList.length; i < iLen; ++i) {
var cell = this.lifeList[i];
if (cell.key) {
shadowCellHash[cell.key] = cell;
}
cell.neighbours = 0;
cell.lastIterated = this.generation;
for (var j = 0, jLen = cell.neighbourCoords.length; j < jLen; ++j) {
var coords;
var neighbour;
if (this.settings.wrap) {
coords = cell.neighbourCoords[j];
neighbour = this.cellList[coords[0]][coords[1]];
} else {
coords = cell.neighbourCoords[j](cell);
if (coords[0] > this.maxX || coords[0] < 0 || coords[1] > this.maxY || coords[1] < 0) {
// This neighbour is off the screen so will require a shadowCell
var key = ''+coords[0]+','+coords[1];
if (!shadowCellHash[key]) {
// ShadowCell not in hash, let's create one
neighbour = shadowCellHash[key] = new ShadowCell(coords[0], coords[1]);
neighbour.neighbourCoords = cell.neighbourCoords;
// NOTE: neighbourCoords are a set of functions that return values relative to the cell you pass to them. I am not literally giving the `ShadowCell` the same neighbour positions here.
} else {
neighbour = shadowCellHash[key];
}
} else {
// This neighbour is on screen, grab its cell.
neighbour = this.cellList[coords[0]][coords[1]];
}
}
...
Object {x: 5, y: -1, key: "5,-1", neighbourCoords: Array[8], neighbours: 0…}
Object {x: 6, y: -1, key: "6,-1", neighbourCoords: Array[8], neighbours: 0…}
Object {x: 7, y: -1, key: "7,-1", neighbourCoords: Array[8], neighbours: 0…}
Object {x: 4, y: -1, key: "4,-1", neighbourCoords: Array[8], neighbours: 0…}
Object {x: -1, y: 1, key: "-1,1", neighbourCoords: Array[8], neighbours: 0…}
Object {x: -1, y: 2, key: "-1,2", neighbourCoords: Array[8], neighbours: 0…}
Object {x: -1, y: 3, key: "-1,3", neighbourCoords: Array[8], neighbours: 0…}
Object {x: 5, y: -2, key: "5,-2", neighbourCoords: Array[8], neighbours: 0…}
Object {x: 6, y: -2, key: "6,-2", neighbourCoords: Array[8], neighbours: 0…}
Object {x: 7, y: -2, key: "7,-2", neighbourCoords: Array[8], neighbours: 0…}
Object {x: -1, y: 4, key: "-1,4", neighbourCoords: Array[8], neighbours: 0…}
if (!shadowCellHash[key]) {
neighbour = shadowCellHash[key] = new ShadowCell(coords[0], coords[1]);
neighbour.neighbourCoords = cell.neighbourCoords;
console.log(utils.extend({}, neighbour));
} else {
// This hash goes out of scope after each tick allowing any dead shadowCells to be garbage collected
if (!this.settings.wrap) {
var shadowCellHash = {};
for (var i = 0; i < this.lifeList.length; i++) {
var cell = this.lifeList[i];
if (cell.key) {
shadowCellHash[cell.key] = cell;
}
}
}