2017-04-21 66 views
1

花了一些时间在HTML画布中使用Javascript实现Conways游戏。康威的生命游戏算法错误(又名复制二维数组问题)

我的细胞没有充当期待。它似乎正在拾取比实际存在的更多的相邻细胞,并移除不应该被移除的细胞。任何帮助,将不胜感激!

//Globals 
 
var currentCells = [ 
 
[0,0,0,0,0,0,0,0], 
 
[0,0,0,0,0,0,0,0], 
 
[0,0,0,1,1,1,0,0], 
 
[0,0,0,0,0,0,0,0], 
 
[0,0,0,0,0,0,0,0], 
 
[0,0,0,0,0,0,0,0], 
 
[0,0,0,0,0,0,0,0], 
 
[0,0,0,0,0,0,0,0], 
 
]; 
 
var currentGrid = currentCells; 
 
var lastGrid = currentCells; 
 

 
var cellsX = currentCells[1].length; 
 
var cellsY = currentCells.length; 
 

 
var canvas_id = "gameGrid"; 
 
var gridWidth = 100; 
 
var gridHeight = 50; 
 

 
var c = document.getElementById("gameGrid"); 
 
var ctx = c.getContext("2d"); 
 

 
var cellWidth = gridWidth/cellsX; 
 
var cellHeight = gridHeight/cellsY; 
 
ctx.fillStyle = "yellow"; 
 

 
window.setInterval(step, 1000); 
 

 

 

 
function move(){ 
 

 

 
for(var a=0;a<cellsX;a++) { 
 

 
    for(var b=0; b<cellsY;b++) { 
 

 
     if (a > 0 && b > 0 && a < cellsY - 1 && b < cellsX){ //centre cells only 
 

 
      var currentNeighbours = neighbourCount(a, b); 
 

 

 

 
      if (lastGrid[a][b] == 0){ 
 

 
       if(currentNeighbours == 3){ 
 

 
        currentGrid[a][b] = 1; 
 

 
       } 
 

 
      }else if (lastGrid[a][b] == 1){ 
 

 
       if(currentNeighbours > 3 || currentNeighbours < 2){ 
 

 
        currentGrid[a][b] = 0; 
 

 
        //console.log("triggered " + currentNeighbours); 
 

 
       } 
 
      } 
 
     } 
 
    } 
 
} 
 
lastGrid = currentGrid; 
 
} 
 

 
function neighbourCount(a, b){ 
 

 
var currentNeighbours = 0; 
 

 
if(lastGrid[a-1][b] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a+1][b] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a][b-1] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a][b+1] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a-1][b-1] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a+1][b+1] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a-1][b+1] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 
if(lastGrid[a+1][b-1] == 1){ // 
 

 
    currentNeighbours = currentNeighbours + 1; 
 

 
} 
 

 
//console.log(currentNeighbours); 
 

 
return currentNeighbours; 
 
} 
 

 

 
function Draw(){ 
 
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
 
for(var a=0;a<cellsY;a++) { 
 
    var startX = 0; 
 
    for(var b=0; b<cellsX;b++) { 
 

 
     startX = cellWidth * b; 
 

 
     if (currentGrid[a][b] == 1){ 
 

 

 
      ctx.fillRect(startX,(a*cellWidth) ,cellWidth,cellWidth); 
 
     } 
 
     ctx.strokeRect(startX,(a*cellWidth) ,cellWidth,cellWidth); 
 

 
    } 
 
} 
 
} 
 

 
function step(){ 
 
    move(); 
 
    Draw(); 
 

 
}
<canvas id="gameGrid"> 
 
</canvas>

+0

与你的问题并不真正相关,但是不是'neighbourCount'函数太复杂了吗?为什么不简单地添加邻居单元格的值? –

+0

根据你的建议,@JonathanM,我已经删除了我的答案并编辑了OP。 – Snowmonkey

+0

@JonathanM我不认为这是一个问题,因为'move'中的外部for循环显式地排除了“边缘”单元格(请参阅检查“a'和'b'必须都大于0并小于它们各自的界限减1)。 – Xirema

回答

1

这里的问题是lastGridcurrentGrid和都引用相同的阵列及其子阵列。当您编码如下:

var currentCells = [ 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,1,1,1,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
]; 
var currentGrid = currentCells; 
var lastGrid = currentCells; 

...你只创建一个阵列与名称引用它。因此,当您操作currentGrid时,您实际上也在操作lastGrid

而是做到这一点:

var currentCells = [ 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,1,1,1,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
[0,0,0,0,0,0,0,0], 
]; 
var currentGrid = currentCells.map(function(arr){return arr.slice()}); 
var lastGrid = currentCells.map(function(arr){return arr.slice()}); 

...这为move()你的最后一行:

lastGrid = currentGrid.map(function(arr){return arr.slice()}); 

...因为,如所描述here,该.slice()方法创建一个新的数组具有相同的值并返回对其的引用。 .map()方法遍历每个顶级数组项并执行请求的函数。

通常情况下,复制的一维数组,你可以使用.slice()这样:

newArray = oldArray.slice(); 

但这种方法不会在二维数组上工作,因为它只是给你一个新阵列中充满指向与oldArray中引用的子阵列相同的子阵列的指针。

因此,您必须逐个查看每个顶层数组,并且每个顶层数组都要经过.slice()其子数组。这是通过.map()方法完成的。

+0

作品享受!谢谢! – Plus1up