Search code examples
carraysif-statementconways-game-of-life

C: index formula for images (array), updating index in nested for loop


My function accepts an array (a glider or acorn) and depicts it accurately at time zero. However, my if/else if conditional statements counts the number of neighbors incorrectly or for some reason every index gets sent to the last else if (for indexes away from edges and corners). Hence the number of neighbors is incorrectly counted at time 0 for index (2,3) which springs to life at time 0 +1 when it should stay dead since it only has two neighbors.
Torus topology is used (wraps around top to bottom and right to left) and here are the actual requirements:

Please Google Conway's game of life for the rules.

/*step 1, check whether in array[index] is 0 or 255 (color) and alter auxiliary game[index] to 1 or 0 (dead or alive).  Do this since changes need to happen simultaneously, ie. we cannot incremently change array values without having an effect on later indexes.
step 2, check neighbors for each index of game[] and alter game[] to 1 or 0 depending on rules.  
step 3, based on game[], reset array[] to 255 or 0.*/

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "imgops.h"

/*typedef unsigned __int8 uint8_t; //for Visual Studio*/

void life(uint8_t array[],
    unsigned int cols,
    unsigned int rows)
{
    //must first scan array and set auxiliary array to alive or dead because changes happen simultaneously,
    //ie. if we change index values in array prior to scanning
    unsigned int i = 0, j = 0;

    int left, right, above, below, topleft, topright, botleft, botright;//life deleted
    uint8_t checkPixel;//state is for if alive/dead but now deleted

    uint8_t* game = malloc(cols*rows * sizeof(unsigned int));//allocate memory on heap for auxiliary array

                                                             //index for game array
    unsigned int index = 0;

    for (i = 0; i < cols; i++)//go through array to check 255 or 0 and set game[] to 1 or 0
    {
        for (j = 0; j < rows; j++)
        {
            index = i + (j*cols);
            if (get_pixel(array, cols, rows, i, j)>0)
                game[index] = 1;
            else
                game[index] = 0;
        }
    }


    //Check neighbors 

    for (i = 0; i < cols; i++)
    {
        for (j = 0; j < rows; j++)
        {
            index = i + (j*cols);
            //set values to 0 before checking the 8 neighbors, 1 for true 0 for false
            left = 0;
            right = 0;
            above = 0;
            below = 0;
            topleft = 0;
            topright = 0;
            botleft = 0;
            botright = 0;

            //check top row, bottom row, left column, right column

            //top row but not corners
            if ((i > 0) && (i < cols - 1) && (j == 0))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, i - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, i + 1, j);
                if (checkPixel > 0)//if checkPixel is not black so alive, either 0 or 255
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, rows - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, j + 1);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, i - 1, rows - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, i + 1, rows - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j + 1);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, i + 1, j + 1);
                if (checkPixel > 0)
                {
                    botright = 1;
                }
            }

            //bottom row but not corners
            else if ((i > 0) && (i < cols - 1) && (j == rows - 1))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, i - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, i + 1, j);
                if (checkPixel > 0)
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, j - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, 0);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, i + 1, j - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, i - 1, 0);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, i + 1, 0);
                if (checkPixel > 0)
                {
                    botright = 1;
                }

            }

            //checks left column except corner
            else if ((i == 0) && (j < (rows - 1)) && (j > 0))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, cols - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, i + 1, j);
                if (checkPixel > 0)
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, j - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, j + 1);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, cols - 1, j - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, i + 1, j - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, cols - 1, j + 1);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, i + 1, j + 1);
                if (checkPixel > 0)
                {
                    botright = 1;
                }

            }

            //right column except corners
            else if ((i == cols - 1) && (j < rows - 1) && (j > 0))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, i - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, 0, j);
                if (checkPixel > 0)
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, j - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, j + 1);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, 0, j - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j + 1);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, 0, j + 1);
                if (checkPixel > 0)
                {
                    botright = 1;
                }

            }

            //top left corner
            else if ((i == 0) && (j == 0))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, cols - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, i + 1, j);
                if (checkPixel > 0)//if checkPixel is not black so alive, either 0 or 255
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, rows - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, j + 1);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, cols - 1, rows - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, i + 1, rows - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, cols - 1, j + 1);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, i + 1, j + 1);
                if (checkPixel > 0)
                {
                    botright = 1;
                }
            }

            //bot left corner
            else if ((i == 0) && (j == rows - 1))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, cols - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, i + 1, j);
                if (checkPixel > 0)
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, j - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, 0);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, cols - 1, j - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, i + 1, j - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, cols - 1, 0);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, i + 1, 0);
                if (checkPixel > 0)
                {
                    botright = 1;
                }
            }

            //top right
            else if ((i == cols - 1) && (j == 0))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, i - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, 0, 0);
                if (checkPixel > 0)
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, rows - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, j + 1);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, i - 1, rows - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, 0, rows - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j + 1);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, 0, j + 1);
                if (checkPixel > 0)
                {
                    botright = 1;
                }
            }

            //bottom right
            else if ((i == cols - 1) && (j == rows - 1))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, i - 1, j);
                if (checkPixel > 0)
                {
                    left = 1;
                }

                //checks right
                checkPixel = get_pixel(array, cols, rows, 0, j);
                if (checkPixel > 0)
                {
                    right = 1;
                }

                //checks above
                checkPixel = get_pixel(array, cols, rows, i, j - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }

                //checks below
                checkPixel = get_pixel(array, cols, rows, i, 0);
                if (checkPixel > 0)
                {
                    below = 1;
                }

                //checks topleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }

                //checks topright
                checkPixel = get_pixel(array, cols, rows, 0, j - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }

                //checks botleft
                checkPixel = get_pixel(array, cols, rows, i - 1, 0);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }

                //checks botright
                checkPixel = get_pixel(array, cols, rows, 0, 0);
                if (checkPixel > 0)
                {
                    botright = 1;
                }
            }

            //the other indexes not in corners nor top or bottom rows or very right or left column
            else if ((j != 0) && (j != rows - 1) && (i != 0) && (i != cols - 1))
            {
                //checks left
                checkPixel = get_pixel(array, cols, rows, i - 1, j);
                //printf("%d\n",checkPixel);
                if (checkPixel > 0)
                {
                    left = 1;
                }
                //checks right
                checkPixel = get_pixel(array, cols, rows, i + 1, j);
                if (checkPixel > 0)
                {
                    right = 1;
                }
                //checks above
                checkPixel = get_pixel(array, cols, rows, i, j - 1);
                if (checkPixel > 0)
                {
                    above = 1;
                }
                //checks below
                checkPixel = get_pixel(array, cols, rows, i, j + 1);
                if (checkPixel > 0)
                {
                    below = 1;
                }
                //checks topleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j - 1);
                if (checkPixel > 0)
                {
                    topleft = 1;
                }
                //checks topright
                checkPixel = get_pixel(array, cols, rows, i + 1, j - 1);
                if (checkPixel > 0)
                {
                    topright = 1;
                }
                //checks botleft
                checkPixel = get_pixel(array, cols, rows, i - 1, j + 1);
                if (checkPixel > 0)
                {
                    botleft = 1;
                }
                //checks botright
                checkPixel = get_pixel(array, cols, rows, i + 1, j + 1);
                if (checkPixel > 0)
                {
                    botright = 1;
                }


            }

            //finished scanning neighbors, time to reset values of game[]
            if (game[index] == 0)//for dead cells
            {
                //exactly 3 neignbors revives a dead cell
                if (left + right + above + below + topleft + topright + botleft + botright != 3)
                    game[index] = 0;
                else
                    game[index] = 1;
            }
            else if (game[index] == 1)//for live cells
            {
                //check overcrowding and undercrowding
                if ((left + right + above + below + topleft + topright + botleft + botright == 3)
                    || (left + right + above + below + topleft + topright + botleft + botright == 2))
                {
                    game[index] = 1;
                }
                //if number of neighbors is not 2 or 3
                else
                {
                    game[index] = 0;
                }
            }

            //Reset left, right, above, below, topleft, topright, botleft, botright
            left = 0;
            right = 0;
            above = 0;
            below = 0;
            topleft = 0;
            topright = 0;
            botleft = 0;
            botright = 0;


        }
    }

    //finished setting the game[]
    //alter the main array to set colors according to state
    for (i = 0; i < cols; i++)
    {
        for (j = 0; j < rows; j++)
        {
            index = j + (i*(cols - 1));

            if (game[index] == 1)
            {
                set_pixel(array, cols, rows, i, j, 255);
            }
            else
            {
                set_pixel(array, cols, rows, i, j, 0);
            }
        }
    }

    //end of program
}

Solution

  • Changed the malloc to the appropriate type (not unit8_t), and used get_pixel rather than the formula index in the first part of filling the auxiliary array.

    Edited formula index=i + (j*cols) within every for loop and if statement to ensure consistency.

    Debugged with printf statements inserted after initializing the game[] based on values from array[].