Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

//main.cpp file #include<iostream> #include <cstdlib> #include <fstream> #includ

ID: 3834816 • Letter: #

Question

//main.cpp file

#include<iostream>

#include <cstdlib>

#include <fstream>

#include "GameOfLife2.h"

using namespace std;

int main()

{

string name;

int choice, iterations;

int seeds;

bool select = true;

  

//create an instance for the game of life class

csci2312::GameOfLife game;

  

//welcome user and display rules in a do-while loop

do {

cout << "Welcome" << endl;

cout << "This program is a C++ implementation of John Conway's Game of Life. Please enter your name: " << endl;

cin >> name;

cout << endl << "The rules of the "Game of Life" are as follows:" << endl

<< endl << "1. Any live cell with fewer than two live neighbors dies, as if caused by under-population."

<< endl << "2. Any live cell with two or three live neighbors lives on to the next generation."

<< endl << "3. Any live cell with more than three live neighbors dies, as if by overcrowding."

<< endl << "4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction." << endl

<< endl << "The initial configuration (Generation 0) of the board is determined randomly."

<< endl << "Every hundred Generations you will get the option to end or continue the simulation."

<< endl << "If a system becomes "stable" (meaning the system does not change from one"

<< endl << "generation to the next), the simulation will end automatically." << endl << endl;

cout << "Press 1 if you want to load the initial seed from a file or 2 if you want the program to generate it" << endl;

cin >> choice;

  

if (choice == 1) {

//load from file

cout << "How many times do you want the program to run?" << endl;

cin >> iterations;

game.seedBoard("initialPopulation.txt");

//game.alive();

game.run(iterations);

  

}

  

//generate random input

else if (choice == 2) {

cout << "Type the number of alive cells that you want to start with: " << endl;

cin >> seeds;

game.seedBoard(seeds);

cout << "How many times do you want the program to run?" << endl;

cin >> iterations;

game.run(iterations);

  

  

}

else if(choice == 3)

select = false;

  

}

while (choice != 3);

  

  

return 0;

}

// Points to remember:

//

// Cell's object state comprises of two data members: state and a matching face

//

// The game has an additional element 'displayBoard' which needs to be set to either

// currentLife or nextLife to avoid copying of elements from one board to the other

// The constructor should set 'display board' to currentLife board, to start with.

// Then, in each cycle the 'display board' needs to be pointed at the other board,

// which at that point will be hold 'next life'

//GameOfLife2.cpp file

#include "GameOfLife2.h"

//#include "ErrorContext.h"

//#include "GameOfLife2_Tests.h"

#include

using std::cout;

using std::endl;

namespace csci2312

