//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
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.