2017-06-14 41 views
0

對於一個有趣的小項目,我決定在javascript中編寫康威的生活遊戲。我的邏輯似乎是有道理的,每個單獨的功能都能完成它的工作,但是我仍然沒有得到預期的結果。我有一個名爲grid的數組,它存儲所有單元格的值,以及它們是活的還是死的。我檢查每個單獨的細胞,然後檢查所有8個周圍的細胞來計數鄰居,對每個其他細胞重複。在某個時候,我的網格不再存儲正確的值並重置。在這一點上,我開始認爲這是一個JavaScript問題。生命陣列Javascript遊戲得到重置

<body> 
 
    <style> 
 
    * { 
 
     padding: 0; 
 
     margin: 0; 
 
    } 
 
    
 
    body { 
 
     overflow: hidden; 
 
    } 
 
    
 
    canvas { 
 
     background: #FFFFFF; 
 
     display: block; 
 
     margin: 0 auto; 
 
    } 
 
    </style> 
 
    <canvas id="canvas" style="border:1px solid #000000;"></canvas> 
 
</body> 
 
<script> 
 
    var canvas = document.getElementById("canvas"); 
 
    var ctx = canvas.getContext('2d'); 
 
    canvas.width = window.innerWidth; 
 
    canvas.height = window.innerHeight; 
 
    var Game = {}; 
 
    var nextGrid, emptyGrid, grid; 
 
    Game.horCells = 30; 
 
    Game.cellSize = canvas.width/Game.horCells; 
 
    Game.verCells = Math.floor(canvas.height/Game.cellSize); 
 
    Game.startLives = 80; 
 

 
    config(); 
 
    //setInterval(run, 1000); 
 

 
    function config() { 
 
    console.log("in config"); 
 
    emptyGrid = newGrid(Game.horCells, Game.verCells); 
 
    grid = emptyGrid; 
 
    nextGrid = emptyGrid; 
 
    //Manual Setup 
 
    for (var i = 0; i < Game.startLives; i++) { 
 
     //grid[getRandomInt(0, Game.horCells - 1)][getRandomInt(0, Game.verCells - 1)] = true; 
 
    } 
 
    grid[0][3] = true; 
 
    grid[1][3] = true; 
 
    grid[2][3] = true; 
 
    } 
 

 
    function run() { 
 
    console.log("gread" + grid[3][3]); 
 
    draw(); 
 
    update(); 
 
    } 
 

 

 
    function draw() { 
 
    console.log("Draw"); 
 
    ctx.fillStyle = "#FFFFFF"; 
 
    ctx.fillRect(0, 0, canvas.width, canvas.height); 
 
    for (var i = 0; i < Game.horCells; i++) { 
 
     for (var j = 0; j < Game.verCells; j++) { 
 
     if (grid[i][j] === false) { 
 
      ctx.fillStyle = "#FFFFFF"; 
 
     } else if (grid[i][j] === true) { 
 
      console.log("drawing live"); 
 
      ctx.fillStyle = "#000000"; 
 
     } 
 
     ctx.fillRect(i * Game.cellSize, j * Game.cellSize, Game.cellSize, Game.cellSize); 
 
     } 
 
    } 
 
    } 
 

 
    function update() { 
 
    for (var p = 0; p < Game.horCells; p++) { 
 
     for (var k = 0; k < Game.verCells; k++) { 
 
     nextGrid[p][k] = survival(p, k); 
 
     } 
 
    } 
 
    } 
 

 
    function survival(x, y) { 
 
    var neighbours = 0; 
 
    for (var l = 0; l < 3; l++) { 
 
     for (var m = 0; m < 3; m++) { 
 
     var sx = (x - 1) + l; 
 
     var sy = (y - 1) + m; 
 
     //Check bounds 
 
     if (inBounds(sx, sy) === true && grid[sx][sy]) { 
 
      neighbours++; 
 
     } 
 
     } 
 
    } 
 
    if (grid[x][y]) { 
 
     neighbours--; 
 
     if (neighbours === 2 || neighbours === 3) { 
 
     return true; 
 
     } else if (neighbours < 2 || neighbours > 3) { 
 
     console.log("DIED"); 
 
     return false; 
 
     } 
 
    } else if (grid[x][y] === false && neighbours === 3) { 
 
     return true; 
 
    } else { 
 
     console.log("DIED"); 
 
     return false; 
 
    } 
 
    } 
 

 
    function inBounds(x, y) { 
 
    return (x >= 0 && x < Game.horCells && y >= 0 && y < Game.horCells); 
 
    } 
 

 
    function newGrid(xCells, yCells) { 
 
    var gridd = new Array(xCells); 
 
    for (var i = 0; i < xCells; i++) { 
 
     gridd[i] = new Array(yCells); 
 
    } 
 

 
    for (var j = 0; j < xCells; j++) { 
 
     for (var k = 0; k < yCells; k++) { 
 
     gridd[j][k] = false; 
 
     } 
 
    } 
 
    return gridd; 
 
    } 
 

 

 
    function getRandomInt(min, max) { 
 
    return Math.floor(Math.random() * (max - min + 1)) + min; 
 
    } 
 
</script>

+1

你能詳細說明你的意思嗎?「在某些時候,我的網格不再存儲正確的值並重置」? JavaScript陣列不會停止工作。如果是這樣的話,網絡將會遭到可怕的破壞。 – Carcigenicate

+0

'emptyGrid = newGrid(Game.horCells,Game.verCells); grid = emptyGrid; nextGrid = emptyGrid;'看起來有點粗略。您將兩個引用分配給同一個可變網格。嘗試創建2個獨立的空網格。 – Carcigenicate

+0

另外,你永遠不會交換'newGrid'和'grid'。 – Carcigenicate

回答

0
emptyGrid = newGrid(Game.horCells, Game.verCells); 
grid = emptyGrid; 
nextGrid = emptyGrid 

創建網格,然後分配gridnextGrid同一對象。再次,gridnextGrid是相同的對象。您對1進行的任何更改都會發生在另一方。

創建2個獨立的電網,使他們能夠獨立地進行更改:

grid = newGrid(Game.horCells, Game.verCells); 
nextGrid = newGrid(Game.horCells, Game.verCells); 

或者小幅neaten起來:

var g =() => newGrid(Game.horCells, Game.verCells); 

grid = g(); 
nextGrid = g(); 

只是爲了澄清問題的評論:

var g =() => newGrid(Game.horCells, Game.verCells); 

Is(basi cally)相同的東西:

var g = function() { 
    return newGrid(Game.horCells, Game.verCells); 
} 

它被稱爲「胖箭頭」功能。

儘管兩者都做同樣的事情:它們創建一個返回新網格的函數。這具有無需編寫newGrid(Game.horCells, Game.verCells);兩次的好處。

我使用了箭頭函數而不是function關鍵字,因爲後者是巨大且醜陋的,這會消除清理代碼的目標。

+0

非常感謝!這一切現在都有道理。我認爲將一個值分配給另一個只會分配它的當前狀態。所以我可以參考emptyGrid,如果我需要得到一個乾淨的網格,而不必重新生成一個。 –

+0

@ArinYaldizciyan沒問題。和不;如果你想要這樣的行爲,你需要使用不可變的數據結構。查找Immutable.js庫或Clojurescript這樣的語言(編譯成JavaScript)。 – Carcigenicate

+0

另一個最後的問題!你的解決方案使用符號=>,這個符號的功能是什麼?再次感謝你:) –