Search code examples
cconways-game-of-life

Counting number of neighbors Conway's Game of Life


I have an error somewhere in this code. The number of neighbors is not being counted correctly, as per my understanding. The neighbors function is probably where the issue is. My field variable is a 12x12 char array, the '#' is an alive cell and '-' is a dead one. I am relatively new to programming and would appreciate some help with this.

int neighbors(int l, int c)
{
  int num = 0;
  for (int i = -1; i < 2; i++)
  {
    for (int j = -1; j < 2; j++)
    {
      if ((l+i < 0 || l+i > 12) && (c+j < 0 || c+j > 12))
      {
        continue;
      }
      else if ((i != 0 || j != 0) && field[(l + i)][(c + j)] == '#')
      {
        num++;
      }
    }
  }
  return num;
}

//game logic
void logic()
{
  char temp[12][12];
  for (int i = 0; i < 12; i++)
  {
    for (int j = 0; j < 12; j++)
    {
      temp[i][j] = field[i][j];
    }
  }
  for (int i = 0; i < 12; i++)
  {
    for (int j = 0; j < 12; j++)
    {
      if (field[i][j] == '#')
      {
        if (neighbors(i, j) < 1 || neighbors(i, j) > 3)
        {
          temp[i][j] = '-';
        }
        else
        {
          temp[i][j] = '#';
        }
      }
      if (field[i][j] = '-')
      {
        if (neighbors(i, j) == 3)
        {
          temp[i][j] = '#';
        }
        else
        {
          temp[i][j] = '-';
        }
      }
      field[i][j] = temp[i][j];
    }
  }
}

Solution

  • If the array has dimensions 12x12, the maximum index value is 11, hence the test if ((l+i < 0 || l+i > 12) && (c+j < 0 || c+j > 12)) is incorrect. It should be:

    if (l+i < 0 || l+i >= 12 || c+j < 0 || c+j >= 12)
        continue;
    

    Another major problem is you update field[i][j] = temp[i][j]; inside the update loop: this corrupts the computation for the neighbors of the adjacent cells. You should first compute the whole temp array and update field in a subsequent loop, or with a single call to memcpy().

    Furthermore, the standard rules for Conway's Game of Life are somewhat different from your implementation: if (neighbors(i, j) < 1 || neighbors(i, j) > 3) keeps a cell with a single neighbour alive whereas under the standard rules it should die. Change this test to:

    if (neighbors(i, j) < 2 || neighbors(i, j) > 3)
        temp[i][j] = '-';
    

    Here is a simplified version:

    int neighbors(int l, int c) {
        int num = 0;
        for (int i = -1; i < 2; i++) {
            for (int j = -1; j < 2; j++) {
                if (l+i >= 0 && l+i < 12 && c+j >= 0 && c+j < 12
                &&  (i != 0 || j != 0) && field[l+i][c+j] == '#') {
                    num++;
                }
            }
        }
        return num;
    }
    
    //game logic
    void logic() {
        char temp[12][12];
        for (int i = 0; i < 12; i++) {
            for (int j = 0; j < 12; j++) {
                temp[i][j] = field[i][j];
            }
        }
        for (int i = 0; i < 12; i++) {
            for (int j = 0; j < 12; j++) {
                int nb = neighbors(i, j);
                if (nb < 2 || nb > 3) {
                    temp[i][j] = '-';
                } else
                if (nb == 3) {
                    temp[i][j] = '#';
                }
            }
        }
        for (int i = 0; i < 12; i++) {
            for (int j = 0; j < 12; j++) {
                field[i][j] = temp[i][j];
            }
        }
    }