-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathGame.cpp
More file actions
162 lines (147 loc) · 5.49 KB
/
Copy pathGame.cpp
File metadata and controls
162 lines (147 loc) · 5.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "Game.h"
using namespace std;
#include <vector>
#include "mainwindow.h"
#include <QDebug>
#include <random>
extern MainWindow * mainWin;
Game::Game()
{
//! it sets how many steps are saved (how many steps back you can go)
stepsBuffer = 100;
}
/*!
* Initialize an empty field with a certain amount of cells per line
*/
void Game::initializeEmptyGame(int cellsPerLine)
{
firstStep = vector<bool>(cellsPerLine*cellsPerLine, false);
gameSteps = {firstStep};
actualStep = 0;
bufferIndex = 0;
actualCellsPerLine = cellsPerLine;
}
/*!
* Turns a certain amount of cells alive (max int is 100)
*/
void Game::turnSomeRandomCellsAlive(int percentAliveCells){
int numAliveCells = actualCellsPerLine*actualCellsPerLine/100 * percentAliveCells;
fill_n(firstStep.begin(), numAliveCells, true);
// get a time-based seed
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// randomly shuffle the vector
shuffle(firstStep.begin(), firstStep.end(), std::default_random_engine(seed));
gameSteps = {firstStep};
}
/*!
* Moves the logic of the game one step further and then triggers the UI to update
*/
void Game::oneStepFurther()
{
//first calculates the new steps and adds it to the vector
gameSteps.push_back(calculateLogicOfLife(gameSteps[bufferIndex], actualCellsPerLine));
if(bufferIndex < stepsBuffer){
// if there is space in the buffer, then it just increases the index
bufferIndex++;
} else {
// otherwise it erases the oldest entry
gameSteps.erase(gameSteps.begin());
}
// it is nevertheless a further step in the development
actualStep++;
// update the UI
mainWin->updateUI();
}
/*!
* Moves the logic of the game one step back in time and then triggers the UI to update
*/
void Game::oneStepBack()
{
if(bufferIndex < 1) return;
bufferIndex--;
actualStep--;
gameSteps.pop_back();
mainWin->updateUI();
}
void Game::backToStartStep()
{
gameSteps = {firstStep};
bufferIndex = 0;
actualStep = 0;
mainWin->updateUI();
}
/*!
* Applies the algorithm of Game of Life and returns a vector with the next configuration
*/
vector<bool> Game::calculateLogicOfLife(vector<bool> & status, int cellsPerLine)
{
vector<bool> toReturn(cellsPerLine*cellsPerLine, false);
int len = cellsPerLine;
for(int i = 0; i < status.size() ; i++){
int sumOfNeigbors = 0;
// calculate number of alive neighbors
// check in which position in the array they are and calculate all neighbors
// corner cells have 3, other border cells 5 and centre cells 8 neighbors
if(i==0){
// topleft corner
sumOfNeigbors += status[1] + status[len] + status[len+1];
}else if (i == len -1){
// topright corner
sumOfNeigbors += status[i-1] + status[i+len-1] +status[i+len];
}else if(i == status.size() - len){
// bottomleft corner
sumOfNeigbors += status[i+1] + status[i-len] + status[i-len+1];
}else if(i == status.size() - 1){
//bottomright corner
sumOfNeigbors += status[i-1] + status[i-len] + status[i-len-1];
}else if(i < len){
// top row
sumOfNeigbors += status[i-1] + status[i+1] + status[i+len-1] + status[i+len] + status[i+len+1];
}else if(i>(status.size()-len)){
// bottom row
sumOfNeigbors += status[i-1] + status[i+1] + status[i-len-1] + status[i-len] + status[i-len+1];
}else if(i % len == 0){
// left column
sumOfNeigbors += status[i+1] + status[i+len] + status[i+len+1] + status[i-len] + status[i-len+1];
}else if ((i + 1) % len == 0){
// right column
sumOfNeigbors += status[i-1] + status[i+len] + status[i+len-1] + status[i-len] + status[i-len-1];
}else{
// in the middle
sumOfNeigbors += status[i-1] + status[i+len] + status[i+len-1] + status[i-len] + status[i-len-1] +
status[i+1] + status[i-len+1] + status[i+len+1];
}
// update the toRender vector depending on the number of neighbors of the cell
int currentState = status[i];
switch (currentState){
case 1:
switch (sumOfNeigbors)
{
case 2:
toReturn[i] = true;
break;
case 3:
toReturn[i] = true;
break;
default:
toReturn[i] = false;
break;
}
break;
case 0:
switch (sumOfNeigbors)
{
case 3:
toReturn[i] = true;
break;
default:
toReturn[i] = false;
break;
}
break;
default:
break;
}
}
return toReturn;
}