2017-04-21 64 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