2017-04-21 10 views
1

Javascriptを使用してConwaysのゲームをHTMLキャンバス内に実装するのに少し時間を費やしました。Conwayのgame of lifeアルゴリズムのエラー(二次元配列をコピーする問題)

私の細胞は期待通りに働いていません。それは実際にそこにあるよりも多くの隣接する細胞を拾い上げると思われ、除去すべきではない細胞を除去する。どんな助けもありがとう!

//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

あなたの提案によると、@ジョナサンM、私は私の答えを削除し、OPを編集しました。 – Snowmonkey

+0

@JonathanM私は、 'move 'の外側のfor-loopが明示的に「エッジ」セルを除外しているために問題ではないと思います(' 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()メソッドは、各最上位の配列項目を移動し、要求された機能を実行します。

newArray = oldArray.slice(); 

をしかし、それはあなたに与えますので、この方法は、2次元配列では動作しません。

通常、1次元配列をコピーするために、あなただけのこのような方法で.slice()を使用することができますoldArrayで参照されているものと同じサブ配列へのポインタの新しい配列。

したがって、一度に1つずつ、サブ配列として.slice()を実行する必要があります。これは.map()メソッドによって実行されます。

+0

お手入れをしてください!ありがとうございました! – Plus1up

関連する問題