Игра из жизни ошибка - PullRequest
       49

Игра из жизни ошибка

2 голосов
/ 09 ноября 2019

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

Может быть, это визуальный сбой, но я тоже не уверен в этом, потому что код выглядит хорошо.

/// <reference path="../TSDef/p5.global-mode.d.ts" />

let gridSize = 10;
let arrCurrent = create2dArray(gridSize);
let arrNext = create2dArray(gridSize);

function setup() {
  createCanvas(800, 800, WEBGL);
  background(0);
  stroke(0, 255, 0);
  noFill();

  initGame();
}

function draw() {

  displayCells();
  calcNextGen();
}

//Returns a 2D Array 
function create2dArray(size) {
  let newArray = new Array(size);
  for (let i = 0; i < newArray.length; i++) {
    newArray[i] = new Array(1);
  }
  return newArray;
}

//Fills initial array with random values
function initGame() {
  for (let x = 0; x < arrCurrent.length; x++) {
    for (let y = 0; y < arrCurrent.length; y++) {
      arrCurrent[x][y] = Math.round((Math.random()));
    }
  }
}

//Calculates next generation
function calcNextGen() {

  for (let x = 0; x < gridSize; x++) {
    for (let y = 0; y < gridSize; y++) {
      let neighbors = countNeighbors1(arrCurrent, x, y);
      let state = arrCurrent[x][y];

      //If cell is dead and has exactly 3 neighbors, it starts living
      if (state === 0 && neighbors === 3) {
        arrNext[x][y] = 1;
      }
      //If cell lives and has too few or too many neighbors, it dies
      else if (state === 1 && (neighbors < 2 || neighbors > 3)) {
        arrNext[x][y] = 0;
      }
      else {
        arrNext[x][y] = state;
      }

    }
  }
  arrCurrent = arrNext.slice();
}

//Count neighbors
function countNeighbors(x, y) {
  return arrCurrent[(x + 1) % gridSize][y] +
    arrCurrent[x][(y + 1) % gridSize] +
    arrCurrent[(x + gridSize - 1) % gridSize][y] +
    arrCurrent[x][(y + gridSize - 1) % gridSize] +
    arrCurrent[(x + 1) % gridSize][(y + 1) % gridSize] +
    arrCurrent[(x + gridSize - 1) % gridSize][(y + 1) % gridSize] +
    arrCurrent[(x + gridSize - 1) % gridSize][(y + gridSize - 1) % gridSize] +
    arrCurrent[(x + 1) % gridSize][(y + gridSize - 1) % gridSize];
}


function countNeighbors1(grid, x, y) {
  let sum = 0;
  for (let i = -1; i < 2; i++) {
    for (let j = -1; j < 2; j++) {
      let col = (x + i + gridSize) % gridSize;
      let row = (y + j + gridSize) % gridSize;
      sum += grid[col][row];
    }
  }
  sum -= grid[x][y];
  return sum;
}

function displayCells() {
  background(0);

  translate(-300, -300, 0);
  for (let x = 0; x < arrCurrent.length; x++) {
    for (let y = 0; y < arrCurrent.length; y++) {
      push();
      translate(x * 50, y * 50, 0);
      if (arrCurrent[x][y] === 1) box(50);
      pop();
    }
  }
}

function logGrid() {
  console.log(arrCurrent[0]);
  console.log(arrCurrent[1]);
  console.log(arrCurrent[2]);
  console.log(arrCurrent[3]);
  console.log(arrCurrent[4]);
  console.log(arrCurrent[5]);
  console.log(arrCurrent[6]);
  console.log(arrCurrent[7]);
  console.log(arrCurrent[8]);
  console.log(arrCurrent[9]);
}

Я знаю, что я очень близок, но я бьюсь головой об этом уже 2 часа.

Вот маленький Веб-редактор P5JS , выМожно скопировать код и визуально увидеть проблему.

Любая помощь приветствуется - спасибо!

1 Ответ

3 голосов
/ 09 ноября 2019

arrCurrent = arrNext.slice(); не создает глубокую копию сетки, она просто создает поверхностную копию первого измерения. Создает сетку, где столбцы arrCurrent относятся к строкам arrNext.

Вы должны создать совершенно новую сетку:

arrCurrent = []
for (let x = 0; x < gridSize; x++)
    arrCurrent.push(arrNext[x].slice());

let gridSize = 10;
let arrCurrent = create2dArray(gridSize);
let arrNext = create2dArray(gridSize);

function setup() {
  createCanvas(800, 800, WEBGL);
  background(0);
  stroke(0, 255, 0);
  noFill();

  initGame();

  frameRate(10)
}

function draw() {

  displayCells();
  calcNextGen();
}

//Returns a 2D Array 
function create2dArray(size) {
  let newArray = new Array(size);
  for (let i = 0; i < newArray.length; i++) {
    newArray[i] = new Array(1);
  }
  return newArray;
}

//Fills initial array with random values
function initGame() {
  for (let x = 0; x < arrCurrent.length; x++) {
    for (let y = 0; y < arrCurrent.length; y++) {
      arrCurrent[x][y] = Math.round((Math.random()));
    }
  }
}

//Calculates next generation
// - A live cell dies if it has fewer than two live neighbors.
// - A live cell with two or three live neighbors lives on to the next generation.
// - A live cell with more than three live neighbors dies.
// - A dead cell will be brought back to live if it has exactly three live neighbors.
function calcNextGen() {

  for (let x = 0; x < gridSize; x++) {
    for (let y = 0; y < gridSize; y++) {
      let neighbors = countNeighbors1(arrCurrent, x, y);
      let state = arrCurrent[x][y];

      //If cell is dead and has exactly 3 neighbors, it starts living
      if (state === 0 && neighbors === 3) {
        arrNext[x][y] = 1;
      }
      //If cell lives and has too few or too many neighbors, it dies
      else if (state === 1 && (neighbors < 2 || neighbors > 3)) {
        arrNext[x][y] = 0;
      }
      else {
        arrNext[x][y] = state;
      }

    }
  }

  arrCurrent = []
  for (let x = 0; x < gridSize; x++)
      arrCurrent.push(arrNext[x].slice());
}

function countNeighbors1(grid, x, y) {
  let sum = 0;
  for (let i = -1; i < 2; i++) {
    for (let j = -1; j < 2; j++) {
      let col = (x + i + gridSize) % gridSize;
      let row = (y + j + gridSize) % gridSize;
      sum += grid[col][row];
    }
  }
  sum -= grid[x][y];
  return sum;
}

function displayCells() {
  background(0);

  translate(-75, -75, 0);
  stroke(128);
  box(50*gridSize, 50*gridSize, 50);

  translate(-225, -225, 0);
  stroke(0, 255, 0);
  
  for (let x = 0; x < arrCurrent.length; x++) {
    for (let y = 0; y < arrCurrent.length; y++) {
      push();
      translate(x * 50, y * 50, 0);
      if (arrCurrent[x][y] === 1) box(50);
      pop();
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
...