Search code examples
cif-statementswitch-statementconways-game-of-life

How to condense many if-statements into something smaller and more readable?


I am working on code for game of life. And one of the functions is supposed to "evolve" the current set of cells. This means that I have to have some conditions and if the if-statement meets the condition then the cell becomes a DEAD or a ALIVE cell.

However, there are only some next cells which are being initialized, so I would have to set the rest of the next cells to DEAD who are not affected by the conditions.

Since there are four conditions I would like to condense my if-statements to the smallest possible amount.

The conditions are:

  • A cell which has 0 or 1 living neighbours dies next generation.
  • A cell which has 2 or 3 living neighbours lives next generation.
  • A cell which has 4 or more living neighbours dies next generation.
  • An empty cell which has exactly 3 living neighbours becomes a live cell next generation.

I've tried fitting as many of the conditions into one if-statement and an else-statement at the if, meaning if non of the cells meet the conditions it will automatically be set to DEAD. Such that all cell in field[i][j].next are either dead or alive.

I would like to mention that the array field[i][j].current is already initialized with DEAD and ALIVE cells.

  void evolve(const int rows,const int cols,cell field[rows][cols], int 
    NeighbourCounter[i][j]){

       CellNeighbour(rows, cols,field,NeighbourCounter);

       for(int i = 0;i<rows;i++){
         for(int j =0;j<cols;j++){
           if(field[i][j].current == ALIVE  && NeighbourCounter[i][j] < 2){
              field[i][j].next == DEAD;
           }
           if(field[i][j].current == ALIVE && NeighbourCounter[i][j] == ||NeighbourCounter[i][j] == 2){
               field[i][j].next = ALIVE;
           } 
           if(field[i][j].current == ALIVE && NeighbourCounter[i][j] >= 4){
                field[i][j].next = DEAD;
           }
           if(field[i][j].current == DEAD && NeighbourCounter[i][j] == 3){
                field[i][j].next = ALIVE;
           }
         }
     else{
            field[i][j].next = DEAD;
     }
    }

NeighbourCounter is an array which calculates how many ALIVE neighbours each cell has.

The expected output should be that field[rows][cols] should be updated and the updated version is stored in ``field[rows][cols].next`.


Solution

  • It's probably easiest and clearest to simply switch on the value of the neighbour count, like this:

    for (int i = 0;  i < rows;  ++i) {
        for (int j = 0;  j < cols;  ++j) {
            switch (NeighbourCounter[i][j]) {
            case 0:
            case 1:
                /* cell dies without enough support */
                field[i][j].next = DEAD; /* I assume you meant =, not == */
                break;
            case 2:
                /* two neighbours can support a live cell */
                field[i][j].next = field[i][j].current;
                break;
            case 3:
                /* three neighbours can resurrect a dead one */
                field[i][j].next = ALIVE;
                break;
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
                /* more than three is a crowd */
                field[i][j].next = DEAD;
                break;
            default:
                fprintf(stderr, "Invalid value %d from NeighbourCounter\n",
                        NeighbourCounter[i][j]);
            }
        }
    }
    

    You'll see that case 2 is the only one in which the current value is needed; all the others depend only on the number of neighbours.