{

  

Cell::Cell()

{

face = dead;// to do

};

  

Cell::Cell(bool initialState)

{

state = initialState;// to do

}

  

Cell::~Cell()

{

  

};

  

bool Cell::getState() const

{

return state; // to do

  

// mockup to comply with the return type

return true;

}

  

void Cell::setState(bool newState)

{

state = newState;// to do

}

  

char Cell::getFace() const

{

if(getState() == 1)// to do

return alive;

else

return dead;

  

// mockup to comply with the return type

return 0;

}

  

  

GameOfLife::GameOfLife(size_t myBoardSize) throw (std::bad_alloc)

{

  

boardSize = myBoardSize; // todo

string fileInput;

  

currentLife = new CellPtr[boardSize];

for(size_t i = 0; i < boardSize; i++)

{

currentLife[i] = new Cell[boardSize];

  

}

  

for(size_t row = 0; row < boardSize; row++)

{

for(size_t column = 0; column < boardSize; column++)

{

currentLife[row][column].setState(0);

}

}

  

// To test the exception, then remove:

  

// throw (std::bad_alloc());

//throw(std::bad_alloc());

  

  

}

  

GameOfLife::~GameOfLife()

{

  

// to do

for(size_t i = 0; i < boardSize; i++)

{

delete[] currentLife[i];

delete[] nextLife[i];

  

}

  

delete[]currentLife;

delete[]nextLife;

  

cout << "Object desctructed ";

};

  

  

  

size_t GameOfLife::getBoardSize() const

{

  

// to do

  

// mockup to comply with the return type

return 0;

  

}

  

void GameOfLife::seedBoard(string fileName)throw (FileIOException)

{

  

// to do

//Takes fileName and reads the data from the file

string dataFile = fileName;

std::ifstream readData(fileName);

  

GameOfLife* game = new GameOfLife(boardSize); //allocate memory for a new game board

  

if (readData.is_open()) //Error check file opening

{

while (!readData.eof()) //Continue reading until eof

{

readData >> *game; //read in file data to dereferenced GameOfLife object

  

//Uses file characters and sets currentLife board to 1 or 0 based on alive or dead characters

for (size_t i = 0; i < game->getBoardSize(); i++)

{

for (size_t j = 0; j < game->getBoardSize(); j++)

{

if (game->boardSize == 'o')

{

currentLife[i][j].setState(1);

}

else

{

currentLife[i][j].setState(0);

}

}

}

}

}

else //Unable to open the file

{

cout << "Error opening file. ";

std::cin.get();

}

  

readData.close(); //close the file

std::ifstream fileInput;

fileInput.open(fileName);

while(!fileInput.eof());

for (int i = 0; i

{

for(int j = 0; j

{

int temp;

fileInput>>temp;

if(temp == 1)

{

currentLife[i][j].setState(true);

}

if(temp == 0)

{

currentLife[i][j].setState(false);

}

cout << currentLife[i][j].getFace();

}

fileInput.close();

}

  

}

  

  

void GameOfLife::seedBoard(size_t seeds)

{

  

  

}

  

void GameOfLife::run()

{

// to do

}

  

bool GameOfLife::executeRules(unsigned int countAlive, bool currentState)

{

// to do

if (currentState == true && countAlive < 2)

{

return false;

}

else if (currentState == true && (countAlive == 2 || countAlive == 3))

{

return true;

}

else if (currentState == true && countAlive > 3)

{

return false;

}

else if (currentState == false && countAlive == 3)

{

return true;

}

else

{

return false;

}

  

  

}

  

  

void GameOfLife::calculateNextGen(CellPtr* current, CellPtr* next)

{

  

// to do

  

  

Cell temp;

  

for (size_t row = 1; row < boardSize - 1; row++)

{

for (size_t col = 1; col < boardSize - 1; col++)

{

int liveCount = 0;

if (current[row - 1][col - 1].getFace() == temp.alive)

{

liveCount++;

}

if (current[row - 1][col].getFace() == temp.alive)

{

liveCount++;

}

if (current[row - 1][col + 1].getFace() == temp.alive)

{

liveCount++;

}

if (current[row][col - 1].getFace() == temp.alive)

{

liveCount++;

}

if (current[row][col + 1].getFace() == temp.alive)

{

liveCount++;

}

if (current[row + 1][col - 1].getFace() == temp.alive)

{

liveCount++;

}

if (current[row + 1][col + 1].getFace() == temp.alive)

{

liveCount++;

}

if (current[row + 1][col].getFace() == temp.alive)

{

liveCount++;

}

  

int num = liveCount;

  

bool nextState = executeRules(num, currentLife[row][col].getState());

next[row][col].setState(nextState);

}

}

  

}

  

void GameOfLife::run(unsigned int numberOfIterations)

{

  

for (int run = 0; run < numberOfIterations; run++)

{

   // alive();

cout << *this << endl;

}

  

}

  

  

  

  

// Display cell's face

ostream& operator << (ostream& out, const Cell& cell)

{

out << (cell.getState() ? cell.alive : cell.dead);

return out;

  

}

  

  

// Display game's board

ostream& operator << (ostream& out, const GameOfLife& board)

{

  

// Iterate over the 'display board' and display cells

  

//size_t row, col;

for ( size_t i = 0; i < board.boardSize; i++)

{

for (size_t j = 0; j < board.boardSize; j++)

{

out << board.currentLife[i][j].getFace(); //display boards current face at each position

}

out << std::endl;

}

out << std::endl;

  

  

  

  

return out;

}

}

//GameOfLife2.h file

#pragma once

#include <iostream> // Provides ostream

#include <string>// String operations

#include<cstdlib> // Randomizer

namespace csci2312

{

using std::string;

using std::ostream;

using std::istream;

  

// PA2: standard exception if memory allcation failed

using std::bad_alloc;

  

// Class Cell stays the same for PA1 and PA2

class Cell

{

  

public:

static const char alive ='o'; // alive image

static const char dead = '-'; // dead image

  

  

Cell();

Cell(bool cellState);

~Cell();

  

// Accessors have no intention to modify the object, so it is a good practice to make them 'const' functions

bool getState() const;

char getFace() const;

void getgame() const;

  

// Mutators

void setState(bool newState);

  

private:

bool state=false;

char face;

  

};

  

// PA2: File IO Error custom exception class

class FileIOException

{

// Nothing inside, just a class type to handle exception

};

  

// PA2: Class GameOfLife will have some new and some changed features

class GameOfLife

{

  

public:

// PA1: maximum display board size

// PA2: default display board size

static const unsigned int MAX_BOARD = 30;

  

// PA2: New type (pointer to Cell type) handy with dynamic arrays

typedef Cell* CellPtr;

  

// PA1: Default constructor construct a board with all dark cells of MAX_BOARD size

// GameOfLife();

  

// PA1: Constructs the board of the requested size

// GameOfLife(size_t boardSize);

  

// PA2: Constructs the board of the requested size, can throw exception.

// If parameter is omitted, it becomes the default constructor, and the board will have MAX_BOARD size

GameOfLife(size_t boardSize = MAX_BOARD) throw (bad_alloc);

  

// PA2: Copy-constructor creates a new instance as a deep copy of the referenced object

GameOfLife(const GameOfLife& game);

  

// PA2: destructor must release memory taken by dynamic arrays

~GameOfLife();

  

// Returns board size

size_t getBoardSize() const;

  

// PA1: seeds the board from a file

// int seedBoard(string fileName);

  

// PA2: seeds the board from a file and throws an exception if there was trouble with file

void seedBoard(string fileName) throw (FileIOException);

  

// PA1 and PA2: seeds the board with a given number of seeds at randomized locations

void seedBoard(size_t seeds);

  

// Executes Conway set of rules. Returns next state

// Needed for TASK #4 to develop a test harness (the files test harness will be provided separately)

bool executeRules(unsigned int countAlive, bool currentState);

  

// PA1 and PA2:

void run();

void run(unsigned int numberOfIterations);

bool fileInput();

  

// Just an example of an possible accessor which reaches to a private array. Not needed to satisfy PAs

// A const(!) accessor method that returns a handle to the private currentLife array.

// The return type must also be 'const' because we return a pointer to a static array, and these are fixed

// It is just an example. It is not needed if we have a friend operator.

// PA1: const Cell(*getCurrentLife() const )[MAX_BOARD+2] { return currentLife; };

// PA2: const CellPtr* getCurrentLIfe() const { return currentLife; };

  

// PA1 and PA2: overloaded output operator to displsy the board

// friend operator can access private members of GameOfLife

friend ostream& operator << (ostream& out, const GameOfLife& board);

  

// PA2: overloaded input operator to input the board (from file of keyboard)

friend istream& operator >> (istream& in, GameOfLife& board);

  

private:

  

// PA2: Encapsulate next generation calculation in a method.

void calculateNextGen(CellPtr* current, CellPtr* next);

  

// PA1: static arrays of Cells. With "Halo" approach we need a bigger board

// Cell currentLife[MAX_BOARD + 2][MAX_BOARD + 2];

// Cell nextLife[MAX_BOARD + 2][MAX_BOARD + 2];

  

// PA2: dynamic arrays of Cells. New type CellPtr defined (typedef Cell* CellPtr)

// currentLife and and nextLife are handles to the dynamic arrays

CellPtr *currentLife;

CellPtr *nextLife;

  

// Just an example how to declare variable cl as a handle to our array of Cells. Not needed to satisfy PAs

// The accessor method getCurrentLife() above uses the same syntax for the return type

// PA1 with static arrays: const Cell(*cl)[MAX_BOARD + 2] = currentLife;

// PA2 with dynamic arrays: const CellPtr* cl = currentLife;

  

// PA1 and PA2, keeps track of the actual board size, set in the constructor

size_t boardSize;

  

// PA2: A handle to the array that needs to be displyed next.

CellPtr *displayBoard;

  

};

  

}

This program has three files main.cpp, GameOfLife2.cpp and GameOfLife2.h

I got linking error on this program, can someone help me to resolve the problem?

Thanks in advance!!!

Explanation / Answer

it sounds like files are not included properly.

make sure #include "GameOfLife2.h" in both GameOfLife2.cpp and main.cpp files.

and you should compile both GameOfLife2.cpp and main.cpp files.

ex : gcc GameOfLife2.cpp main.cpp

or

Create a project folder then proceed to place your header files and your .cpp files inside your project folder and copile both .cpp files