234 lines
9.0 KiB
C++
234 lines
9.0 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Champlain College SDEV-240-81A
|
|
*
|
|
* C++ Final Project (first semester) - Coding Component (2020/05/02)
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* This is a demonstration in C++ of a game called
|
|
* Game of life created by John Horton Conway in 1970
|
|
* https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* Written by Llewellyn van der Merwe <llewellyn.vandermerw@mymail.champlain.edu>, April 2020
|
|
* Copyright (C) 2020. All Rights Reserved
|
|
* License GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "GameOfLife.h"
|
|
|
|
namespace GOL {
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* I am trying out namespace just to see how it works :) any input would be great!
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
// set the active coordinate
|
|
void GameOfLife::set(int x, int y) {
|
|
GameOfLife::activeState[x + GameOfLife::center][y + GameOfLife::center] = true;
|
|
}
|
|
|
|
// unset any coordinate
|
|
void GameOfLife::unset(int x, int y) {
|
|
GameOfLife::activeState[x + GameOfLife::center][y + GameOfLife::center] = false;
|
|
}
|
|
|
|
// reset the board
|
|
void GameOfLife::reset() {
|
|
for (int x = 0; x < GameOfLife::size; x++) {
|
|
for (int y = 0; y < GameOfLife::size; y++) {
|
|
GameOfLife::previousState[x][y] = false;
|
|
GameOfLife::activeState[x][y] = false;
|
|
}
|
|
}
|
|
// any moment reset is called we also re-start the game internally
|
|
this->start();
|
|
// do some house cleaning resets
|
|
this->setActiveInfinity(false);
|
|
this->setInfinityCounter(0);
|
|
this->setInfinity(false);
|
|
}
|
|
|
|
// print the board with active coordinates
|
|
void GameOfLife::print(int action) {
|
|
if (this->isActive()) {
|
|
// make sure we stay in same color
|
|
cout << this->getColor();
|
|
// stop game if all are dead
|
|
if (action == 1) {
|
|
this->stop();
|
|
}
|
|
// loop over the y axis
|
|
for (int y = GameOfLife::boardSize; y > 0; y--) {
|
|
// loop over the x axis
|
|
for (int x = 1; x < GameOfLife::boardSize; x++) {
|
|
if (x == 1) {
|
|
// add line numbers
|
|
if (action == 3) {
|
|
if (y < 10) {
|
|
cout << y << " ";
|
|
} else {
|
|
cout << y;
|
|
}
|
|
} else {
|
|
cout << " ";
|
|
}
|
|
}
|
|
// check if a cell is active/alive
|
|
if (GameOfLife::activeState[x + GameOfLife::center][y + GameOfLife::center]) {
|
|
cout << " O ";
|
|
// check if one cell in view is still active (and not still)
|
|
if (!GameOfLife::previousState[x + GameOfLife::center][y + GameOfLife::center] ||
|
|
this->isActiveInfinity()) {
|
|
// if this is infinity
|
|
if (this->isActiveInfinity()) {
|
|
this->decrementInfinity();
|
|
}
|
|
this->start();
|
|
}
|
|
} else {
|
|
cout << " . ";
|
|
}
|
|
// print end of line when at the end of line
|
|
if (x == GameOfLife::boardSize - 1) {
|
|
cout << endl;
|
|
}
|
|
}
|
|
}
|
|
// add bottom line of numbers if needed
|
|
if (action == 3) {
|
|
cout << " ";
|
|
for (int x = 1; x < GameOfLife::boardSize; x++) {
|
|
if (x < 10) {
|
|
cout << " " << x << " ";
|
|
} else {
|
|
cout << " " << x;
|
|
}
|
|
}
|
|
cout << endl;
|
|
}
|
|
// if this is infinity
|
|
if (action == 1 && this->isActiveInfinity() && this->getInfinityCounter() < 0) {
|
|
// when the preset infinity controller switches
|
|
// reach its conclusion stop the game
|
|
// so the player can choose another pattern
|
|
this->stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy the active state to the previous state array
|
|
void GameOfLife::copyState() {
|
|
// loop over the entire x axis of the board
|
|
for (int x = 0; x < GameOfLife::size; x++) {
|
|
// loop over the entire y axis of the board
|
|
for (int y = 0; y < GameOfLife::size; y++) {
|
|
// copy the value over to the previous state
|
|
GameOfLife::previousState[x][y] = GameOfLife::activeState[x][y];
|
|
}
|
|
}
|
|
}
|
|
|
|
// set the board active state
|
|
void GameOfLife::setState() {
|
|
// make sure we have the active state copied
|
|
this->copyState();
|
|
// check every cell on the board
|
|
// loop over the entire x axis of the board
|
|
for (int x = 1; x < GameOfLife::size; x++) {
|
|
// loop over the entire y axis of the board
|
|
for (int y = 1; y < GameOfLife::size; y++) {
|
|
int alive = 0;
|
|
// loop to check all eight neighbours
|
|
// . . .
|
|
// . 0 .
|
|
// . . .
|
|
// the dots are the neighbours
|
|
// zero is the active cell
|
|
for (int x2 = -1; x2 < 2; x2++) { // this loop increments the x axis lookup
|
|
for (int y2 = -1; y2 < 2; y2++) { // this loop increments the y axis lookup
|
|
// when x and y are 0 then
|
|
// do not check since it is
|
|
// the current active cell
|
|
if (!(x2 == 0 && y2 == 0)) {
|
|
// check if this neighbour was alive
|
|
if (GameOfLife::previousState[x + x2][y + y2]) {
|
|
// when alive we increment the alive value
|
|
// which we later will use to act upon
|
|
++alive;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// now let's act upon the alive status
|
|
if (alive < 2) {
|
|
// Any live cell with fewer than two live neighbours dies, as if caused by under-population.
|
|
// what ever that means...
|
|
GameOfLife::activeState[x][y] = false;
|
|
} else if (alive == 3) {
|
|
// Any live cell with three live neighbours lives on to the next generation.
|
|
// what ever that means...
|
|
GameOfLife::activeState[x][y] = true;
|
|
} else if (alive > 3) {
|
|
// Any live cell with more than three live neighbours dies, as if by over-population.
|
|
// Which is not true, I have eight children and a very bright future!!!
|
|
// We were made to be fruitful Genesis 1:28 (in real Life)
|
|
// but in this game...
|
|
GameOfLife::activeState[x][y] = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// get view board size
|
|
int GameOfLife::getViewSize() {
|
|
// return string
|
|
return GameOfLife::boardSize;
|
|
}
|
|
|
|
// get view board size
|
|
int GameOfLife::getViewArea() {
|
|
return GameOfLife::boardSize * GameOfLife::boardSize;
|
|
}
|
|
|
|
// get settable board area
|
|
int GameOfLife::getSettableArea() {
|
|
return GameOfLife::boardSize * 3;
|
|
}
|
|
|
|
// check if infinity is set
|
|
bool GameOfLife::isInfinitySet() const {
|
|
return GameOfLife::infinitySet;
|
|
}
|
|
|
|
// set infinity
|
|
void GameOfLife::setInfinity(bool infinitySet) {
|
|
GameOfLife::infinitySet = infinitySet;
|
|
}
|
|
|
|
// check if infinity is active
|
|
bool GameOfLife::isActiveInfinity() const {
|
|
return activeInfinity;
|
|
}
|
|
|
|
// set the infinity active state
|
|
void GameOfLife::setActiveInfinity(bool activeInfinity) {
|
|
GameOfLife::activeInfinity = activeInfinity;
|
|
}
|
|
|
|
// get the infinity counter value
|
|
long GameOfLife::getInfinityCounter() const {
|
|
return GameOfLife::infinityCounter;
|
|
}
|
|
|
|
// set the infinity counter value
|
|
void GameOfLife::setInfinityCounter(long infinity) {
|
|
GameOfLife::infinityCounter = infinity;
|
|
}
|
|
|
|
// decrement infinity counter value
|
|
void GameOfLife::decrementInfinity() {
|
|
GameOfLife::infinityCounter--;
|
|
}
|
|
} |