Skip to content

Instantly share code, notes, and snippets.

@PyBagheri
Last active May 21, 2021 06:57
Show Gist options
  • Save PyBagheri/858d1bc3a5e5a34001fe831b4fd694b9 to your computer and use it in GitHub Desktop.
Save PyBagheri/858d1bc3a5e5a34001fe831b4fd694b9 to your computer and use it in GitHub Desktop.
John Conway's Game of life simulation with C++
// 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