DapperDan
DapperDan

Reputation: 213

Learning C++: The game of Life

student Java developer here looking for some help getting off the ground in a new language with a C++ program.

The issue is that this code won't compile on gcc and I have zero idea why.

The intended behavior follows as a game with a set of rules:

The game is represented as a 2D array with randomly populated binary cells, each either alive or dead.

Each "round" of the game, cells live or die based on a rule subset.
a. If a cell has 4 or more live neighbors, it dies of overcrowding.
b. If a cell has 1 or fewer live neighbors, it dies of loneliness.
c. If a dead cell has exactly 3 neighbors, it springs to life as if colonized.

For the purposes of determining neighbors, each side of the board is considered adjacent to the opposing side. Thus the right side is adjacent to the left side, and vice versa. Likewise for the top and bottom, as well as corners.

For example: [0][0] has 8 neighbors, above it are [n-1][n-1], [n-1][0],[n-1][1], on the same line are [0][n-1], [0][1], and below it are [1][n-1],[1][0], and [1][1].

Run until there is no change in the board or the user specified maximum cycles have completed.

Probably the most confusing element of this is that I chose to represent this in the easiest way I found possible, by mirroring a N by N array into a N+2 by N+2 array, and filling the surrounding "shell" with "ghost values" representing the interior opposite neighbors.

Any help getting this off the ground floor would be greatly appreciated. Off to more reading I go.

#include "Life.h"
#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* rand */
#include <time.h>       /* time */
#include<iostream>
#include<fstream>
using namespace std;
/*
 * Main handles the first steps, collecting user input. It creates the initial board, then passes it for further manipulation.
 */
int main(){
    time_t start;
    time(&start);
    int rows;
    cout << "Please input the row number \n";
    cin >> rows;
    rows += 2;
    int maxCycles;
    cout << "Please input Maximum cycles \n";
    cin >> maxCycles;
    int** board = new int*[rows];
    for(int i = 0; i < rows; ++i){
        board[i] = new int[rows];
    }
    initBoard(board, rows);
    playGame(board, rows, maxCycles);
    time_t end;
    cout << "Runtime:" << end-start << "\n";

    return 0;
}

/*
 * Randomizes the chance of a cell to be alive in the initial cycle. After values are initialized, passes board to set ghost values, i.e., the surrounding opposite side neighbors.
 */
void initBoard(int** board, int rows){
    for(int i = 1; i < rows-1; ++i){
        for(int j = 1; j < rows-1; ++j){
            if(rand()%4 == 0){
                board[i][j] = 1;
            }else{
                board[i][j] = 0;
            }
        }
    }
    setGhosts(board, rows);
}

/*
 * Sets the ghost values framing the functioning game board
 */
void setGhosts(int** board, int rows){
    for(int i = 1; i < rows-1; ++i){
        board[0][i] = board[rows-2][i];
        board[rows-1][i] = board[1][i];
        board[i][0] = board[i][rows-2];
        board[i][rows-1] = board[i][1];
    }

    //Sets corner values
    board[0][0] = board[rows-2][rows-2];
    board[rows-1][rows-1] = board[1][1];
    board[0][rows-1] = board[rows-2][1];
    board[rows-1][0] = board[1][rows-2];
}

//Runs up to maxCycles cycles of the game, with each cycle altering the value of board.
void playGame(int** board, int rows, int maxCycles){
    int boolean = 1;
    for(int k = 0; k < maxCycles; ++k){
        //initialize temp array
        int** temp = new int*[rows];
        for(int i = 0; i < rows; ++i){
            temp[i] = new int[rows];
        }
        //Begin game
        for(int i = 1; i < rows-1;++i){
            for(int j = 1; j < rows; ++j){
                //check live neighbors
                int count = neighbors(board, i, j);
                if(board[i][j] == 1){//If alive, check if it stays alive
                    if(count < 4 || count > 1){
                        temp[i][j] = 1;
                    }else{
                        temp[i][j] = 0;
                        boolean = 0;
                    }
                }else if(board[i][j] == 0){//If dead, check if it stays dead
                    if(count == 3){
                        temp[i][j] = 1;
                        boolean = 0;
                    }else{
                        temp[i][j] = 0;
                    }
                }
            }
        }
        setGhosts(temp, rows);
        board = temp;
        if(boolean == 1) break;//If there is no change in the board across a cycle, the game is over
    }
    printBoard(board, rows);
}

//Returns the number of living neighbors to the given cell[i][j]
int neighbors(int** board, int i, int j){
    int count = 0;
    if(board[i-1][j-1] == 1){ ++count;}
    if(board[i-1][j] == 1){ ++count;}
    if(board[i-1][j+1] == 1){ ++count;}
    if(board[i][j-1] == 1){ ++count;}
    if(board[i][j+1] == 1){ ++count;}
    if(board[i+1][j-1] == 1){ ++count;}
    if(board[i+1][j] == 1){ ++count;}
    if(board[i+1][j+1] == 1){ ++count;}
    return count;
}

void printBoard(int** board, int rows){
    for(int i=1; i< rows-1; i++){
        for(int j=1; j< rows-1; j++){
            cout << board[i][j]  << "  ";
        }
        cout << endl;
    }
}

Upvotes: 0

Views: 187

Answers (1)

Justin Randall
Justin Randall

Reputation: 2278

Observed error output from g++

g++ -c -Wall -ansi -O3 -std=c++11 foo.cc
foo.cc: In function 'int main()':
foo.cc:51:26: error: 'initBoard' was not declared in this scope
     initBoard(board, rows);
                          ^
foo.cc:52:36: error: 'playGame' was not declared in this scope
     playGame(board, rows, maxCycles);
                                    ^
foo.cc: In function 'void initBoard(int**, int)':
foo.cc:72:26: error: 'setGhosts' was not declared in this scope
     setGhosts(board, rows);
                          ^
foo.cc: In function 'void playGame(int**, int, int)':
foo.cc:106:50: error: 'neighbors' was not declared in this scope
                 int count = neighbors(board, i, j);
                                                  ^
foo.cc:128:27: error: 'printBoard' was not declared in this scope
     printBoard(board, rows);
                           ^
make: *** [foo.o] Error 1

How to fix it

You have to forward declare all of your functions so that the compiler knows about them when they are invoked. You have an order dependency in the way these functions get called from within one another. Change the order of your functions to be something like this where int main() goes at the bottom of your file.

  1. void setGhosts(int** board, int rows)
  2. void initBoard(int** board, int rows)
  3. int neighbors(int** board, int i, int j)
  4. void printBoard(int** board, int rows)
  5. void playGame(int** board, int rows, int maxCycles)
  6. int main()

You also have a few unnecessary includes such as #include "Life.h" and #include <stdio.h>. The other C includes should be included using the C++ format i.e. instead of #include <stdlib.h> it should be #include <cstdlib> and instead of #include <math.h> it should be #include <cmath>.

Finally, you have a problem at the end of your int main() where end is used uninitialized. You will see it once you get all your other issues fixed.

Upvotes: 2

Related Questions