-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.cpp
295 lines (256 loc) · 10.4 KB
/
Main.cpp
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
WISH I FOUND THIS OUT SOONER:
In Conway's game of life, the entire matrix should be looped over only once: all changes are done simultaneously.
This, in effect, would cause the need for two matrices: the old state and the new one
- https://stackoverflow.com/questions/38660983/algorithms-extreme-specifics-about-conways-game-of-life
*/
#include <iostream>
#include <stdio.h>
#include <random>
#include <Windows.h>
#include <fstream>
const int boardX = 72;
const int boardY = 48;
const char aliveCell = '@';
const char deadCell = ' ';
char newBoard[boardY][boardX] = {
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
};
char oldBoard[boardY][boardX] = {};
void showCursor(bool flag) {
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(out, &cursorInfo);
cursorInfo.bVisible = flag;
SetConsoleCursorInfo(out, &cursorInfo);
}
void generateStartingCells(int CHANCE) {
int index = 0;
srand(CHANCE + time(0));
for (int y = 0; y < boardY; y++) {
for (int x = 0; x < boardX; x++) {
int randnum = rand() % CHANCE; // generates num between 0 and CHANCE
if (randnum == CHANCE -1) { // can be any num between 0 and chance
newBoard[y][x] = aliveCell;
}
}
}
}
/*
1 2 3 4 5
1
2 - - -
3 - + -
4 - - -
5
cell in question = 3,3
coords (X, Y switched up)
top left neighbour = x - 1 and y -1 (2,2)
top neighbour = x, y - 1 (2,3)
top right neighbour = x + 1, y - 1 (2,4)
left neighbour = x - 1, y ()
right neighbour = x + 1, y
bottom left neighbour = x - 1, y + 1
bottom neighbour = x, y + 1
bottom right neighbour = x + 1, y + 1
*/
int countNeighbours(int y, int x, char board[boardY][boardX]) {
int num = 0;
// EFFICIENT METHOD, NOT MINE
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
int row = (y + i + boardY) % boardY;
int col = (x + j + boardX) % boardX;
if (board[row][col] == aliveCell) {
num++;
} // this counts cell in question, so ... see if statement outside of for loop
}
}
if (board[y][x] == aliveCell && num > 0) {
num--;
}
// MY METHOD, LONG AND DRAWN OUT
/*
if (!(y == 0 && x == 0) && (y < (boardY-1) && x < (boardY-1))) { // centre of board
if (board[y - 1][x - 1] == aliveCell) { num++; }
if (board[y - 1][x] == aliveCell) { num++; }
if (board[y - 1][x + 1] == aliveCell) { num++; }
if (board[y][x - 1] == aliveCell) { num++; }
if (board[y][x + 1] == aliveCell) { num++; }
if (board[y + 1][x - 1] == aliveCell) { num++; }
if (board[y + 1][x] == aliveCell) { num++; }
if (board[y + 1][x + 1] == aliveCell) { num++; }
}
// BORDERS
else if (y == 0 || (x > 0 && x < boardX -1)) { // top border
if (board[y][x - 1] == aliveCell) { num++; }
if (board[y][x + 1] == aliveCell) { num++; }
if (board[y + 1][x - 1] == aliveCell) { num++; }
if (board[y + 1][x] == aliveCell) { num++; }
if (board[y + 1][x + 1] == aliveCell) { num++; }
}
else if (x == 0 || (y > 0 && y < boardY -1)) { // left border
if (board[y - 1][x] == aliveCell) { num++; }
if (board[y - 1][x + 1] == aliveCell) { num++; }
if (board[y][x + 1] == aliveCell) { num++; }
if (board[y + 1][x] == aliveCell) { num++; }
if (board[y + 1][x + 1] == aliveCell) { num++; }
}
else if (!(y < boardY-1) || x < boardX-1) { // bottom border
if (board[y - 1][x - 1] == aliveCell) { num++; }
if (board[y - 1][x] == aliveCell) { num++; }
if (board[y - 1][x + 1] == aliveCell) { num++; }
if (board[y][x - 1] == aliveCell) { num++; }
if (board[y][x + 1] == aliveCell) { num++; }
}
else if (!(x < boardX - 1) || y < boardY - 1) { // right border
if (board[y - 1][x - 1] == aliveCell) { num++; }
if (board[y - 1][x] == aliveCell) { num++; }
if (board[y][x - 1] == aliveCell) { num++; }
if (board[y + 1][x - 1] == aliveCell) { num++; }
if (board[y + 1][x] == aliveCell) { num++; }
}
// CORNERS
else if (y == 0 && x == 0) { // top left
if (board[y][x + 1] == aliveCell) { num++; }
if (board[y + 1][x] == aliveCell) { num++; }
if (board[y + 1][x + 1] == aliveCell) { num++; }
}
else if (!(x < boardX-1) && !(y < boardY-1)) { // bottom right
if (board[y - 1][x - 1] == aliveCell) { num++; }
if (board[y - 1][x] == aliveCell) { num++; }
if (board[y][x - 1] == aliveCell) { num++; }
}
else if (!(x < boardX - 1) && y == 0) { // top right
if (board[y][x - 1] == aliveCell) { num++; }
if (board[y + 1][x - 1] == aliveCell) { num++; }
if (board[y + 1][x] == aliveCell) { num++; }
}
else if (x == 0 && !(y < boardY - 1)) { // bottom left
if (board[y - 1][x] == aliveCell) { num++; }
if (board[y - 1][x + 1] == aliveCell) { num++; }
if (board[y][x + 1] == aliveCell) { num++; }
}
*/
return num;
}
void processAliveCell(int y, int x, char board[boardY][boardX])
{
int neighbours = countNeighbours(y, x, board);
if (neighbours <= 1 || neighbours >= 4) {
newBoard[y][x] = deadCell;
}
}
void processDeadCell(int y, int x, char board[boardY][boardX])
{
int neighbours = countNeighbours(y, x, board);
if (neighbours == 3) {
newBoard[y][x] = aliveCell;
}
}
void newGeneration(char board[boardY][boardX]) {
for (int y = 0; y < boardY; y++) {
for (int x = 0; x < boardX; x++) {
processAliveCell(y, x, board);
processDeadCell(y, x, board);
}
}
}
void printBoard() {
for (int y = 0; y < boardY; y++) {
for (int x = 0; x < boardX; x+=4) {
std::cout << newBoard[y][x] << " " << newBoard[y][x + 1] << " " << newBoard[y][x + 2] << " " << newBoard[y][x + 3] << " ";
//printf(newBoard[y][x] + " ");
}
std::cout << std::endl;
//printf("\n");
}
}
void updateOldBoard() {
for (int y = 0; y < boardY; y++) {
for (int x = 0; x < boardX; x++) {
oldBoard[y][x] = newBoard[y][x];
}
}
}
void updateGame(int generation) {
updateOldBoard();
showCursor(false);
system("cls");
std::cout << "Generation: " << generation << "\n";
double before = clock();
printBoard();
double after = clock();
double delta = after - before;
if (delta < 67) { // if it took less than 67ms to print the board...
Sleep(67 - delta); // then sleep the amount of time that it took to print the board from 67ms
}
newGeneration(oldBoard);
}
int main() {
std::cout << "\n----==== CONWAY'S GAME OF LIFE (ASCII VERSION) ====----\n\n\t\t- Concept And Design: John Conway (1937-2020)\n\n\t\t- This implementation in C++ was done by Ben Grant on the 27th of November 2021\n\t\t Ben Grant - https://bensgrant.github.io \n" << std::endl;
while (true) {
std::cout << "Enter the 1 in n chance for a cell to be generated in the first generation (enter anything that's not a number to exit): ";
int num;
std::cin >> num;
generateStartingCells(num);
showCursor(false);
int generation = 1;
std::cout << "Generation: " << generation << "\n";
printBoard();
Sleep(2000);
while (!GetAsyncKeyState(VK_ESCAPE)) {
updateGame(generation);
generation++;
}
}
return 0;
}