Hey everyone, I've got a problem with my program and don't really know how to fix it. The program is a simulation Game of Life and has these rules:

  1. A new cell is born on an empty square if is surrounded by exactly three neighboring cells
  2. A cell dies of overcrowding if it has four or more neighbors
  3. A cell dies of loneliness if it has zero or one neighbor
  4. Any live cell with two or three live neighbors lives, unchanged, to the next generation.

The program is run in a project so I have a driver, cpp and h file. So, I think the problem is with my "countNeighbors" function because every time I try to compile it I get a grid of 2's and 3's instead of a grid with 1's and 0's in it. This is what is in my cpp file:

#include <iostream>
#include <fstream>

#include "life.h"

using namespace std;



//global data structure
string *world; 

int numRows;
int numCols;

//reads a text file into an array of strings
//will allocate more memory as necessary
//assumes each line is same length

void populateWorld (string FILE_NAME){

    const int SIZE_INCREMENT = 3;
    char line[80];
    numRows = 0;
    numCols = 0;

    ifstream inFile;
    inFile.open(FILE_NAME.data());

    world = new string[SIZE_INCREMENT];

    while ( inFile.getline(line,80) ) {

          world [numRows] = line;
          numCols = world[numRows].length();

          numRows++;      


          if (numRows % SIZE_INCREMENT == 0) { //time to resize


             string *tempWorld = new string[numRows + SIZE_INCREMENT];

             for (int i = 0; i < numRows; i++) {
                 tempWorld[i] = world[i];
             }

             //free the world memory
             delete [] world;         

             world  = tempWorld;

          }


    }

}


//Prints out structure as if it were 2D array of characters

void showWorld() {

     //show the the grid or txt file
     for(int row=0; row < numRows; row++) {  
        for (int col=0; col < numCols; col++) {  
           cout << world[row][col];   
        }         

        cout << endl;                           
     }

     cout << endl;


}


// creates a duplicate of the space in the Life program

void iterateGeneration() {

    string *newworld = new string[numRows];    

     for(int row=0; row < numRows; row++) {  

         string temp = "";  //create a storage place for the next line       
         for (int col=0; col < numCols; col++) {

            temp += (char) (world[row][col] + 1);        
         }   

         newworld[row] = temp; 
    }

    delete [] world;

    world = newworld;

    return;


}
// counts number of neighbors in grid
int countNeighbors(bool ** newworld, int row, int col){
    int neighbors = 0;
    if ( newworld[row - 1][col - 1] == true )
neighbors++;
    if ( newworld[row - 1][col] == true )
neighbors++;
     if ( newworld[row - 1][col + 1] == true )
neighbors++;
     if ( newworld[row ][col - 1] == true )
neighbors++;
     if ( newworld[row ][col + 1] == true )
neighbors++;
     if ( newworld[row + 1][col - 1] == true )
neighbors++;
      if ( newworld[row + 1][col] == true )
neighbors++;
      if ( newworld[row + 1][col + 1] == true )
neighbors++;

return neighbors;

}

So, a couple things I forgot to mention: 1. I am only computing the first and second generations. In my driver file I declared it as: "const int NUM_GENERATIONS = 2." 2. I am reading the grid from a txt file declared as this: const string FILE_NAME = "starting_grid.txt." The txt file contains the following:

00000000100000001010
00000000010000001001
11100000010100000010
10100100101010101010
00101010010010101000

Can anyone help me?

Two obvious problems in countNeighbors:

  1. You are not bounds-checking (row or col plus or minus one may be out-of-bounds).
  2. You are testing against true when you've loaded your "array" with '0' and '1' (i.e., change true to '1')

