Created
October 29, 2017 17:57
-
-
Save mtao/ffa645c9ec15e2be8da9708473a253a3 to your computer and use it in GitHub Desktop.
game of life / langdon's ant code i wrote to help someone learning first year C
This file contains hidden or 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
#include <stdio.h> | |
#include <unistd.h> | |
#define NUM_ROWS 50 | |
#define NUM_COLS 50 | |
int wrap(int i, int max) { | |
return ((i) % max + max) % max; | |
} | |
int row_wrap(int i) { | |
return wrap(i,NUM_ROWS); | |
} | |
int col_wrap(int j) { | |
return wrap(j,NUM_COLS); | |
} | |
void copy(int from[NUM_ROWS][NUM_COLS], int to[NUM_ROWS][NUM_COLS]) | |
{ | |
for(int i = 0; i < NUM_ROWS; ++i) { | |
for(int j = 0; j < NUM_COLS; ++j) { | |
to[i][j] = from[i][j]; | |
} | |
} | |
} | |
void swap(int g1[NUM_ROWS][NUM_COLS], int g2[NUM_ROWS][NUM_COLS]) | |
{ | |
for(int i = 0; i < NUM_ROWS; ++i) { | |
for(int j = 0; j < NUM_COLS; ++j) { | |
int tmp = g1[i][j]; | |
g1[i][j] = g2[i][j]; | |
g2[i][j] = tmp; | |
} | |
} | |
} | |
void clear(int g[NUM_ROWS][NUM_COLS]) | |
{ | |
for(int i = 0; i < NUM_ROWS; ++i) { | |
for(int j = 0; j < NUM_COLS; ++j) { | |
g[i][j] = 0; | |
} | |
} | |
} | |
void print(int g[NUM_ROWS][NUM_COLS]) | |
{ | |
for(int j = 0; j < NUM_COLS; ++j) { | |
printf("="); | |
} | |
printf("\n"); | |
for(int i = 0; i < NUM_ROWS; ++i) { | |
for(int j = 0; j < NUM_COLS; ++j) { | |
if(g[i][j] != 0) { | |
printf("o"); | |
} else { | |
printf("."); | |
} | |
} | |
printf("\n"); | |
} | |
for(int j = 0; j < NUM_COLS; ++j) { | |
printf("="); | |
} | |
printf("\n\n"); | |
} | |
int alive_neighbors(int grid[NUM_ROWS][NUM_COLS], int i, int j) | |
{ | |
int alive = 0; | |
for(int l = -1; l < 2; ++l) { | |
for(int m = -1; m < 2; ++m) { | |
if((l != 0) || (m != 0)) { | |
int ri = wrap(i+l,NUM_ROWS); | |
int rj = wrap(j+m,NUM_COLS); | |
if(grid[ri][rj] != 0) { | |
alive++; | |
} | |
} | |
} | |
} | |
return alive; | |
} | |
void gol_step(int grid[NUM_ROWS][NUM_COLS]) | |
{ | |
int tmpgrid[NUM_ROWS][NUM_COLS]; | |
copy(grid,tmpgrid); | |
clear(grid); | |
for(int i = 0; i < NUM_ROWS; ++i) { | |
for(int j = 0; j < NUM_COLS; ++j) { | |
int alive_nbrs = alive_neighbors(tmpgrid,i,j); | |
int alive = tmpgrid[i][j]; | |
if(alive != 0) { | |
if(alive_nbrs < 2 || alive_nbrs > 3) { | |
alive = 0; | |
} else { | |
alive = 1; | |
} | |
} else { | |
if(alive_nbrs == 3) { | |
alive = 1; | |
} | |
} | |
grid[i][j] = alive; | |
} | |
} | |
} | |
void set(int grid[NUM_ROWS][NUM_COLS], int i, int j, int val) | |
{ | |
int ri = wrap(i,NUM_ROWS); | |
int rj = wrap(j,NUM_COLS); | |
grid[ri][rj] = val; | |
} | |
void toad(int grid[NUM_ROWS][NUM_COLS], int i, int j) | |
{ | |
set(grid,i+0,j+0,1); | |
set(grid,i+0,j+1,1); | |
set(grid,i+0,j+2,1); | |
set(grid,i+1,j+1,1); | |
set(grid,i+1,j+2,1); | |
set(grid,i+1,j+3,1); | |
} | |
void glider(int grid[NUM_ROWS][NUM_COLS], int i, int j) | |
{ | |
set(grid,i+0,j+1,1); | |
set(grid,i+1,j+0,1); | |
set(grid,i+2,j+0,1); | |
set(grid,i+2,j+1,1); | |
set(grid,i+2,j+2,1); | |
} | |
void beacon(int grid[NUM_ROWS][NUM_COLS], int i, int j) | |
{ | |
set(grid,i+0,j+0,1); | |
set(grid,i+1,j+0,1); | |
set(grid,i+0,j+1,1); | |
set(grid,i+1,j+1,1); | |
set(grid,i+2,j+2,1); | |
set(grid,i+3,j+2,1); | |
set(grid,i+2,j+3,1); | |
set(grid,i+3,j+3,1); | |
} | |
int value(int grid[NUM_ROWS][NUM_COLS], int i, int j) { | |
return grid[row_wrap(i)][row_wrap(j)]; | |
} | |
//0 = north | |
//1 = east | |
//2 = south | |
//3 = west | |
int left(int dir) { | |
return wrap(dir-1,4); | |
} | |
int right(int dir) { | |
return wrap(dir+1,4); | |
} | |
int xoff(int dir) { | |
switch(dir) { | |
case 0: return 0; | |
case 1: return 1; | |
case 2: return 0; | |
case 3: return -1; | |
} | |
return 0; | |
} | |
int yoff(int dir) { | |
switch(dir) { | |
case 0: return 1; | |
case 1: return 0; | |
case 2: return -1; | |
case 3: return 0; | |
} | |
return 0; | |
} | |
void langdon_ant_step(int grid[NUM_ROWS][NUM_COLS], int* x_ptr, int* y_ptr, int* dir_ptr) | |
{ | |
int x = *x_ptr; | |
int y = *y_ptr; | |
int dir = *dir_ptr; | |
if(value(grid,x,y) == 0) {//black | |
dir = right(dir); | |
} else { | |
dir = left(dir); | |
} | |
grid[x][y] = grid[x][y]==0?1:0; | |
x = row_wrap(x + xoff(dir)); | |
y = col_wrap(y + yoff(dir)); | |
*x_ptr = x; | |
*y_ptr = y; | |
*dir_ptr = dir; | |
} | |
void gol(int grid[NUM_ROWS][NUM_COLS]) { | |
//for(int i = 0; i < 1000; ++i) { | |
while(1) { | |
print(grid); | |
gol_step(grid); | |
usleep(16000); | |
} | |
} | |
void langdon_ant(int grid[NUM_ROWS][NUM_COLS]) | |
{ | |
int x = NUM_ROWS/2; | |
int y = NUM_COLS/2; | |
int dir = 0; | |
while(1) { | |
print(grid); | |
langdon_ant_step(grid,&x,&y,&dir); | |
usleep(16000); | |
} | |
} | |
void double_step(int grid[NUM_ROWS][NUM_COLS]) | |
{ | |
int x = NUM_ROWS/2; | |
int y = NUM_COLS/2; | |
int dir = 0; | |
while(1) { | |
gol_step(grid); | |
for(int i = 0; i < 20; ++i) { | |
langdon_ant_step(grid,&x,&y,&dir); | |
usleep(1600); | |
print(grid); | |
} | |
} | |
} | |
int main() { | |
int grid[NUM_ROWS][NUM_COLS]; | |
for(int i = 0; i < NUM_ROWS; ++i) { | |
for(int j = 0; j < NUM_COLS; ++j) { | |
if(grid[i][j] != 0) { | |
grid[i][j] = 1; | |
} | |
} | |
} | |
//clear(grid); | |
toad(grid,5,6); | |
glider(grid,20,1); | |
beacon(grid,2,30); | |
double_step(grid); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment