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<string> #include \

ID: 3847004 • Letter: #

Question

//main.cpp file

#include<iostream>

#include<cstdlib>

#include<string>

#include "GameOfLife2_Tests.h"

#include "ErrorContext.h"

//#include "GameOfLife2_csci2312.h"

using std::cout;

using std::endl;

using std::cin;

using namespace csci2312;

// ======================

// main function

// ======================

int main()

{

GameOfLife* myGame;

  

// Construct the game anticipating memory allocation issues

try {

  

myGame = new GameOfLife(20);

}

catch (std::bad_alloc) {

cout << "Failed to allocate memory for a new game" << endl;

  

system("pause");

return(1);

};

  

////////// STUDENT TASK - go on with your menus etc

  

///////// END TASK

  

delete myGame; // invokes GameOfLife destructor

  

return 0;

}

//GameOfLife2_Tests.h file

#pragma once

//#include "GameOFLife2_csci2312.h"

#include "ErrorContext.h"

using Testing::ErrorContext;

// - - - - - - - - - Tests: class Cell - - - - - - - - - -

// Smoke test

void test_cell_smoketest(ErrorContext &ec);

// Cell set/get test

void test_cell_setget(ErrorContext &ec);

// - - - - - - - - - Tests: class GameOfLife - - - - - - - - - -

// Smoke test

void test_game_smoketest(ErrorContext &ec);

// Rules test

void test_game_rules(ErrorContext &ec);

//GameOfLife_Tests.h cpp

#pragma once

#include<iostream>

#include<iomanip>

#include<cmath>

#include<cassert>

#include "ErrorContext.h"

#include "GameOfLife2_Tests.h"

using std::cout;

using std::endl;

using std::setprecision;

using Testing::ErrorContext;

using csci2312::GameOfLife;

#define DESC(x) desc(x, __LINE__) // ugly hack, but saves some time

///////// STUDENT TASK: Fill in implementatin for Cell tests

// Test Cell constructor and destructor

void test_cell_smoketest(ErrorContext &ec)

{

// to do

}

// Test Cell setters and getters

void test_cell_setget(ErrorContext &ec) {

// to do

}

///////// END TASK

// Test GameOfLife constructor and destructor

void test_game_smoketest(ErrorContext &ec) {

bool pass;

GameOfLife* myGame;

  

ec.DESC("--- Test - GameOfLife - Smoketest ---");

  

ec.DESC("Default Constructor");

pass = true;

// Construct a Default GameOfLife - boardSize should be set to MAX_BOARD

myGame = new GameOfLife;

pass = (myGame->getBoardSize() == myGame->MAX_BOARD);

ec.result(pass);

  

ec.DESC("Destruct Defualt Test Game");

// Cleans up after previous test, destruct the object

delete myGame;

  

ec.DESC("Custom Constructor requesting a specific boad size");

pass = true;

// Construct a Custom GameOfLife - boardSize should be set to what was requested

myGame = new GameOfLife(50);

pass = (myGame->getBoardSize() == 50);

ec.result(pass);

  

  

ec.DESC("Destruct Custom Test Game");

// Cleans up after previous test, destruct the object

delete myGame;

  

}

// Game rules test

void test_game_rules(ErrorContext &ec) {

bool pass;

GameOfLife *myGame;

  

// Run at least once!!

// assert(numRuns > 0);

  

ec.DESC("--- Test - Game Rule 110 ---");

  

pass = true;

// Construct a Default GameOfLife - boardSize should be set to MAX_BOARD

myGame = new GameOfLife;

  

ec.DESC("--------- Alive cell with 2 alive neighbors ---");

pass = (myGame->executeRules(2, true) == true);

ec.result(pass);

  

ec.DESC("--------- Dead cell with 2 alive neighbors ---");

pass = (myGame->executeRules(2, false) == false);

ec.result(pass);

  

///////// STUDENT TASK: add test for the remaining rule outcomes

  

  

///////// END TASK

  

// Destruct the object at the end of test

  

ec.DESC("Destruct Test Game");

// Cleans up after previous test, destruct the object

delete myGame;

  

}

//ErrorContext.h file

#pragma once

#include<iostream>

#include<set>

#include<sstream>

namespace Testing {

  

using std::set;

using std::ostream;

using std::string;

  

class ErrorContext // displays test results

{

public:

ErrorContext(ostream &os); // write header to stream

void desc(const char *msg, int line); // write line/description

void desc(string msg, int line);

  

void result(bool good); // write test result

~ErrorContext(); // write summary info

bool ok() const; // true iff all tests passed

  

private:

ostream &os; // output stream to use

int passed; // # of tests which passed

int total; // total # of tests

int lastline; // line # of most recent test

set badlines; // line #'s of failed tests

bool skip; // skip a line before title?

};

  

}

I got linking errors on this program files main.cpp file, GameOfLife2_Tests.h, GameOflife2_Tests.cpp and ErrorContext.h file can someone can help me please?

Explanation / Answer

//A very simple C++ implementation of John Conway's Game of Life.
//This implementation uses several nested for loops as well as two-dimensional
//arrays to create a grid for the cells in the simulation to interact.
//The array that is displayed to the user is 50 x 100, but actual size
//of the array is 52 x 102. The reason for this is to make the
//calculations easier for the cells on the outermost "frame" of the grid.

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

using namespace std;

//Copies one array to another.
void copy(int array1[52][102], int array2[52][102])
{
for(int j = 0; j < 52; j++)
{
       for(int i = 0; i < 102; i++)           
           array2[j][i] = array1[j][i];
   }
}

//The life function is the most important function in the program.
//It counts the number of cells surrounding the center cell, and
//determines whether it lives, dies, or stays the same.
void life(int array[52][102], char choice)
{
//Copies the main array to a temp array so changes can be entered into a grid
//without effecting the other cells and the calculations being performed on them.
int temp[52][102];
copy(array, temp);
   for(int j = 1; j < 51; j++)
    {
        for(int i = 1; i < 101; i++)           
       {  
           if(choice == 'm')
           {
//The Moore neighborhood checks all 8 cells surrounding the current cell in the array.
               int count = 0;
               count = array[j-1][i] +
                   array[j-1][i-1] +
                   array[j][i-1] +
                   array[j+1][i-1] +
                   array[j+1][i] +
                   array[j+1][i+1] +
                   array[j][i+1] +
                   array[j-1][i+1];
               //The cell dies.
if(count < 2 || count > 3)
                   temp[j][i] = 0;
               //The cell stays the same.
if(count == 2)
                   temp[j][i] = array[j][i];
               //The cell either stays alive, or is "born".
if(count == 3)
                   temp[j][i] = 1;
           }

           else if(choice == 'v')
           {
//The Von Neumann neighborhood checks only the 4 surrounding cells in the array,
//(N, S, E, and W).
               int count = 0;
               count = array[j-1][i] +
                   array[j][i-1] +
                   array[j+1][i] +
                   array[j][i+1];  
//The cell dies.
               if(count < 2 || count > 3)
                   temp[j][i] = 0;
               //The cell stays the same.
if(count == 2)
                   temp[j][i] = array[j][i];
               //The cell either stays alive, or is "born".
if(count == 3)
                   temp[j][i] = 1;
           }              
       }
    }
//Copies the completed temp array back to the main array.
copy(temp, array);
}

//Checks to see if two arrays are exactly the same.
//This is used to end the simulation early, if it
//becomes stable before the 100th generation. This
//occurs fairly often in the Von Neumann neighborhood,
//but almost never in the Moore neighborhood.
bool compare(int array1[52][102], int array2[52][102])
{
   int count = 0;
   for(int j = 0; j < 52; j++)
   {
       for(int i = 0; i < 102; i++)
       {
           if(array1[j][i]==array2[j][i])
               count++;  
       }
   }
//Since the count gets incremented every time the cells are exactly the same,
//an easy way to check if the two arrays are equal is to compare the count to
//the dimensions of the array multiplied together.
   if(count == 52*102)
   return true;
   else
   return false;
}

