Функция обновления в игре жизни Конвея не работает - PullRequest
0 голосов
/ 09 декабря 2018

Я пытаюсь сделать игру жизни Конвея на JavaScript, но не могу найти, что не так с определенной функцией после нескольких часов отладки.

Программа работает, создавая двумерный массив на основе глобальных переменных "row" и "column", а затем помещает объекты "Square" в каждое пространство в массиве.Затем программа устанавливает интервал для функции «рисования» для определенного интервала (глобальная переменная «скорость»).

Я извиняюсь, если это трудно понять, но в основном, каждый конкретный интервал времени, например, каждые 1000 миллисекунд, программа проверяет каждый объект "Квадрат" в массиве, обновляет количество соседей, которые у него есть, и затемрисует это на экране.

Вот где я застрял;Предполагается, что функция обновления проверяет все 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>
...