0

How do you check neighboring cells? These are the rules for the cells

  • If a live cell has less than two living neighbours, it perishes
  • If a live cell has two or three living neighbours it continues to live
  • If a live cell has more than three living neighbours, it perishes
  • If a dead cell has exactly three living neighbours, it comes into being

This is the code I have so far JS Bin

function shouldBeAlive(row, col) {
  if (model[i][j] === true) {
    // check if it should stay alive or whether it should die
  }
  else {
    // check whether it should stay dead or come alive
  }
}
  • Possible duplicate of [Optimizing Conway's 'Game of Life'](https://stackoverflow.com/questions/40485/optimizing-conways-game-of-life) – Estradiaz Mar 16 '19 at 21:56

2 Answers2

0

Conway's Game of Life, did it once, here's basically how I did it:

function shouldBeAlive(row, col) {
  var neighbors_alive = 0;
  // first, calculate number of alive neighbors
  // 1. check if there is a top neighbor
  if (row > 0) {
    neighbors_alive += model[row - 1][col];
  }
  // 2. check if there is a bottom neighbor
  if (row < model.length - 1) {
    neighbors_alive += model[row + 1][col];
  }
  // 3. check if there is a left neighbor
  if (col > 0) {
    neighbors_alive += model[row][col - 1];
  }
  // 4. check if there is a right neighbor
  if (col < model[row].length - 1) {
    neighbors_alive += model[row][col + 1];
  }
  // 5. check if there is a top-right neighbor
  if (row > 0 && col < model[row].length - 1) {
    neighbors_alive += model[row - 1][col + 1];
  }
  // 6. check if there is a top-left neighbor
  if (row > 0 && col > 0) {
    neighbors_alive += model[row - 1][col - 1];
  }
  // 7. check if there is a bottom-right neighbor
  if (row < model.length - 1 && col < model[row].length - 1) {
    neighbors_alive += model[row + 1][col + 1];
  }
  // 8. check if there is a bottom-left neighbor
  if (row < model.length - 1 && col > 0) {
    neighbors_alive += model[row + 1][col - 1];
  }
  
  if (model[row][col] === true) {
    // check if it should stay alive or whether it should die
    if (neighbors_alive < 2 || neighbors_alive > 3) {
      return false;
    }
    return true;
  }
  else {
    // check whether it should stay dead or come alive
    if (neighbors_alive === 2) {
      return true;
    }
    return false;
  }
}

A note: when adding a Boolean to an integer, it's value is converted automatically, true becomes 1, false becomes 0.

EDIT: Some edits to your code:

First, check the edit in the function above, then, here's how your evolve function should be:

function evolve() {
  for (var i = 0; i < model.length; i++) {
    for (var j = 0; j < model[i].length; j++) {
      model[i][j] = shouldBeAlive(i, j); // before, it was shouldBeAlive()
    }
  }
  paintGrid();
}
DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
  • When I run that code and add colored boxes and hit evolve it does not kill off cells or add cells. Is the boolean messing up my code or is there another issue? –  Mar 16 '19 at 22:10
  • @canijusttravel Check my edit, the first is that I'm returning values now from the `shouldBeAlive` from, the second is an error in your `evolve` function, it's working now. – DjaouadNM Mar 16 '19 at 22:20
  • @canijusttravel I've just discovered another mistake, check the edit, I've added consideration to the neighbors on the diagonals, which I forgot to consider before. – DjaouadNM Mar 17 '19 at 12:00
0

Let's get counting live neighbors into it's own function. In the one below, I loop a little differently so you don't have to include all those if statements. It gets any cell within one distance away in any direction, excluding the cell itself.

function getLiveNeighborCount (row, col) {

  let result = 0;

  let rLow = row == 0 ? 0 : row - 1;
  let rHigh = row == model.length -1 ? row : row + 1;

  for (let r = rLow; r <= rHigh; r++) {

    let cLow = col == 0 ? 0 : col - 1;
    let cHigh = col == model[r].length -1 ? col : col + 1;

    for (let c = cLow; c <= cHigh; c++)
      if (r != 0 || c != 0) 
        result += model[r][c];

  }

  return result;

}

Now shouldBeAlive() just cares about your rules:

function shouldBeAlive (row, col) {

  var alive = model[row][col];
  var lnc = getLiveNeighborCount(row, col);

  return ( 
      !alive && lnc != 3 ? false 
      : lnc == 2 || lnc == 3 ? true 
      : false
  );

}

By the way. You may want to prevent execution of shouldBeAlive before all "should" calculations occur. I say this because I don't imagine that a cell to the upper-left should get priority over one in the lower-right. They should all get their value simultaneously. So consider changing your evolve function to something like this:

function evolve() {

  let anticipated = [];

  for (let r = 0; r < model.length; r++) {

    anticipated[r] = [];

    for (let c = 0; c < model[r].length; c++) 
      anticipated[r][c] = shouldBeAlive(r,c);

  }

  model = anticipated;
  paintGrid();

}
pwilcox
  • 5,542
  • 1
  • 19
  • 31