//This function prints the 50 x 100 part of the array, since that's the only
//portion of the array that we're really interested in. A live cell is marked
//by a '*', and a dead or vacant cell by a ' '.
void print(int array[52][102])
{
   for(int j = 1; j < 51; j++)
    {
        for(int i = 1; i < 101; i++)           
       {  
           if(array[j][i] == 1)
               cout << '*';
           else
               cout << ' ';
       }
       cout << endl;
    }
}

int main()
{
   int gen0[52][102];
   int todo[52][102];
   int backup[52][102];
   char neighborhood;
   char again;
char cont;
bool comparison;
   string decoration;

//Instructions on how the program is used, along with the rules of the game.
   cout << endl << "This program is a C++ implementation of John Conway's Game of Life."
   << endl << "With it, you can simulate how "cells" interact with each other." << endl
   << endl << "There are two types of neighborhoods you can choose, the"
   << endl << "Moore, and the Von Neumann. The Moore neighborhood checks"
<< endl << "all 8 surrounding cells, whereas the Von Neumann checks"
<< endl << "only the 4 cardinal directions: (N, S, E, and W)." << endl
<< 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;
//Loop to check if user wants to keep simulating.
do
   {  
//Loop to check for proper inputs.
do
       {
cout << "Which neighborhood would you like to use (m or v): ";
       cin >> neighborhood;
       }while(neighborhood != 'm' && neighborhood != 'v');
//Clears the screen so the program can start fresh.
system("clear");
int i = 0;
       //Loop that does the bulk of the simulation.
do
       {
//Generates the initial random state of the game board.
           srand(time(NULL));
//The actual array is 102 x 52, but it's easier to just leave the surrounding part of
//the array blank so it doesn't effect the calculations in the life function above.
           for(int j = 1; j < 51; j++)
           {
               for (int i = 1; i < 101; i++)
                   gen0[j][i] = rand() % 2;
           }
//Determines how big the decoration should be.
           if(i < 10)
               decoration = "#############";
           else if(i >= 10 && i < 100)
               decoration = "##############";
           else if(i >= 100 && i < 1000)
               decoration = "###############";
           else if(i >= 1000 && i < 10000)
               decoration = "################";
           else
               decoration = "#################";
//Prints the generation. If i == 0, the gen0 array is copied to the
//todo array, and is printed before any functions act upon it.
           cout << decoration << endl << "Generation " << i
           << ":" << endl << decoration << endl << endl;
//Initializes the arrays by copying the gen0 array to the todo array.
if(i == 0)
               copy(gen0, todo);
           copy(todo, backup);          
           print(todo);      
       life(todo, neighborhood);
       i++;
//Pauses the system for 1/10 of a second in order to give the screen
//time to refresh.
system("sleep .1");
//Checks whether the generation is a multiple of 100 to ask
//the user if they want to continue the simulation. If they
//wish to end, the program breaks out of the loop to ask if
//the user wishes to run another simulation.
if(i % 100 == 1 && i != 1)
{
cout << endl;
//Loop to check for proper inputs.
do
{
cout << "Would you like to continue this simulation? (y/n): ";
cin >> cont;
}while(cont != 'y' && cont != 'n');
if(cont == 'n')
break;
}
//Compares the current generation with a backup generation.
//If they aren't the same (they usually aren't) the system
//clears the screen and repeats the process until they are
//the same or the user chooses to quit.
comparison = compare(todo, backup);
if(comparison == false)
system("clear");
if(comparison == true)
cout << endl;
       }while(comparison == false);
//Loop to check for proper inputs.
do
{
cout << "Would you like to run another simulation? (y/n): ";
       cin >> again;
}while(again != 'y' && again != 'n');
   }while(again == 'y');
   return 0;
}