Conway's Game of Life
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
/** | |
Conway's Game of Life | |
Forked by Skully | |
Original Author: Huynh Quang Huy | |
TODO: Detect stale states. | |
TODO: Provide option to automatic generation stepper. | |
TODO: File output and input of patterns. | |
COMPILING WITH GCC: | |
> gcc -o gol gol.c | |
> gol [Height] [Width] | |
**/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <time.h> | |
#include <conio.h> | |
const int TRUE = 1; | |
const int FALSE = 0; | |
int WIDTH = 67; | |
int HEIGHT = 47; | |
void makeBoardLines(int board[HEIGHT][WIDTH]) | |
{ | |
int cols, rows; | |
for(cols = 0; cols < WIDTH; cols++) | |
{ | |
board[0][cols] = '_'; | |
board[HEIGHT - 1][cols] = '_'; | |
} | |
for(rows = 1; rows < HEIGHT; rows++) | |
{ | |
board[rows][0] = '|'; | |
board[rows][WIDTH - 1] = '|'; | |
} | |
} | |
void fillArray(int board[HEIGHT][WIDTH]) | |
{ | |
int i,j; | |
for(i = 1; i < HEIGHT - 1; i++) | |
for(j = 1; j < WIDTH - 1; j++) | |
board[i][j] = ' '; | |
} | |
void fillArrayRandomly(int board[HEIGHT][WIDTH]) | |
{ | |
int i, j, num; | |
srand((unsigned)time(NULL)); | |
for(i = 1; i < HEIGHT -1; i++) | |
for(j = 1; j < WIDTH - 1; j++) | |
{ | |
num = rand() % 11; | |
if (num == 1) | |
board[i][j] = 'O'; | |
else board[i][j] = ' '; | |
} | |
} | |
void display2DArray(int board[HEIGHT][WIDTH]) | |
{ | |
int rows; | |
int cols; | |
for(rows = 0; rows < HEIGHT; rows++) | |
{ | |
for(cols = 0; cols < WIDTH; cols++) | |
printf("%3c", board[rows][cols]); | |
printf("\n"); | |
} | |
} | |
void countNeighbours(int board[HEIGHT][WIDTH]) | |
{ | |
int neighbors; | |
int rows; | |
int cols; | |
int a, b; | |
for(rows = 1; rows < HEIGHT; rows++) | |
{ | |
for(cols = 1; cols < WIDTH; cols ++) | |
{ | |
neighbors = 0; | |
if (board[rows][cols] == 'O') | |
{ | |
for(a = -1; a < 2; a++) | |
{ | |
for(b = -1; b < 2; b++) | |
if (((rows + a) == rows) && ((cols + b) == cols)) | |
neighbors = neighbors; | |
else if ((board[rows + a][cols + b] == 'O') || (board[rows +a][cols +b] == 1) || (board[rows + a][cols + b] == 0)) | |
neighbors++; | |
} | |
if ((neighbors == 2) || (neighbors == 3)) | |
board[rows][cols] = 1; // Set alive. | |
else if ((neighbors < 2) || (neighbors >= 4)) | |
board[rows][cols] = 0; // Set dead. | |
} | |
} | |
} | |
} | |
void checkNewborns(int board[HEIGHT][WIDTH]) | |
{ | |
int neighbors; | |
int rows; | |
int cols; | |
int a, b; | |
for(rows = 1; rows < HEIGHT - 1; rows++) | |
{ | |
for(cols = 1; cols < WIDTH - 1; cols++) | |
{ | |
neighbors = 0; | |
if (board[rows][cols] == ' ') | |
{ | |
for(a = - 1; a < 2; a++) | |
{ | |
for(b = - 1; b < 2; b++) | |
if (((rows + a) == rows) && ((cols +b) == cols)) | |
neighbors = neighbors; | |
else if ((board[rows + a][cols + b] == 'O') || (board[rows + a][cols + b] == 1) || (board[rows + a][cols + b] == 0)) | |
neighbors++; | |
} | |
if ((neighbors == 3)) | |
board[rows][cols] = 2; // Newborn. | |
} | |
} | |
} | |
} | |
void newGeneration(int board[HEIGHT][WIDTH]) | |
{ | |
int rows; | |
int cols; | |
for(rows = 1; rows < HEIGHT -1; rows++) | |
{ | |
for(cols = 1; cols < WIDTH - 1; cols++) | |
{ | |
if (board[rows][cols] == 1) | |
board[rows][cols] = 'O'; | |
else if (board[rows][cols] == 2) | |
board[rows][cols] = 'O'; | |
else if (board[rows][cols] == 0) | |
board[rows][cols] = ' '; | |
} | |
} | |
} | |
int checkForExistance(int board[HEIGHT][WIDTH]) | |
{ | |
int rows; | |
int cols; | |
int creatures = 0; | |
for(rows = 1; rows < HEIGHT - 1; rows++) | |
{ | |
for(cols = 1; cols < WIDTH - 1; cols++) | |
{ | |
if (board[rows][cols] == 'O') | |
creatures++; | |
} | |
} | |
if (creatures == 0) | |
return TRUE; // All live forms dead. | |
else return FALSE; // There is still life existent. | |
} | |
void playGame(int board[HEIGHT][WIDTH], int numgeneration) | |
{ | |
int i, c, check; | |
for(i = 1; (i <= numgeneration) && (c != 32); i++) | |
{ | |
system("cls"); // Clear board. | |
countNeighbours(board); | |
checkNewborns(board); | |
newGeneration(board); | |
printf("Generation: %i\n", i); | |
printf("Press enter to move to the next generation.\n"); | |
display2DArray(board); | |
getchar(); | |
if(kbhit()) | |
{ | |
c = getch(); | |
if(c == 32) | |
break; | |
} | |
check = checkForExistance(board); | |
if ((check = checkForExistance(board)) == TRUE) | |
{ | |
printf("\nALL LIFE HAS DIED: GAME OVER!"); | |
c = 32; | |
} | |
} | |
} | |
int returnNumber(int anumber) | |
{ | |
if ((anumber > 50) || (anumber == 0)) | |
{ | |
printf("ERROR: The number must be between 1 and 50!\n"); | |
printf("Please enter a valid number: "); | |
scanf("%i", &anumber); | |
returnNumber(anumber); | |
} | |
else return anumber; | |
} | |
void inputCoordinates(int board[HEIGHT][WIDTH]) | |
{ | |
int rows = 1; | |
int cols = 1; | |
while ((rows > 0) && (cols > 0)) | |
{ | |
printf("\nPlease enter x coordinate(a number from 1 to 30): "); | |
scanf("%i", &cols); | |
cols = returnNumber(cols); | |
if (cols > 0) | |
{ | |
printf("Please enter Y coordinate (a number from 1 to 50): "); | |
scanf("%i", &rows); | |
rows = returnNumber(rows); | |
if ((rows > 0) && (cols > 0)) | |
board[rows][cols] = 'O'; | |
} | |
} | |
} | |
void createPatternTypes(int board[HEIGHT][WIDTH]) | |
{ | |
int type; | |
printf("\nType [1] to use the pattern 'BOX'"); | |
printf("\nType [2] to use the pattern 'BEEHIVE'"); | |
printf("\nType [3] to use the pattern 'TOAD'"); | |
printf("\nType [4] to use the pattern 'SHIP'"); | |
printf("\nType [5] to use the pattern 'GLIDER'"); | |
printf("\nType [6] to use the pattern 'QUEEN BEE SHUTTLE'"); | |
printf("\nType [7] to use the pattern 'PULSAR'"); | |
printf("\nType [8] to use the pattern 'BLINKER'"); | |
printf("\nType [9] to use the pattern 'PENTADECATHLON'\n"); | |
scanf("%i", &type); | |
if (type == 1) | |
{ | |
board[10][10] = 'O'; | |
board[10][11] = 'O'; | |
board[11][10] = 'O'; | |
board[11][11] = 'O'; | |
} | |
else if (type == 9) | |
{ | |
board[15][10] = 'O'; | |
board[15][11] = 'O'; | |
board[15][12] = 'O'; | |
board[15][13] = 'O'; | |
board[15][14] = 'O'; | |
board[15][15] = 'O'; | |
board[15][16] = 'O'; | |
board[15][17] = 'O'; | |
board[15][18] = 'O'; | |
board[15][19] = 'O'; | |
} | |
else if (type == 5) | |
{ | |
board[28][3] = 'O'; | |
board[27][4] = 'O'; | |
board[26][4] = 'O'; | |
board[27][5] = 'O'; | |
board[28][5] = 'O'; | |
} | |
else if (type == 3) | |
{ | |
board[18][12] = 'O'; | |
board[18][13] = 'O'; | |
board[18][14] = 'O'; | |
board[19][11] = 'O'; | |
board[19][12] = 'O'; | |
board[19][13] = 'O'; | |
} | |
else if (type == 6) | |
{ | |
board[20][28] = 'O'; | |
board[20][29] = 'O'; | |
board[21][30] = 'O'; | |
board[22][31] = 'O'; | |
board[23][31] = 'O'; | |
board[24][31] = 'O'; | |
board[25][30] = 'O'; | |
board[26][29] = 'O'; | |
board[26][28] = 'O'; | |
} | |
else if (type == 7) | |
{ | |
board[12][14] = 'O'; | |
board[13][13] = 'O'; | |
board[13][14] = 'O'; | |
board[13][15] = 'O'; | |
board[14][13] = 'O'; | |
board[14][15] = 'O'; | |
board[15][13] = 'O'; | |
board[15][14] = 'O'; | |
board[15][15] = 'O'; | |
board[16][14] = 'O'; | |
} | |
else if (type == 8) | |
{ | |
board[12][12] = 'O'; | |
board[12][13] = 'O'; | |
board[12][14] = 'O'; | |
} | |
else if (type == 4) | |
{ | |
board[12][12] = 'O'; | |
board[12][13] = 'O'; | |
board[13][12] = 'O'; | |
board[14][13] = 'O'; | |
board[14][14] = 'O'; | |
board[13][14] = 'O'; | |
} | |
else if (type ==2) | |
{ | |
board[12][14] = 'O'; | |
board[13][13] = 'O'; | |
board[13][15] = 'O'; | |
board[14][13] = 'O'; | |
board[15][14] = 'O'; | |
board[14][15] = 'O'; | |
} | |
} | |
void userMode(int board[HEIGHT][WIDTH]) | |
{ | |
int i, generation, c, choice; | |
printf("\nDo you want to insert a particular pattern type? [1] for yes or [0] for no: "); | |
scanf("%i", &choice); | |
if (choice == 1) | |
{ | |
createPatternTypes(board); | |
display2DArray(board); | |
} | |
else | |
{ | |
inputCoordinates(board); | |
display2DArray(board); | |
} | |
printf("\nPlease input number of generations: "); | |
scanf("%i", &generation); | |
playGame(board, generation); | |
} | |
void automaticMode(int board[HEIGHT][WIDTH]) | |
{ | |
int i, generation, c; | |
fillArrayRandomly(board); | |
display2DArray(board); | |
printf("\nPlease input number of generations: "); | |
scanf("%i", &generation); | |
playGame(board, generation); | |
} | |
void hybridMode(int board[HEIGHT][WIDTH]) | |
{ | |
int i, generation, c; | |
fillArrayRandomly(board); | |
display2DArray(board); | |
inputCoordinates(board); | |
system("cls"); // Clear console. | |
display2DArray(board); | |
printf("\nPlease input number of generations: "); | |
scanf("%i", &generation); | |
playGame(board, generation); | |
} | |
// Main function. | |
int main(int argc, char *argv[]) | |
{ | |
printf("\nCONWAY'S GAME OF LIFE\n\n"); | |
int h = atoi(argv[1]); | |
int w = atoi(argv[2]); | |
if (h) HEIGHT = h; | |
if (w) WIDTH = w; | |
printf("Height: %i\nWidth: %i\n\n", HEIGHT, WIDTH); | |
int board[HEIGHT][WIDTH], mode; | |
makeBoardLines(board); | |
fillArray(board); | |
printf("Please press CTRL+C to terminate the program, press enter to move to the next generation.\n"); | |
printf("Type [1] for User Mode, [2] for Automatic Mode and [3] for Hybrid Mode: "); | |
scanf("%i", &mode); | |
if (mode == 1) | |
userMode(board); | |
else if (mode == 2) | |
automaticMode(board); | |
else if (mode == 3) | |
hybridMode(board); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment