Heya everyone. I am a first-year student and doing a project for my C class. It is to do with John Conway's "Game of Life" as I am sure you are all aware of what that is. Here is the things needed. And after that is the code that I have. I have done everything up to printing the original config that the user gives. I would like a little help on how to reset the grid to show the next generation though. Thanks so much.

Write a C program that:

* Reads coordinates entered by the user until a -1 is entered. Be sure to check each pair for validity assuming all inputs are integers. If a user enters an invalid value, ask the user to enter both coordinates again. If an invalid value is read froma file, terminate the program with an error message.
* Asks the user how many generations to calculate.
* Prints the initial configuration using an "*" for occupied cells and a "-" for unoccupied cells.
* Calculate and print successive generations.
* Print the generation number above the grid, print the statistics stating how many cells were "born" and how many cells "died" during this generation, then print the grid.
* Make sure that your prompts and outputs use EXACTLY the same format as the example.

You are to write at least 4 functions (note that I didn't specify the parameters or return values of these functions):

* initconfig( ) which reads in the initial configuration
* generate( ) which creates and prints a new generation of organisms
* occ( ) which returns the number of occupied cells around cell[x,y]
* printgrid( ) which prints a grid

#include <stdio.h> 

#define SIZE 10 
#define SIZE2 15 

void initconfig(int [][SIZE2], int, int, int); 
void printgrid(int [][SIZE2], int, int ); 

int main () 
{ 

  int coordArray[SIZE][SIZE2] = {0}, x = 0, y = 0, 
      generations = 0; 
  
  initconfig(coordArray, x, y, generations); 

  printf("\n\n\nInitial State\n\n"); 
  printgrid(coordArray, SIZE, SIZE2); 

  return 0; 

} 

void initconfig(int coordArray[][SIZE2], int x, int y, int generations) 
{ 
   printf("\nEnter the number of generations: "); 
   scanf("%d", &generations); 

   printf("\nEnter coordinates: "); 
   scanf("%d%d", &x, &y); 

  while (x != -1){ 

    if(x<1 || x>10 || y<1 || y>15) 
      printf("\nInvalid input."); 
     else 
      coordArray[x-1][y-1] = 1; 
    
   printf("\nEnter coordinates: "); 
   scanf("%d%d", &x, &y); 
} 
} 

void printgrid(int coordArray[][SIZE2], int row, int col) 
{ 
  int i, j; 

  printf("\n"); 

  for(i=0; i <= row - 1; i++){ 
    for(j=0; j <= col - 1; j++){ 
      if(coordArray[i][j] == 1){ 
   printf("*");} 
   else 
     printf("-");} 

      printf("\n\n"); 
  } 
}

Recommended Answers

All 33 Replies

I would like a little help on how to reset the grid to show the next generation though.

Like this?

void resetgrid(int coordArray[][SIZE2], int row, int col) 
{
   int i, j; 
   for ( i = 0; i < row; i++ )
   {
      for ( j = 0; j < col; j++ )
      {
         coordArray[i][j] == 0;
      }
   }
}

Don't you need to implement a function occ to determine the number of occupied cells around cell[x,y] for the next generation, rather than resetting?

Don't you need to implement a function occ to determine the number of occupied cells around cell[x,y] for the next generation, rather than resetting?

Eep, yes that is what I meant to ask. Any help on that? Sorry for the confusion.

Something like this, I'd imagine.

int occ(int coordArray[][SIZE2], int row, int col, int r, int c)
{
   /*
    * +---------+-------+---------+
    * | r-1,c-1 | r-1,c | r-1,c+1 |
    * +---------+-------+---------+
    * |  r,c-1  | [r,c] |  r,c+1  |
    * +---------+-------+---------+
    * | r+1,c-1 | r+1,c | r+1,c+1 |
    * +---------+-------+---------+
    */
   int neighbors = 0;

   if ( r - 1 >= 0  && c - 1 >= 0  && coordArray[r - 1][c - 1] )
   {
      ++neighbors;
   }
   if ( r - 1 >= 0  && c     >= 0  && coordArray[r - 1][  c  ] )
   {
      ++neighbors;
   }
   if ( r - 1 >= 0  && c + 1 < col && coordArray[r - 1][c + 1] )
   {
      ++neighbors;
   }
   if ( r     >= 0  && c - 1 >= 0  && coordArray[  r  ][c - 1] )
   {
      ++neighbors;
   }
   if ( r     >= 0  && c + 1 < col && coordArray[  r  ][c + 1] )
   {
      ++neighbors;
   }
   if ( r + 1 < row && c - 1 >= 0  && coordArray[r + 1][c - 1] )
   {
      ++neighbors;
   }
   if ( r + 1 < row && c     >= 0  && coordArray[r + 1][  c  ] )
   {
      ++neighbors;
   }
   if ( r + 1 < row && c + 1 < col && coordArray[r + 1][c + 1] )
   {
      ++neighbors;
   }
   return neighbors;
}

Untried, untested, etc.

Or something similar to this.

int occ( int Grid[ ROW ][ COLUMN ], int x, int y )
{
	int neighbourCount = 0 ;
	for ( int i = max( 0, x - 1 ) ; i < min( COLUMN, x + 1 ); i++ )
	{
		for ( int j = max( 0, y - 1 ) ; j < min( ROW, y + 1 ); j++ )
		{
			if ( ( x == i ) & ( y == j ) )
			{
				continue;
			}
			if ( Grid[ i ][ j ] == 1 )
			{
				neighbourCount++ ;
			}
		}
	}
	return neighbourCount;
}

Check the conditions as your Rows and Columns start from 1 and the arrays begin from 0.

Ok, so by implementing that... I would take the "neighbor" variable and do what with it? That is the occ function and I know I somehow need to implement that to my "new generation" function. Do I take the neighbor variable and like put it into the generation function? And for the unoccupied coords, if the coords around it have 3 occupied, then it turns occupied.. Does that occ function take care of that as well? I'm sorry, I just can't seem to understand the occ function's purpose.

Ok, so by implementing that... I would take the "neighbor" variable and do what with it?

Use it later...

That is the occ function and I know I somehow need to implement that to my "new generation" function.

Now that you can get a count of the number of heighbors...

Do I take the neighbor variable and like put it into the generation function?

You take the return value to determine what to do with each cell in the generate function.

And for the unoccupied coords, if the coords around it have 3 occupied, then it turns occupied.. Does that occ function take care of that as well?

It counts the number of occupied neighbors. It takes care of nothing. It counts the neighbors.

I'm sorry, I just can't seem to understand the occ function's purpose.

Methinks the generate function that you'll need to write might make use of it, though.

Quoted from Wikipedia.

1. Any live cell with fewer than two neighbors dies of loneliness.
2. Any live cell with more than three neighbors dies of crowding.
3. Any dead cell with exactly three neighbors comes to life.
4. Any live cell with two or three neighbors lives, unchanged, to the next generation.

It is important to understand that all births and deaths occur simultaneously. Together they constitute a single generation or, we could call it, a "tick" in the complete "life history" of the initial configuration.

I'm sorry, I just can't seem to understand the occ function's purpose.

Inside the generate( ) function, use occ to calculate the number of neighbours for all the cells in the grid, and according to the rules determine if the cell is dead or alive.
Because all the births and deaths occur simultaneously, dont update the original cell. Make a temporary array of the same dimensions and update the cell corresponding to the one in the original array.

After you have finished doing that to all the cells in the original array, copy the temp array into the original one.

Ok, awesome. I am up to the generate function and have all that coded up. I am just wondering now, what happens if an inputted coord is on the border of the grid? When it goes to do (row - 1) and isn't in the array anymore, is there a way to put this into the occ function?

Look at my occ function. The max and min functions take care of that.

int occ( int Grid[ ROW ][ COLUMN ], int x, int y )
{
	int neighbourCount = 0 ;
	for ( int i = max( 0, x - 1 ) ; i < min( COLUMN - 1, x + 1 ); i++ )
	{
		for ( int j = max( 0, y - 1 ) ; j < min( ROW - 1, y + 1 ); j++ )
		{
			if ( ( x == i ) & ( y == j ) )
			{
				continue;
			}
			if ( Grid[ i ][ j ] == 1 )
			{
				neighbourCount++ ;
			}
		}
	}
	return neighbourCount;
}

In your for loop coding it gives me an error. Other than this error I think I am good to go! Thanks so much!

for ( int i = max( 0, x - 1 ) ; i < min( COLUMN - 1, x + 1 ); i++ )
	{
		for ( int j = max( 0, y - 1 ) ; j < min( ROW - 1, y + 1 ); j++ )
		{

project5.c:85: error: âforâ loop initial declaration used outside C99 mode
project5.c:87: error: âforâ loop initial declaration used outside C99 mode

you are using the C language. in C you cant declare the iterator i or j inside the for loop.

do this

int i, j;
for ( i = max( 0, x - 1 ) ; i < min( COLUMN - 1, x + 1 ); i++ )
{
	for ( j = max( 0, y - 1 ) ; j < min( ROW - 1, y + 1 ); j++ )
	{

Now this is given:

project5.c: In function âoccâ:
project5.c:85: error: redefinition of âiâ
project5.c:84: error: previous definition of âiâ was here
project5.c:85: error: âforâ loop initial declaration used outside C99 mode
project5.c:87: error: âforâ loop initial declaration used outside C99 mode

Looks like you have defined i more than once in the same scope( i.e. inside the same {} brackets. ). Check at the line numbers given. Usually compiler errors are easy to handle by the programmer as a good guess of the line numbers in error are also given. Rather than posting them here try to figure that out yourself.

I really do thank you Wolfpack for all the help you have given me. I am through all of the compiler errors and have one small problem left. No matter what I do I can't seem to get the second grid (i.e. the new generation) to print out any occupied cells. Am I definind the max and min wrong? Or is something wrong with one of my functions?

include <stdio.h>

#define SIZE 10
#define SIZE2 15
#define max(A,B) ( (A) > (B) ? (A):(B))
#define min(A,B) ( (A) < (B) ? (A):(B))

void initconfig(int [][SIZE2], int, int, int);
int occ(int [][SIZE2], int, int);
void generate(int [][SIZE2], int, int);
void printgrid(int [][SIZE2], int, int );

int main ()
{

  int coordArray[SIZE][SIZE2] = {0}, x = 0, y = 0,
      generations = 0;
  
  initconfig(coordArray, x, y, generations);

  printf("\n\n\nInitial State\n\n");
  printgrid(coordArray, SIZE, SIZE2); 

  generate(coordArray, SIZE, SIZE2);
  printgrid(coordArray, SIZE, SIZE2);

  return 0;

}

void initconfig(int coordArray[][SIZE2], int x, int y, int generations)
{
   printf("\nEnter the number of generations: ");
   scanf("%d", &generations);

   printf("\nEnter coordinates: ");
   scanf("%d%d", &x, &y);

  while (x != -1){

    if(x<1 || x>10 || y<1 || y>15)
      printf("\nInvalid input.");
     else
      coordArray[x-1][y-1] = 1;
   
   printf("\nEnter coordinates: ");
   scanf("%d%d", &x, &y);
}
}

void generate(int coordArray[][SIZE2], int row, int col)
{
  int tempArray[SIZE][SIZE2] = {0}, i=0, j=0;


  for(i=0; i < row; i++){
    for(j=0; j < col; j++){

      if(coordArray[i][j] == 1){
	if(occ(coordArray, i, j) == 2)
	  tempArray[i][j] = 1;      
	if(occ(coordArray, i, j) == 3)
	  tempArray[i][j] = 1;
	else
	  tempArray[i][j] = 0;}

      if(coordArray[i][j] == 0){
	if(occ(coordArray, i, j) == 3)
	  tempArray[i][j] = 1;
	else
	  tempArray[i][j] = 0;}
    }}

  for(i=0; i< row; i++){
    for(j=0; j < col; j++){
      coordArray[i][j] = tempArray[i][j];}}
}


int occ( int coordArray[][SIZE2], int x, int y )
{
  int neighbourCount = 0, i, j;
	for(i = max( 0, x - 1 ) ; i < min( SIZE2, x + 1 ); i++ )
	{
		for(j = max( 0, y - 1 ) ; j < min( SIZE, y + 1 ); j++ )
		{
			if ( ( x == i ) & ( y == j ) )
			{
				continue;
			}
			if ( coordArray[ i ][ j ] == 1 )
			{
				neighbourCount++ ;
			}
		}
	}
	return neighbourCount;
}

void printgrid(int coordArray[][SIZE2], int row, int col)
{
  int i, j;

  printf("\n");

  for(i=0; i < row; i++){
    for(j=0; j < col; j++){
      if(coordArray[i][j] == 1){
	printf("*");}
	else
	  printf("-");}

      printf("\n\n");
  }
}

Shouldn't it be...?

int occ( int coordArray[][SIZE2], int x, int y )
{
   int neighbourCount = 0, i, j;
   for ( i = max( 0, x - 1 ) ; i < min( SIZE - 1, x + 1 ); i++ )
   {
      for ( j = max( 0, y - 1 ) ; j < min( SIZE2 - 1, y + 1 ); j++ )
      {
         if ( ( x == i ) && ( y == j ) )

Hmm that still shows a blank grid. Could it be my max min #DEFINE functions?

Hmmm. Let me use my psychic powers to divine the input you are feeding your program:

10 7 8 8 8 8 9 8 7 9 8 -1 -1

Cool! That's the same data I'm using!

Initial State


---------------
---------------
---------------
---------------
---------------
---------------
-------*-------
------***------
-------*-------
---------------

---------------
---------------
---------------
---------------
---------------
---------------
---------------
---------------
--------*------
---------------

(Without the extra line between.)

Hmm. Well the occ function must not be calculating the neighbors how I need them to. Or the generate function isn't. From the initial state:

if it is occupied and has 2 or 3 occupied around it, then it says occupied, else dies.
if it is unoccupied and has 3 occupied around it, it becomes occupied, else stays dead.

Here I'd use some elementary debugging to determine what is going on.

void generate(int coordArray[][SIZE2], int row, int col)
{
   int tempArray[SIZE][SIZE2] = {0}, i=0, j=0;


   for ( i=0; i < row; i++ )
   {
      for ( j=0; j < col; j++ )
      {
         int count = occ(coordArray, i, j);
         if ( coordArray[i][j] == 1 )
         {
            if ( count == 2 || count == 3 )
            {
               tempArray[i][j] = 1;
               printf("case 1 : i = %d, j = %d\n", i, j);
            }
            else
            {
               tempArray[i][j] = 0;
               printf("case 2 : i = %d, j = %d\n", i, j);
            }
         }

         if ( coordArray[i][j] == 0 )
         {
            if ( occ(coordArray, i, j) == 3 )
            {
               tempArray[i][j] = 1;
               printf("case 3 : i = %d, j = %d\n", i, j);
            }
            else
            {
               tempArray[i][j] = 0;
            }
         }
      }
   }

   for ( i=0; i< row; i++ )
   {
      for ( j=0; j < col; j++ )
      {
         coordArray[i][j] = tempArray[i][j];
      }
   }
}
Initial State


---------------
---------------
---------------
---------------
---------------
---------------
-------*-------
------***------
-------*-------
---------------
case 2 : i = 6, j = 7
case 2 : i = 7, j = 6
case 1 : i = 7, j = 7
case 1 : i = 7, j = 8
case 1 : i = 8, j = 7
case 3 : i = 8, j = 8

---------------
---------------
---------------
---------------
---------------
---------------
---------------
-------**------
-------**------
---------------

[Aside: When you're new, it is most especially important to use the accepted style practices of good indentation and always using full bracing to help avoid bugs. You've got the indentation, which is good to see.]

Oops, I meant this.

void generate(int coordArray[][SIZE2], int row, int col)
{
   int tempArray[SIZE][SIZE2] = {0}, i=0, j=0;


   for ( i=0; i < row; i++ )
   {
      for ( j=0; j < col; j++ )
      {
         int count = occ(coordArray, i, j);
         if ( coordArray[i][j] == 1 )
         {
            if ( count == 2 || count == 3 )
            {
               tempArray[i][j] = 1;
               printf("case 1 : i = %d, j = %d\n", i, j);
            }
            else
            {
               tempArray[i][j] = 0;
               printf("case 2 : i = %d, j = %d\n", i, j);
            }
         }

         if ( coordArray[i][j] == 0 )
         {
            if ( count == 3 )
            {
               tempArray[i][j] = 1;
               printf("case 3 : i = %d, j = %d\n", i, j);
            }
            else
            {
               tempArray[i][j] = 0;
            }
         }
      }
   }

   for ( i=0; i< row; i++ )
   {
      for ( j=0; j < col; j++ )
      {
         coordArray[i][j] = tempArray[i][j];
      }
   }
}

Yea. For that new grid on that according to the criteria the new grid should have coords:

7 7
7 8
7 9
8 7
8 9
9 7
9 8
9 9

Those should all have stars. Maybe the problem is the occ function is not counting the function that are diagonal to the cell? Those have to be counted to.

Yes, something looks amiss. Adding more debugging seems to show that fewer than expected combinations are examined.

int occ( int coordArray[][SIZE2], int x, int y )
{
   int neighbourCount = 0, i, j;
   printf("x = %d, y = %d\n", x, y);
   for ( i = max( 0, x - 1 ) ; i < min( SIZE, x + 1 ); i++ )
   {
      for ( j = max( 0, y - 1 ) ; j < min( SIZE2, y + 1 ); j++ )
      {
         if ( ( x == i ) && ( y == j ) )
         {
            continue;
         }
         printf("occ: i = %d, j = %d\n", i, j);
         if ( coordArray[ i ][ j ] == 1 )
         {
            neighbourCount++ ;
         }
      }
   }
   puts("--");
   return neighbourCount;
}

Partial output:

x = 7, y = 5
occ: i = 6, j = 4
occ: i = 6, j = 5
occ: i = 7, j = 4
--
x = 7, y = 6
occ: i = 6, j = 5
occ: i = 6, j = 6
occ: i = 7, j = 5
--
case 2 : i = 7, j = 6
x = 7, y = 7
occ: i = 6, j = 6
occ: i = 6, j = 7
occ: i = 7, j = 6
--
case 1 : i = 7, j = 7
x = 7, y = 8
occ: i = 6, j = 7
occ: i = 6, j = 8
occ: i = 7, j = 7
--

M'kay.

int occ( int coordArray[][SIZE2], int x, int y )
{
   int neighbourCount = 0, i, j;
   for ( i = max( 0, x - 1 ) ; i <= min( SIZE - 1, x + 1 ); i++ )
   {
      for ( j = max( 0, y - 1 ) ; j <= min( SIZE2 - 1, y + 1 ); j++ )
      {
         if ( ( x == i ) && ( y == j ) )
         {
            continue;
         }
         if ( coordArray[ i ][ j ] == 1 )
         {
            neighbourCount++ ;
         }
      }
   }
   return neighbourCount;
}

Sorry for my complete noobishness at the occ function, but I was helped out on the occ function so I have no idea how to get it to read the diagonal coords. I wrote out some pseudocode on paper but it checks each and every possibility of combinations of coords, and I don't think that way is efficient or even possible at all. If I take out the max and min functions from occ, I would have to set up many, many different if statements that go through all the possibilities of different coords that could be on the border of the grid. /Sigh!! I am so lost on this part of the program it's not even cool...

Did you try the code I last posted?

Oooh. We are getting closer! You are the best! It is definitely counting the diagonal coords now, but it's not doing the cells that are already occupied right. Like the criteria that says:

if occupied, and 2 or 3 around it are occupied, stays occupied, else dies.

I don't think it's checking the ones that are occupied correctly.

Hm? I thought you had about what I've got. Let's resync.

#include <stdio.h>

#define SIZE 10
#define SIZE2 15
#define max(A,B) ( (A) > (B) ? (A):(B))
#define min(A,B) ( (A) < (B) ? (A):(B))

void initconfig(int [][SIZE2], int, int, int);
int occ(int [][SIZE2], int, int);
void generate(int [][SIZE2], int, int);
void printgrid(int [][SIZE2], int, int );

int main ()
{

  int coordArray[SIZE][SIZE2] = {0}, x = 0, y = 0,
      generations = 0;

  initconfig(coordArray, x, y, generations);

  printf("\n\n\nInitial State\n\n");
  printgrid(coordArray, SIZE, SIZE2);

  generate(coordArray, SIZE, SIZE2);
  printgrid(coordArray, SIZE, SIZE2);

  return 0;

}

void initconfig(int coordArray[][SIZE2], int x, int y, int generations)
{
   printf("\nEnter the number of generations: ");
   scanf("%d", &generations);

   printf("\nEnter coordinates: ");
   scanf("%d%d", &x, &y);

  while (x != -1){

    if(x<1 || x>10 || y<1 || y>15)
      printf("\nInvalid input.");
     else
      coordArray[x-1][y-1] = 1;

   printf("\nEnter coordinates: ");
   scanf("%d%d", &x, &y);
}
}

void generate(int coordArray[][SIZE2], int row, int col)
{
  int tempArray[SIZE][SIZE2] = {0}, i=0, j=0;


  for(i=0; i < row; i++){
    for(j=0; j < col; j++){

      if(coordArray[i][j] == 1){
	if(occ(coordArray, i, j) == 2)
	  tempArray[i][j] = 1;
	if(occ(coordArray, i, j) == 3)
	  tempArray[i][j] = 1;
	else
	  tempArray[i][j] = 0;}

      if(coordArray[i][j] == 0){
	if(occ(coordArray, i, j) == 3)
	  tempArray[i][j] = 1;
	else
	  tempArray[i][j] = 0;}
    }}

  for(i=0; i< row; i++){
    for(j=0; j < col; j++){
      coordArray[i][j] = tempArray[i][j];}}
}


int occ( int coordArray[][SIZE2], int x, int y )
{
  int neighbourCount = 0, i, j;
	for(i = max( 0, x - 1 ) ; i < min( SIZE2, x + 1 ); i++ )
	{
		for(j = max( 0, y - 1 ) ; j < min( SIZE, y + 1 ); j++ )
		{
			if ( ( x == i ) & ( y == j ) )
			{
				continue;
			}
			if ( coordArray[ i ][ j ] == 1 )
			{
				neighbourCount++ ;
			}
		}
	}
	return neighbourCount;
}

void printgrid(int coordArray[][SIZE2], int row, int col)
{
  int i, j;

  printf("\n");

  for(i=0; i < row; i++){
    for(j=0; j < col; j++){
      if(coordArray[i][j] == 1){
	printf("*");}
	else
	  printf("-");}

      printf("\n\n");
  }
}

/* my input
10 7 8 8 8 8 9 8 7 9 8 -1 -1
*/

/* my output
Initial State


---------------
---------------
---------------
---------------
---------------
---------------
-------*-------
------***------
-------*-------
---------------

---------------
---------------
---------------
---------------
---------------
---------------
------***------
------*-*------
------***------
---------------

*/

Isn't that what is expected? That's what it does here.

Hmm sorry for the long response time. I was trying the one you said and it does the same thing as mine. Have you input as:

4 8
4 10
5 8
5 10
6 8
6 9
6 10

And for that it does not print out the new ones that are already occupied.

For example, so you see what I see, put the above coords into the Game URL you posted on a 15x10 grid (the same as the one in the program, had to flip the dimensions). The game shows

**-**
-*-*-
--*--

But the program output for ours shows this:

**-**
------
--*--

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.