Last active
May 21, 2021 06:57
-
-
Save PyBagheri/858d1bc3a5e5a34001fe831b4fd694b9 to your computer and use it in GitHub Desktop.
John Conway's Game of life simulation with C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// By MohammadHossein Bagheri KheirAbadi (@PyBagheri) | |
// Initialize `board` variable with desired values and run. | |
#include <stdio.h> | |
#include <iostream> | |
#include <vector> | |
#include <chrono> | |
#include <thread> | |
using namespace std; | |
using namespace std::this_thread; | |
vector<vector<int>> getNeighbours(int dim_x, int dim_y, int x, int y) { | |
if (x > 0 and x < dim_x - 1) { | |
if (y == 0) { | |
vector<vector<int>> output = {{x + 1, y}, {x + 1, y + 1}, {x, y + 1}, {x - 1, y}, {x - 1, y + 1}}; | |
return output; | |
} else if (y == dim_y - 1) { | |
vector<vector<int>> output = {{x - 1, y}, {x - 1, y - 1}, {x, y - 1}, {x + 1, y}, {x + 1, y - 1}}; | |
return output; | |
} else { | |
vector<vector<int>> output = {{x - 1, y - 1}, {x - 1, y}, {x - 1, y + 1}, {x, y - 1}, {x, y + 1}, {x + 1, y - 1}, {x + 1, y}, {x + 1, y + 1}}; | |
return output; | |
} | |
} else if (x == 0) { | |
if (y == 0) { | |
vector<vector<int>> output = {{x + 1, y}, {x + 1, y + 1}, {x, y + 1}}; | |
return output; | |
} else if (y == dim_y - 1) { | |
vector<vector<int>> output = {{x + 1, y}, {x + 1, y - 1}, {x, y - 1}}; | |
return output; | |
} else { | |
vector<vector<int>> output = {{x + 1, y - 1}, {x + 1, y}, {x + 1, y + 1}, {x, y - 1}, {x, y + 1}}; | |
return output; | |
} | |
} else { | |
if (y == 0) { | |
vector<vector<int>> output = {{x - 1, y}, {x - 1, y + 1}, {x, y + 1}}; | |
return output; | |
} else if (y == dim_y - 1) { | |
vector<vector<int>> output = {{x - 1, y}, {x - 1, y - 1}, {x, y - 1}}; | |
return output; | |
} else { | |
vector<vector<int>> output = {{x - 1, y - 1}, {x - 1, y}, {x - 1, y + 1}, {x, y - 1}, {x, y + 1}}; | |
return output; | |
} | |
} | |
} | |
bool checkExpansionCase(vector<vector<int>> board) { | |
int dim_x = board.size(); | |
int dim_y = board[0].size(); | |
for (int j = 0; j < dim_y; j++) { | |
if (board[0][j] == 1) { | |
return true; | |
} | |
} | |
for (int j = 0; j < dim_y; j++) { | |
if (board[dim_x - 1][j] == 1) { | |
return true; | |
} | |
} | |
for (int i = 0; i < dim_x; i++) { | |
if (board[i][0] == 1) { | |
return true; | |
} | |
} | |
for (int i = 0; i < dim_x; i++) { | |
if (board[i][dim_y - 1] == 1) { | |
return true; | |
} | |
} | |
return false; | |
} | |
vector<vector<int>> getExpandedBoard(vector<vector<int>> board) { | |
int dim_x = board.size(); | |
int dim_y = board[0].size(); | |
for (int i = 0; i < dim_x; i++) { | |
board[i].insert(board[i].begin(), 0); | |
board[i].insert(board[i].end(), 0); | |
} | |
vector<int> toAppend; | |
toAppend.assign(dim_y + 2, 0); | |
board.insert(board.begin(), toAppend); | |
board.insert(board.end(), toAppend); | |
return board; | |
} | |
int getNextMove(vector<vector<int>> board, int x, int y) { | |
vector<vector<int>> neighbours; | |
int dim_x = board.size(); | |
int dim_y = board[0].size(); | |
neighbours = getNeighbours(dim_x, dim_y, x, y); | |
bool isPopulated = (board[x][y] == 1); | |
int neighboursCount = 0; | |
for (int i = 0; i < neighbours.size(); i++) { | |
if (board[neighbours[i][0]][neighbours[i][1]] == 1) { | |
neighboursCount += 1; | |
} | |
} | |
// 0: Remain/No Action | |
// 1: Die | |
// 2: Born | |
if (isPopulated) { | |
if (neighboursCount == 2 or neighboursCount == 3) { | |
return 0; | |
} else { | |
return 1; | |
} | |
} else { | |
if (neighboursCount == 3) { | |
return 2; | |
} else { | |
return 0; | |
} | |
} | |
} | |
string getBoardString(vector<vector<int>> board) { | |
int dim_x = board.size(); | |
int dim_y = board[0].size(); | |
string finalString; | |
for (int i = 0; i < dim_x; i++) { | |
for (int j = 0; j < dim_y; j++) { | |
if (board[i][j] == 0) { | |
finalString.append("⬜"); | |
} else { | |
finalString.append("⬛"); | |
} | |
} | |
finalString.append("\n"); | |
} | |
return finalString; | |
} | |
int main() { | |
int roundCount, delay; | |
cout << "How many rounds should execute? "; | |
cin >> roundCount; | |
cout << "\nHow much delay should occur (ms)? "; | |
cin >> delay; | |
vector<vector<int>> board = { | |
{1, 1, 1}, | |
{1, 0, 1}, | |
{1, 1, 1}, | |
{1, 1, 1}, | |
{1, 1, 1}, | |
{1, 1, 1}, | |
{1, 0, 1}, | |
{1, 1, 1} | |
}; | |
if (checkExpansionCase(board)) { | |
board = getExpandedBoard(board); | |
} | |
int dim_x = board.size(); | |
int dim_y = board[0].size(); | |
for (int t = 0; t < roundCount; t++) { | |
cout << "Round: "<< (t+1) << "\n" << getBoardString(board) << "\n\n"; | |
vector<int> actions; | |
for (int x = 0; x < dim_x; x++) { | |
for (int y = 0; y < dim_y; y++) { | |
actions.insert(actions.end(), getNextMove(board, x, y)); | |
} | |
} | |
for (int x = 0; x < dim_x; x++) { | |
for (int y = 0; y < dim_y; y++) { | |
if (actions[0] == 1) { | |
// Kill | |
board[x][y] = 0; | |
} else if (actions[0] == 2) { | |
// Born | |
board[x][y] = 1; | |
} | |
actions.erase(actions.begin()); | |
} | |
} | |
if (checkExpansionCase(board)) { | |
board = getExpandedBoard(board); | |
dim_x = board.size(); | |
dim_y = board[0].size(); | |
} | |
sleep_for(std::chrono::milliseconds(delay)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment