In: Computer Science
c++
Programming Assignment 1: Game of Life
The objective of this programming assignment is to design and implement what is known as the “Game of Life”, conceptualized by the British mathematician John Horton Conway in 1970 to simulate the evolution patterns in a population of living organisms.
The game board is seeded with an initial population pattern, and then evolves based on the set of rules defining when a cell dies or is born into life. A cell’s life cycle depends on the state of its neighboring cells.
The game has no players - a user interacts with the “Game of Life” by creating an initial configuration and then observes how it unfolds. Some already known initial patterns have interesting predictable properties – you might discover a new one!
The implementation will only utilize the C++ programming concepts covered by pre-requisite courses. We will take an iterative approach; walk through the phases of specification, design and implementation.
Task #1 - Preparation
Please familiarize yourself with the topic by watching the following video:
https://www.youtube.com/watch?v=CgOcEZinQ2I (Links to an external site.)
Task #2 - Specification
We will discuss the game specification in class. What functionality (encapsulated in the member functions/methods) will be needed to accomplish the goal? Which of those methods will be publicly available (API) to invoke and operate the game, and which methods will be private to carry out the internal implementation details?
The specification will then be documented as part of the GameOfLife.h file – the comment section of the file, including the Pre-Conditions and Post-Conditions, followed by methods’ prototypes.
A skeleton .h file will be provided.
Task #3 - Object Oriented Design
Object Oriented design asks to model all significant entities in a problem domain as classes, with appropriate structural relationships between them. We would then have two classes - one corresponding to the game itself (example: GameOfLife_T), and another one corresponding to a cell (example: Cell_T). The GameOfLife class will contain a private structure(s) of Cell_T. The entities will each have a set of responsibilities, reflected in the corresponding member functions/methods.
The GameOfLife_T would have to be able to:
Seed/initialize the game board with
a predefined pattern (from a file)
a randomly generated pattern
Run the game
Execute the rules for every cell in order to generate the next generation of our cell population
Display the next generation matrix
Stop the game (ask a user up front how many generations to display, or ask a user whether to continue every step of the way)
The Cell_T would have to be able to:
Know, if it is alive or dead, and communicate so
Die
Come alive
Task #4 - Implementation
There are many ways to implement the generation of the “next step/generation” game board, and it will be up to a student to decide. We will discuss the options in class.
The display of the board will be character based, simply accomplished with console output.
--------------------
-----*--------------
----*-*-------------
--------*-----------
Please put your game in Namespace CS
Deliverables
A zip/archive file named <CS_PA1_LastName_FirstName.zip> containing:
h header file
cxx implementation file
cxx with main() to instantiate and run the game
txt – configuration file to seed the initial population pattern
The following information has been provided for the question above:
"Screen shot of C++ code" for your understanding.
Screen shot of C++ code:
Data in "seedPattern.txt" file:
1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1
1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 0 0 0 00 0 0 0 0 0 0 0 01 1 1 1 1
0 0 0 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 01 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 0 0 0 00 0 0 0 0 0 0 0 01 1 1 1 1
Output:
Text format code:
//GameOfLife_T.cpp
//Header file section
#include "GameOfLife.h"
#include <iostream>
using namespace gametest;
using namespace std;
//Program begins with a main function
int main()
{
//Declare variables
int numOfIterations;
int choice;
int rule;
unsigned int livingSeeds;
const int FILE = 1, RANDOM = 2, QUIT = 3;
//Create a GameOfLife class's object
GameOfLife gameBoard;
//Prompt and read the input from the user
do
{
cout << "1 for a predefined pattern (from a
file)" << endl;
cout << "2 for a randomly generated pattern"
<< endl;
cout << "3 to quit the game." <<
endl;
cout<<"Enter your choice (1/2/3): ";
cin >> choice;
if (choice != 3)
{
cout << "Enter number of Iterations:
";
cin >> numOfIterations;
cout << "Do you want to execute standard
rules(press 1), or"
" rule2 (press 2)?" << endl;
cin >> rule;
while (rule < 1 || rule > 2)
{
cout << "Invalid input. Please try
again:" << endl;
cin >> rule;
}
}
if (choice == 2)
{
cout << "Enter number of seeds: ";
cin >> livingSeeds;
}
while (choice<FILE || choice >QUIT)
{
cout << "please make a valid choice:
";
cin >> choice;
}
//Call the methods to appropriate input
switch (choice)
{
case FILE:
gameBoard.seedBoard("seedPattern.txt");
while (numOfIterations > 0)
{
gameBoard.run(rule);
cout << gameBoard;
--numOfIterations;
cout << "\n\n";
}
break;
case RANDOM: gameBoard.seedBoard(livingSeeds);
while (numOfIterations > 0)
{
gameBoard.run(rule);
cout << gameBoard;
--numOfIterations;
cout << "\n\n";
}
break;
}
} while (choice != 3);
//Pause the system for a while
system("pause");
}
//Cell_T.cpp
//Header file section
#include <string>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include "GameOfLife.h"
//use namespace gametest
namespace gametest
{
gametest::Cell::Cell()
{
state = 0;
}
gametest::Cell::Cell(bool state)
{
face = state;
}
gametest::Cell::~Cell()
{
}
bool Cell::getState() const
{
return state;
}
void Cell::setState(bool status)
{
state = status;
if (state == 0)
face = dead;
else
face = alive;
}
char Cell::getFace() const
{
return face;
}
GameOfLife::GameOfLife() throw (bad_alloc)
{
}
GameOfLife::GameOfLife(const GameOfLife& game)
{
GameOfLife newGame;
newGame.currLife = new CellPtr[30];
for (int i = 0; i < 30; ++i)
newGame.currLife[i] = new Cell[30];
for (int i = 0; i < 30; i++)
{
for (int j = 0; j < 30; j++)
{
newGame.currLife[i][j].setState(game.currLife[i][j].getState());
}
}
}
gametest::GameOfLife::~GameOfLife()
{
for (int i = 2; i < 28; i++)
{
delete[] nextLife[i];
}
for (int i = 2; i < 28; i++)
{
delete[] currLife[i];
}
}
void GameOfLife::seedBoard(string fileName) throw
(FileIOException)
{
int data;
ifstream file;
file.open(fileName);
currLife = new CellPtr[30];
for (int i = 0; i < 30; ++i)
currLife[i] = new Cell[30];
if (file.fail())
{
cout << "Sorry!!!! Unable to open the file"
<< std::endl;
return;
}
for (int i = 0; i < 30; i++)
{
for (int j = 0; j < 30; j++)
{
file >> data;
currLife[i][j].setState(data);
}
}
file.close();
}
void GameOfLife::seedBoard(size_t seeds)
{
srand(time(NULL));
currLife = new CellPtr[30];
for (int i = 0; i < 30; ++i)
currLife[i] = new Cell[30];
size_t count = 0;
while (count < seeds)
{
int randNumber1 = rand() % (26) + 2;
int randNumber2 = rand() % (26) + 2;
count++;
currLife[randNumber1][randNumber2].setState(true);
}
}
ostream& operator << (ostream& out, const
GameOfLife& board)
{
for (int i = 1; i < 28; i++)
{
if (i > 1)
cout <<endl;
for (int j = 1; j < 28; j++)
{
out <<
board.currLife[i][j].getFace();
}
}
return out;
}
void gametest::GameOfLife::run(int rule)
{
nextLife = new CellPtr[30];
for (int i = 0; i < 30; i++)
nextLife[i] = new Cell[30];
for (int i = 2; i < 28; i++)
{
for (int j = 2; j < 28; j++)
{
nextLife[i][j].setState(currLife[i][j].getState());
}
}
for (int i = 2; i < 28; i++)
{
for (int j = 2; j < 28; j++)
{
int lifeAlive = 0;
if (currLife[i][j].getState() ==
false)
{
if (currLife[i - 1][j - 1].getState()
== 1)
lifeAlive++;
if (currLife[i - 1][j].getState() ==
1)
lifeAlive++;
if (currLife[i - 1][j + 1].getState()
== 1)
lifeAlive++;
if (currLife[i][j - 1].getState() ==
1)
lifeAlive++;
if (currLife[i][j + 1].getState() ==
1)
lifeAlive++;
if (currLife[i + 1][j - 1].getState()
== 1)
lifeAlive++;
if (currLife[i + 1][j].getState() ==
1)
lifeAlive++;
if (currLife[i + 1][j + 1].getState()
== 1)
lifeAlive++;
}
if (currLife[i][j].getState() ==
true)
{
if (currLife[i - 1][j - 1].getState()
== 1)
lifeAlive++;
if (currLife[i - 1][j].getState() ==
1)
lifeAlive++;
if (currLife[i - 1][j + 1].getState()
== 1)
lifeAlive++;
if (currLife[i][j - 1].getState() ==
1)
lifeAlive++;
if (currLife[i][j + 1].getState() ==
1)
lifeAlive++;
if (currLife[i + 1][j - 1].getState()
== 1)
lifeAlive++;
if (currLife[i + 1][j].getState() ==
1)
lifeAlive++;
if (currLife[i + 1][j + 1].getState()
== 1)
lifeAlive++;
}
if (rule == 1)
{
if (currLife[i][j].getState() ==
false) {
if (lifeAlive == 3)
{
nextLife[i][j].setState(true);
}
else
nextLife[i][j].setState(false);
}
if (currLife[i][j].getState() ==
true) {
if (lifeAlive < 2 ||
lifeAlive >3)
nextLife[i][j].setState(false);
else
nextLife[i][j].setState(true);
}
}
if (rule == 2)
{
bool result = false;
result =
executeRuleB2_S(lifeAlive,
currLife[i][j].getState());
if (result == true)
nextLife[i][j].setState(true);
else
nextLife[i][j].setState(false);
}
}
}
for (int i = 2; i < 28; i++)
{
for (int j = 2; j < 28; j++)
{
currLife[i][j].setState(nextLife[i][j].getState());
}
}
cin.get();
}
istream& operator >> (istream& in, const
GameOfLife& board)
{
return in;
}
bool GameOfLife::executeRuleB2_S(unsigned int countAlive,
bool currentState)
{
if (currentState == false)
{
if (countAlive == 2)
{
return true;
}
}
if (currentState == true)
{
return false;
}
}
}
//GameOfLife.h
//Header file section
#include <iostream>
#include <string>
#include <cstdlib>
#include <iomanip>
using namespace std;
//Create a namespace
namespace gametest
{
bad_alloc;
//create a class name, Cell
class Cell
{
//Define member variables
public:
static const char alive = '*';
static const char dead = '-';
Cell();
Cell(bool cellState);
~Cell();
bool getState() const;
char getFace() const;
void setState(bool newState);
private:
bool state;
char face;
};
class FileIOException
{
};
//create a class name, GameOfLife
class GameOfLife
{
public:
static const unsigned int MAX = 30;
typedef Cell* CellPtr;
GameOfLife() throw (bad_alloc);
GameOfLife(const GameOfLife& game);
~GameOfLife();
void seedBoard(string fileName) throw
(FileIOException);
void seedBoard(size_t seeds);
void run(int);
friend ostream& operator << (ostream&
out, const
GameOfLife& board);
friend istream& operator >> (istream& in,
const GameOfLife& board);
private:
bool executeRule110(unsigned int countAlive, bool
currentState);
bool executeRuleB2_S(unsigned int countAlive, bool
currentState);
void calculateNextGen(CellPtr* current, CellPtr*
next);
CellPtr *currLife;
CellPtr *nextLife;
size_t boardSize;
CellPtr displayBoard;
};
}