我试图在JavaScript中制作Conway的生命游戏,但在经过数小时的调试后无法找到特定功能的问题 .

该程序通过制作基于全局“行”和“列”变量的2d数组,然后将“Square”对象推送到数组中的每个空间来工作 . 然后,程序为特定间隔(全局变量“rate”)设置“绘制”功能的间隔 .

我很难道歉,如果这很难理解,但基本上,每个特定的时间间隔,比如每1000毫秒,程序检查数组中的每个“Square”对象,更新它拥有的邻居数量,然后在屏幕上绘制它 .

这就是我被困的地方;更新函数应该检查一个正方形具有的所有8个邻居,(如果它是边缘正方形则为3-5)但它只检查4个邻居 . 无论我做什么,如果我点击一个方块来填充它,只有现在填充的方块的顶部,左上角,右上角和左边邻居将注册他们的邻居已经填充 .

除了这个错误,代码工作正常,我99%肯定问题出在这一个函数中,因为代码目前仍将作为细胞自动机运行,而不是康威的生命游戏 .

var canvas = document.getElementById("life");
var ctx = canvas.getContext('2d');
var timer;
var rate = 1000;
var rows = 20;
var columns = 20;
var width = 20;
var clickX;
var clickY;
var board;
var running = false;
var checkArray = [
  [-1, 0, 1, 1, 1, 0, -1, -1],
  [-1, -1, -1, 0, 1, 1, 1, 0]
];
var visuals = true;
var gridColor = "#000000";
/*
live cell with < 2 neighbors = death
live cell with 2 or 3 neighbors = live for 1 generation
live cell with > 4 neighbors = death
dead cell with 3 neighbors = live for 1 generation
      
0 = death
1 = death
2 = continues life if alive
3 = continues life if alive OR brings to life if dead
4 = death
5 = death
6 = death
7 = death
8 = death
*/
window.onload = function() {
  makeBoard();
  var timer = setInterval(draw, rate);
  window.addEventListener("mousedown", clickHandler);
  // for(var i = 0; i < 8; i++){
  //     var checkIndexX = checkArray[0][i];
  //     var checkIndexY = checkArray[1][i];
  //   console.log(checkIndexX, checkIndexY);
  // }
}

function makeBoard() {
  board = new Array(columns);
  for (var i = 0; i < rows; i++) {
    var intRow = new Array(rows);
    for (var j = 0; j < columns; j++) {
      intRow[j] = new Square(false, j, i);
    }
    board[i] = intRow;
  }
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (var y = 0; y < rows; y++) {
    for (var x = 0; x < columns; x++) {
      if (running) {
        board[y][x].update();
      }
      board[y][x].draw();
      if (visuals) {
        board[y][x].visuals();
      }
    }
  }
  drawRunButton();
}

function Square(alive, PARX, PARY) {
  this.alive = false;
  this.X = PARX;
  this.Y = PARY;
  this.neighbors = 0;

  this.update = function() {
    this.neighbors = 0;
    for (var i = 0; i < 8; i++) {
      var checkIndexX = checkArray[0][i];
      var checkIndexY = checkArray[1][i];
      if ((this.X + checkIndexX) >= 0 && (this.X + checkIndexX) < columns &&
        (this.Y + checkIndexY) >= 0 && (this.Y + checkIndexY) < rows) {
        var check = board[this.Y + checkIndexY][this.X + checkIndexX];
        // console.log(this.X, this.Y, check.X, check.Y, checkIndexX, checkIndexY);
        if (check.alive) {
          this.neighbors++;
        }
      }
    }
    if (this.alive) {
      if (this.neighbors < 2 || this.neighbors > 3) {
        this.alive = false;
      }
    } else {
      if (this.neighbors == 3) {
        this.alive = true;
      }
    }
  };
  this.visuals = function() {
    drawVisuals(this.neighbors, this.X * width, this.Y * width);
  };
  this.draw = function(alive) {
    drawSquare(this.alive, this.X * width, this.Y * width, width);
  }
}

function clickHandler(e) {
  var clickX = e.screenX - 68;
  var clickY = e.screenY - 112;
  mapClick(clickX, clickY);
  manageRun(clickX, clickY);
}

function mapClick(x, y) {
  var indexX = Math.floor(x / width);
  var indexY = Math.floor(y / width);
  if (indexX >= 0 && indexX < columns && indexY >= 0 && indexY < rows) {
    board[indexY][indexX].alive = true;
  }
}

function manageRun(x, y) {
  if (x >= (columns * width) + 5 && x <= (columns * width) + 45 && y >= 5 && y <= 45) {
    if (running) {
      running = false;
    } else {
      running = true;
    }
    console.log(running);
  }
}

function drawRunButton() {
  drawSquare(false, (columns * width) + 5, 5, 40)
}

function drawSquare(fill, x, y, width) {
  ctx.beginPath();
  ctx.moveTo(x, y);
  ctx.lineTo(x + width, y);
  ctx.lineTo(x + width, y + width);
  ctx.lineTo(x, y + width);
  ctx.lineTo(x, y);
  if (fill) {
    ctx.fillStyle = gridColor;
    ctx.fill();
  } else {
    ctx.strokeStyle = gridColor;
    ctx.stroke();
  }
}

function drawVisuals(neighbors, x, y) {
  ctx.beginPath();
  ctx.fillStyle = "#ff0000";
  ctx.font = '20px serif';
  ctx.fillText(neighbors, x + (width / 3), y + (width / 1.25));
}
<!DOCTYPE html>
<html>

<head>
  <title>template.com</title>
  <link href="style.css" type="text/css" rel="stylesheet">
</head>

<body>
  <canvas id="life" width="1400" height="700" style="border: 1px solid black"></canvas>

</body>

</html>