Other than that you need to post all your code (can't be much more).

This is the driver file:

#include <iostream>
#include <fstream>

#include "life.h"

const string FILE_NAME = "starting_grid.txt";


using namespace std;

const int NUM_GENERATIONS = 2; //set to a smaller number for debugging

int main() {
    
    populateWorld(FILE_NAME);
        
    showWorld();  
  
    for (int iteration = 0; iteration < NUM_GENERATIONS; iteration++) {
   
        if (WINDOWS)
           system("cls"); //Windows only
        else
           system("clear"); //Linux only
    
        iterateGeneration();
    
        showWorld();
        
        //int countNeighbors(bool ** newworld, int row, int col);
        int countNeighbors(bool ** newworld,int row, int col);
    } 

    if (WINDOWS)
        system("PAUSE");
    
    return 0;
}

I changed my "cpp file" a bit to have the bounds checking in the "countNeighbors" function this is the contents:

#include <iostream>
#include <fstream>

#include "life.h"

using namespace std;



//global data structure
string *world; 

int numRows;
int numCols;

//reads a text file into an array of strings
//will allocate more memory as necessary
//assumes each line is same length

void populateWorld (string FILE_NAME){
    
    const int SIZE_INCREMENT = 3;
    char line[80];
    numRows = 0;
    numCols = 0;
    
    ifstream inFile;
    inFile.open(FILE_NAME.data());
        
    world = new string[SIZE_INCREMENT];
    
    while ( inFile.getline(line,80) ) {
         
          world [numRows] = line;
          numCols = world[numRows].length();
                  
          numRows++;      


          if (numRows % SIZE_INCREMENT == 0) { //time to resize
          
          
             string *tempWorld = new string[numRows + SIZE_INCREMENT];
             
             for (int i = 0; i < numRows; i++) {
                 tempWorld[i] = world[i];
             }
          
             //free the world memory
             delete [] world;         
             
             world  = tempWorld;
                        
          }
                     
       
    }
        
}


//Prints out structure as if it were 2D array of characters

void showWorld() {
   
     //show the the grid or txt file
     for(int row=0; row < numRows; row++) {  
        for (int col=0; col < numCols; col++) {  
           cout << world[row][col];   
        }         
        
        cout << endl;                           
     }
    
     cout << endl;
    
    
}


// creates a duplicate of the space in the Life program

void iterateGeneration() {
          
    string *newworld = new string[numRows];    

     for(int row=0; row < numRows; row++) {  
                
         string temp = "";  //create a storage place for the next line       
         for (int col=0; col < numCols; col++) {
                
            temp += (char) (world[row][col] + 1);        
         }   
            
         newworld[row] = temp; 
    }
  
    delete [] world;
    
    world = newworld;
        
    return;
    
     
}

int countNeighbors(bool ** newworld, int row, int col){
    int neighbors = 0;
    int Height =0;
    int Width =0;
    if (row<0 || row>=Height ) { return 0; }
        if (col<0 || col>=Width ) { return 0; }
        return (newworld[row][col] == 1) ? 1 : 0;
    if ( newworld[row - 1][col - 1] == true )
neighbors++;
    if ( newworld[row - 1][col] == true )
neighbors++;
     if ( newworld[row - 1][col + 1] == true )
neighbors++;
     if ( newworld[row ][col - 1] == true )
neighbors++;
     if ( newworld[row ][col + 1] == true )
neighbors++;
     if ( newworld[row + 1][col - 1] == true )
neighbors++;
      if ( newworld[row + 1][col] == true )
neighbors++;
      if ( newworld[row + 1][col + 1] == true )
neighbors++;

return neighbors;

}

So, how do I change true to equal 1, is it like this: " bool true = 1"?

> int countNeighbors(bool ** newworld,int row, int col);
Where's your declaration for this 'newworld' array?

IMO, you'd be better off with some more parameters to some of these functions. A scattering of global variables in several files is going to be harder to read.

Your bounds-checking will not work. It isn't a matter of whether row or col are already out-of-bounds, but that they may become so after you add or subtract one to/from them. You could make a function called checkForNeighbor with your bounds-checking code in it and use it like this in countNeighbors: if (checkForNeighbor(newworld, row - 1, col - 1)) n++; To check for '1' instead of true, simply replace everywhere it says true in countNeighbors with '1' (including the single quotes).

Presumably, iterateGeneration should be calling countNeighbors. And you should really clean up those globals. Also, since this is a C++ program, shouldn't you be using a class?

I can't use a class in this program because my teacher doesn't allow us to use them until the next program we write. Also, I heard that in c++ something called an ".at" function can be used to check the bounds in an array. Is there someway I can use this to do the bounds checking code or does it not apply here(I was just thinking this could be an easier way to bounds check)?

at() cannot be used with C-style arrays, but can be used with vector and string. You would want to change your data structure from string *world; to vector<string> world; . You could use a vector of vectors, instead.

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.