Create a C program that implements \"The Game of Life\" cellular automata (CA) simulation. A
few comments: You will want 2 two-dimensional arrays. One that holds the current state of the
\"universe\" and second that is generated from the first using the Game of Life rules, which are
given below. After the computations for filling the second array are complete, the contents of the
second array can be copied back to the first. You can make the array as big as you want, but you
should probably use 20 times 20 as a minimum. As discussed in class, the outside boundary of
the \"universe\" can be a bit tricky. To keep it simple for this exercise, you can assume that the
outside boundary cells are always \"dead\". You can use whatever character (or number) that
you want to represent the \"living\" cells. The dead cells should probably be spaces. The rules
for whether a particular cell lives or dies are determined by the 8 surrounding cells. If a particular
cell is alive, then: If only 0 or 1 of the surrounding cells are alive, the cell dies. (It\'s lonely.) If
4 or more of the surrounding cells are alive, the cell dies. (Too much competition.) If 2 or 3 of
the surrounds cells are alive, the cell stays alive. If a particular cell is dead, then it comes to life
if exactly 3 of the surround cells are alive. You will have to pick some starting configuration for
the universe. An easy thing to do is fill the array randomly, and then let things go and see what
evolves. Write your program as described above and demo the operation to your TA. Then try
some modifications. First, try using a different starting configurations. Look here for some
ideas:. Gosper\'s Glider Gun is a famous one. Or try a simple spaceship or oscillator. Then try
changing the rules determining life and death. A common variation is to include a \"birth\" when
6 neighboring cells are alive in addition to the \"3-cell\" birth. Finally, there will be a short quiz
covering 2D arrays. This exercise should be very familiar.
Solution
#include #include #include #include #include #include #include #define ROWS 60 #define
COLS 60 #define OFF 0 #define ON 1 #define BLACK 8, 0, 0, 0, 0 #define scr_width 600
#define scr_height 600 #define cell_width (scr_width / ROWS) #define cell_height (scr_height /
COLS) We must hold two copies of the board so that we can analyze board and make *
changes to temp when killing/creating cells so that we don\'t cause changes * to the board to
affect the following cells. */ char board[ROWS][COLS]; char temp[ROWS][COLS];
SDL_Rect cells[ROWS][COLS]; /* Stores positions of each cell for blits. */ void
randomize_board(void); void initialize_grid(SDL_Surface* screen); void
blit_board(SDL_Surface* bcell, SDL_Surface* screen); int num_neighbours(int x, int y); void
update_board(void); int clear_board(SDL_Surface* screen, Uint32 color); int
clear_cell(SDL_Surface* screen, int x, int y, Uint32 color); void initialize_cells_array(void); int
main(void) { SDL_Init(SDL_INIT_VIDEO).
Hybridoma Technology ( Production , Purification , and Application )
Create a C program that implements The Game of Life cellular auto.pdf
1. Create a C program that implements "The Game of Life" cellular automata (CA) simulation. A
few comments: You will want 2 two-dimensional arrays. One that holds the current state of the
"universe" and second that is generated from the first using the Game of Life rules, which are
given below. After the computations for filling the second array are complete, the contents of the
second array can be copied back to the first. You can make the array as big as you want, but you
should probably use 20 times 20 as a minimum. As discussed in class, the outside boundary of
the "universe" can be a bit tricky. To keep it simple for this exercise, you can assume that the
outside boundary cells are always "dead". You can use whatever character (or number) that
you want to represent the "living" cells. The dead cells should probably be spaces. The rules
for whether a particular cell lives or dies are determined by the 8 surrounding cells. If a particular
cell is alive, then: If only 0 or 1 of the surrounding cells are alive, the cell dies. (It's lonely.) If
4 or more of the surrounding cells are alive, the cell dies. (Too much competition.) If 2 or 3 of
the surrounds cells are alive, the cell stays alive. If a particular cell is dead, then it comes to life
if exactly 3 of the surround cells are alive. You will have to pick some starting configuration for
the universe. An easy thing to do is fill the array randomly, and then let things go and see what
evolves. Write your program as described above and demo the operation to your TA. Then try
some modifications. First, try using a different starting configurations. Look here for some
ideas:. Gosper's Glider Gun is a famous one. Or try a simple spaceship or oscillator. Then try
changing the rules determining life and death. A common variation is to include a "birth" when
6 neighboring cells are alive in addition to the "3-cell" birth. Finally, there will be a short quiz
covering 2D arrays. This exercise should be very familiar.
Solution
#include #include #include #include #include #include #include #define ROWS 60 #define
COLS 60 #define OFF 0 #define ON 1 #define BLACK 8, 0, 0, 0, 0 #define scr_width 600
#define scr_height 600 #define cell_width (scr_width / ROWS) #define cell_height (scr_height /
COLS) We must hold two copies of the board so that we can analyze board and make *
changes to temp when killing/creating cells so that we don't cause changes * to the board to
affect the following cells. */ char board[ROWS][COLS]; char temp[ROWS][COLS];
SDL_Rect cells[ROWS][COLS]; /* Stores positions of each cell for blits. */ void
randomize_board(void); void initialize_grid(SDL_Surface* screen); void
blit_board(SDL_Surface* bcell, SDL_Surface* screen); int num_neighbours(int x, int y); void
update_board(void); int clear_board(SDL_Surface* screen, Uint32 color); int
clear_cell(SDL_Surface* screen, int x, int y, Uint32 color); void initialize_cells_array(void); int
main(void) { SDL_Init(SDL_INIT_VIDEO); SDL_WM_SetCaption("Conway's Game of
Life - Ryuurei", NULL); SDL_Event event; int breaker = 0; int paused = 1;
2. SDL_Surface* screen = SDL_SetVideoMode( scr_width, scr_height, 0,
SDL_SWSURFACE); if (! screen) { perror("SDL_SetVideoMode");
return EXIT_FAILURE; } Uint32 bgcolor = SDL_MapRGB(screen->format, 0xFF, 0xFF,
0xFF); if (SDL_FillRect(screen, &(screen->clip_rect), bgcolor) == -1) {
perror("SDL_FillRect"); return EXIT_FAILURE; } initialize_cells_array();
initialize_grid(screen); SDL_Surface* bcell = SDL_CreateRGBSurface(
SDL_SWSURFACE, cell_width, cell_height, BLACK); if (! bcell) { perror("BLACK
SDL_CreateRGBSurface"); return EXIT_FAILURE; } SDL_Flip(screen); while (1)
{ /* Infinite game loop. */ /** The event loop handles any events in the poll/queue *
even while paused. */ while (SDL_PollEvent(&event)) { switch (event.type) {
case SDL_QUIT: breaker = 1; break; case
SDL_KEYDOWN: /* Pause on enter/return key press. */ if
(event.key.keysym.sym == SDLK_KP_ENTER || event.key.keysym.sym ==
SDLK_RETURN) { paused = !paused; /* Space causes the board to
be randomized. */ } else if (event.key.keysym.sym == SDLK_SPACE) {
SDL_FillRect(screen, &(screen->clip_rect), bgcolor); randomize_board();
/* Escape button also quits. */ } else if (event.key.keysym.sym ==
SDLK_ESCAPE) { breaker = 1; break; /* Either shift
button clears the screen. */ } else if (event.key.keysym.sym == SDLK_RSHIFT ||
event.key.keysym.sym == SDLK_LSHIFT) { if
(clear_board(screen, bgcolor) == -1) { perror("clear_board");
return EXIT_FAILURE; } } break; case
SDL_MOUSEBUTTONDOWN: /** The only mouse event we handle is the left
click. * If the cell being clicked is alive, kill it. * Otherwise, give it
life. */ if (event.button.button == SDL_BUTTON_LEFT) {
if (event.button.y > (ROWS * cell_height)) break; int tx = floor(event.button.x /
cell_width); int ty = floor(event.button.y / cell_height); if
(board[tx][ty] == OFF) { board[tx][ty] = ON; temp[tx][ty] =
ON; SDL_BlitSurface( bcell, &(bcell-
>clip_rect), screen, &cells[tx][ty]); } else
if (clear_cell(screen, tx, ty, bgcolor) == -1) { perror("clear_cell");
return EXIT_FAILURE; } } break;
default: continue; } if (breaker) break; } if (breaker)
break; /* Redraw the grid so it's not painted over by clear_cell. */
initialize_grid(screen); blit_board(bcell, screen); SDL_Flip(screen); if (!paused) {
update_board(); SDL_Delay(250); SDL_FillRect(screen, &(screen-
3. >clip_rect), bgcolor); } } return EXIT_SUCCESS; } void randomize_board(void) {
/* Clear the board then randomly set ~1/5 of them to ON. */ memset((void *)board, OFF,
ROWS * COLS); for (int y = 0; y < ROWS; y++) { for (int x = 0; x < COLS; x++) {
if (rand() % 5 == 0) { board[x][y] = ON; } temp[x][y] = board[x][y];
} } } void initialize_grid(SDL_Surface* screen) { /** Position horizontal and veritcal
lines to form a grid to * make it easier to count cell spaces when trying to draw things. */
SDL_Surface* linex = SDL_CreateRGBSurface( /* Vertical lines */
SDL_SWSURFACE, 1, scr_height, BLACK); SDL_Surface* liney =
SDL_CreateRGBSurface( /* Horizontal lines */ SDL_SWSURFACE,
scr_width, 1, BLACK); SDL_Rect pos_x; SDL_Rect pos_y; pos_x.y = pos_y.x = 0;
for (int i = 0; i < scr_width / (cell_width); i++) { pos_x.x = cell_width + cell_width * i;
SDL_BlitSurface(linex, &(linex->clip_rect), screen, &pos_x); } for (int i = 0; i < scr_height
/ (cell_height); i++) { pos_y.y = cell_height + cell_height * i; SDL_BlitSurface(liney,
&(liney->clip_rect), screen, &pos_y); } } void blit_board(SDL_Surface* bcell,
SDL_Surface* screen) { /* Blit all the live cells onto the board. */ for (int y = 0; y <
ROWS; y++) { for (int x = 0; x < COLS; x++) { if (board[x][y] == ON) {
SDL_BlitSurface( bcell, &(bcell->clip_rect), screen,
&cells[x][y]); } } } } int num_neighbours(int x, int y) { /** Count the
number of live cells all around the cell given by * the position (x, y). Of course, this includes
all diagonal, vertical, * and horizontal living cells. The program works using a toroidal array,
* thus we must check to see if it is necessary to wrap to the other side * of the array in
order to find cells that must be taken into account. */ int num_adj = 0; int tmpy = y; int
tmpx = x; if (y-1 < 0) tmpy = ROWS - 1; else tmpy = y - 1; if
(board[x][tmpy] == ON) num_adj++; if (y+1 >= ROWS) tmpy = 0; else tmpy = y
+ 1; if (board[x][tmpy] == ON) num_adj++; if (x-1 < 0) tmpx = COLS - 1; else
tmpx = x - 1; if (board[tmpx][y] == ON) num_adj++; if (x+1 >= COLS) tmpx = 0;
else tmpx = x + 1; if (board[tmpx][y] == ON) num_adj++; if (y-1 < 0) tmpy =
ROWS - 1; else tmpy = y - 1; if (x-1 < 0) tmpx = COLS - 1; else tmpx = x
- 1; if (board[tmpx][tmpy] == ON) num_adj++; if (x+1 >= COLS) tmpx = 0; else
tmpx = x + 1; if (board[tmpx][tmpy] == ON) num_adj++; if (y+1 >= ROWS) tmpy =
0; else tmpy = y + 1; if (x+1 >= COLS) tmpx = 0; else tmpx = x + 1; if
(board[tmpx][tmpy] == ON) num_adj++; if (x-1 < 0) tmpx = COLS - 1; else tmpx
= x - 1; if (board[tmpx][tmpy] == ON) num_adj++; return num_adj; } void
update_board(void) { /** Detirmine which cells live and which die. Operate on temp so that
* each change does not affect following changes, then copy temp into * the main board to be
displayed. */ int neighbours = 0; for (int y = 0; y < ROWS; y++) { for (int x = 0; x
4. < COLS; x++) { neighbours = num_neighbours(x, y); if (neighbours < 2 &&
board[x][y] == ON) { temp[x][y] = OFF; /* Dies by underpopulation. */ } else
if (neighbours > 3 && board[x][y] == ON) { temp[x][y] = OFF; /* Dies by
overpopulation. */ } else if (neighbours == 3 && board[x][y] == OFF) {
temp[x][y] = ON; /* Become alive because of reproduction. */ } /* Otherwise the
cell lives with just the right company. */ } } for (int y = 0; y < ROWS; y++) { for
(int x = 0; x < COLS; x++) { board[x][y] = temp[x][y]; } } } int
clear_board(SDL_Surface* screen, Uint32 color) { /* Simply set both the main and temporary
boards to completely off. */ for (int y = 0; y < ROWS; y++) { for (int x = 0; x < COLS;
x++) { board[x][y] = OFF; temp[x][y] = OFF; } } return
SDL_FillRect(screen, &(screen->clip_rect), color); } int clear_cell(SDL_Surface* screen, int x,
int y, Uint32 color) { /* Clear a cell by coloring it white and setting the board pos. to off. */
SDL_Rect rect; rect.x = cell_width * x; rect.y = cell_height * y; board[x][y] = OFF;
temp[x][y] = OFF; return SDL_FillRect(screen, &rect, color); } void
initialize_cells_array(void) { /** Initialize the array of SDL_Rect structs that store the cell
* coordinates by iteratively calculating their successive positions. */ for (int y = 0; y <
ROWS; y++) { for (int x = 0; x < COLS; x++) { (cells[x][y]).x = (cell_width * x);
(cells[x][y]).y = (cell_height * y); } } }