# Conway's Game of Life in C++ with a Board Struct

I made the game of Life in C++ for a highschool class project. The website we're using doesn't have an autograder for C++, and my programming teacher doesn't really know how to program... so I'd love some external feedback! While I believe this simulation works, I'm not sure about the quality of the code. I tried making it as readable and fluid as possible, but I'm new to C++. Let me know how "C++" this code is, and about any pitfalls I may have dug myself into.

I'm unsure what version of C++ this website uses, but I believe its pre-C++11? (Due to a lack of smart pointers.)

I highly reccomend running it on the website here: https://codehs.com/sandbox/drakepickett/game-of-life

p.s. - I added console clearing and such just as a cheeky experiment to make it look nice. Not sure how safe console clearing with my method is :)

Thank you very much!

Here is the raw code:

#include "util.h"
#include <vector>
#include <chrono>

using namespace std;

struct Board
{
int BOARD_SIZE;
char liveCell;
vector<vector<char> > cells;

void populateBoard()
{
int numLive = readInt(1, BOARD_SIZE*BOARD_SIZE, "Please enter number of active cells between 1 and " + to_string(BOARD_SIZE*BOARD_SIZE)+ ": ");
for (int i = 0; i < numLive; i++)
{
int x, y;
while (true)
{
x = randInt(0, this->BOARD_SIZE-1);
y = randInt(0, this->BOARD_SIZE-1);
if (this->cells[x][y] == this->deadCell) break;
}

this->cells[x][y] = this->liveCell;
}
}

Board(int size, char liveCell, char deadCell)
{
this->BOARD_SIZE = size;
this->liveCell = liveCell;

for (int i = 0; i < this->BOARD_SIZE; i++)
{
vector<char> row;
for (int j = 0; j < this->BOARD_SIZE; j++)
{
}
this->cells.push_back(row);
}

populateBoard();
}

int getNumNeighbors(int row, int column)
{
int numNeighbors = 0;

vector<int> xRange;
vector<int> yRange;

if (row > 0) yRange.push_back(-1);
yRange.push_back(0);
if (row < this->cells.size()-1) yRange.push_back(1);

if (column > 0) xRange.push_back(-1);
xRange.push_back(0);
if (column < this->cells.size()-1) xRange.push_back(1);

for (int y : yRange)
{
for (int x : xRange)
{
if (x == 0 && y == 0) continue;
//cout <<"Y: " << row << " | Row: " << row+y << " _ X: " << column << " | Column: " << column + x << endl;
if (this->cells[row+y][column+x] == this->liveCell) numNeighbors++;
//cout << "We made it!" << endl;
}
}

return numNeighbors;
}

void update()
{
vector<vector<char> > b = this->cells;

for (int i = 0; i < this->BOARD_SIZE; i++)
{
for(int j = 0; j < this->BOARD_SIZE; j++)
{
int numNeighbors = getNumNeighbors(i, j);

if (this->cells[i][j] == this->liveCell && !(numNeighbors == 2 || numNeighbors == 3)) b[i][j] = this-> deadCell;
if (this->cells[i][j] == this->deadCell && numNeighbors == 3) b[i][j] = this->liveCell;

}
}

this->cells = b;
}

void print()
{
for (int i = 0; i < this->BOARD_SIZE; i++)
{
for (int j = 0; j < this->BOARD_SIZE; j++)
{
cout << this->cells[i][j] << " ";
}
cout << endl;
}
}
};

void cls()
{
using namespace std::chrono_literals;
std::cout << "\x1B[2J\x1B[H";
}

int main()
{
Board board(15, 'X', '-');
int numIterations = readInt(0, 1000, "Run how many iterations? (0-1000): ");
for (int i = 0; i < numIterations; i++)
{
cls();
cout << "Iteration " << i << endl;
board.print();
board.update();
}
cls();
cout <<"Final Board" << endl;
board.print();

return 0;
}

• A possible trick is to surround the map by extra cases. That might avoid bound checking. Jan 4 at 11:48