Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

CS 1713 Assignment 9: The Game of Life — Spring 1998, Assignments of Computer Science

Instructions for assignment 9 of the cs 1713 course, where students are required to write a c program to simulate the game of life. The rules of the game, the required functions, and provides a sample outline for the program. It also suggests improvements for better program output.

Typology: Assignments

Pre 2010

Uploaded on 07/30/2009

koofers-user-51j
koofers-user-51j 🇺🇸

10 documents

1 / 2

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CS 1713, Assignment 9, The Game of Life Spring 1998 Page 1 of 2
CS 1713, Introduction to Computer Science
Assignment 9, Spring 1998
The Game of Life, Due April 16, 1998
Life. For this assignment you are to write a C program that will simulate the game of “Life.” Life takes
place on an infinite 2-dimensional rectangular grid of cells. Initially (the 0th generation, or at time

)
some finite collection of these cells are “live”— the rest are “dead. At each successive generation, cells
may remain live or dead, or may switch states according to fixed rules. Thus the course of the game depends
on the initial configuration and on the fixed set of rules. What happens to a cell depends on its state (live or
dead) and on the states of its 8 neighbors (cells touching the given cell on an edge or a corner).
Here are the rules:
BIRTH: A cell that’s dead at time
becomes live at time

if exactly three of its eight neighbors were
live at time
.
DEATH by overcrowding: A cell that’s live at time
and has four or more of its eight neighbors live at
time
will be dead at time

.
DEATH by exposure: A live cell that has only one live neighbor or none at all at time
will also be dead
at time

.
In summary, a live cell stays live if it has exactly 2 or 3 live neighbors—otherwise it dies. A dead cell
becomes a live one if it has exactly 3 live neighbors—otherwise it stays dead. These simple rules lead to an
astonishing complexity.
A Finite Grid. For this course it is too hard to think about an “infinite” grid of cells, so your simulation
should work on a fixed rectangular

grid of cells—with
rows and
columns. Since we want
you to display your results on an ordinary terminal screen, you should choose

and

,i.e., a


rectangular grid. I suggest you use an array of char, using a blank for dead and a star (*) for live.
Notice that cells on the boundaries of the grid do not have a full eight neighbors, and your count of dead
and live cells must stay inside the grid. (You must not have a row or column index outside the ranges from
0 to

and from 0 to

.)
The Initial Program. Your program should use two

arrays, for the
th and

st generations.
These arrays should be passed as parameters. You must use a separate C function neighbors with the row
and column number as parameters that returns the number of live neighbors of a given cell. (The function
neighbors must also handle the boundary correctly.) You must also have a function next gen with the
two arrays as parameters that updates from one generation to the next (using the neighbors function).
Another function get config should read a finite list of pairs of integers for the initial configuration.
There will be a number of sample initial files to choose from. Finally, you need a function disp array to
output each new generation to the screen. The simplest way is just to write 24 lines of 80 characters each.
Here is a sample outline for this program:
#include <stdio.h>
#include <stdlib.h>
#define M 24
#define N 80
#define MAX_GEN 40
void get_config(char b[M][N]);
void blank_array(char b[M][N]);
void disp_array(char b[M][N]);
void next_gen(char b1[M][N], char b2[M][N]);
void assign(char b1[M][N], char b2[M][N]);
int neighbors(char b[M][N], int i, int j);
void main(void)
{
char b1[M][N], b2[M][N];
get_config(b1);
pf2

Partial preview of the text

Download CS 1713 Assignment 9: The Game of Life — Spring 1998 and more Assignments Computer Science in PDF only on Docsity!

CS 1713, Assignment 9, The Game of Life — Spring 1998 Page 1 of 2

CS 1713, Introduction to Computer Science Assignment 9, Spring 1998 The Game of Life, Due April 16, 1998 Life. For this assignment you are to write a C program that will simulate the game of “Life.” Life takes place on an infinite 2-dimensional rectangular grid of cells. Initially (the 0th generation, or at time

some finite collection of these cells are “live”— the rest are “dead.” At each successive generation, cells may remain live or dead, or may switch states according to fixed rules. Thus the course of the game depends on the initial configuration and on the fixed set of rules. What happens to a cell depends on its state (live or dead) and on the states of its 8 neighbors (cells touching the given cell on an edge or a corner).

Here are the rules: BIRTH: A cell that’s dead at time

becomes live at time

if exactly three of its eight neighbors were live at time

DEATH by overcrowding: A cell that’s live at time

and has four or more of its eight neighbors live at time

will be dead at time

DEATH by exposure: A live cell that has only one live neighbor or none at all at time

will also be dead at time

In summary, a live cell stays live if it has exactly 2 or 3 live neighbors—otherwise it dies. A dead cell becomes a live one if it has exactly 3 live neighbors—otherwise it stays dead. These simple rules lead to an astonishing complexity.

A Finite Grid. For this course it is too hard to think about an “infinite” grid of cells, so your simulation

should work on a fixed rectangular  grid of cells—with rows and  columns. Since we want

you to display your results on an ordinary terminal screen, you should choose

and 

, i.e. , a

rectangular grid. I suggest you use an array of char, using a blank for dead and a star (*) for live. Notice that cells on the boundaries of the grid do not have a full eight neighbors, and your count of dead and live cells must stay inside the grid. (You must not have a row or column index outside the ranges from

0 to 

and from 0 to 

The Initial Program. Your program should use two  arrays, for the

th and 

st generations. These arrays should be passed as parameters. You must use a separate C function neighbors with the row and column number as parameters that returns the number of live neighbors of a given cell. (The function neighbors must also handle the boundary correctly.) You must also have a function next gen with the two arrays as parameters that updates from one generation to the next (using the neighbors function). Another function get config should read a finite list of pairs of integers for the initial configuration. There will be a number of sample initial files to choose from. Finally, you need a function disp array to output each new generation to the screen. The simplest way is just to write 24 lines of 80 characters each. Here is a sample outline for this program: #include <stdio.h> #include <stdlib.h> #define M 24 #define N 80 #define MAX_GEN 40 void get_config(char b[M][N]); void blank_array(char b[M][N]); void disp_array(char b[M][N]); void next_gen(char b1[M][N], char b2[M][N]); void assign(char b1[M][N], char b2[M][N]); int neighbors(char b[M][N], int i, int j); void main(void) { char b1[M][N], b2[M][N]; get_config(b1);

CS 1713, Assignment 9, The Game of Life — Spring 1998 Page 2 of 2

disp_array(b1); fflush(stdout); int dummy; for (dummy = 0; dummy < MAX_GEN; dummy++) { next_gen(b1, b2); disp_array(b2); fflush(stdout); sleep(1); assign(b1, b2); } } Note that next gen takes the grid for the old generation b1 and produces a grid b2 for the next generation. Because the program moves from b1 to b2, it is necessary to copy b2 back to b1, overwriting the old contents of b1. This is carried out by the function assign. There is also a system function sleep(1) that puts the program to sleep for 1 second, to slow down the output. Finally, on runner it is necessary to force output with a system call fflush(stdout). (One could cleverly use next gen(b1, b2) followed by next gen(b2, b1) in the for loop to avoid the assign function.) I intend for you to terminate this program by typing ctrl-C. (This way you can watch as many generations as you like. However, be sure to use a for loop as shown with a maximum number of generations, so that you won’t produce a huge amount of output by mistake.)

A Better Program. During initial debugging you should try to get your program to work just using this simple form of output. For full credit (and a more interesting program), you should handle the writing to the screen in a more sophisticated way. One would like to just change those screen grid locations where there was a change from one generation to the next. Let’s assume that you use a blank for dead cells and a star for live ones. Initially you should blank out the screen using a special C function clear screen, supplied below. (This and the next function work on VT-100 terminals, that accept special sequences of characters, starting with “escape” or 033, that cause special actions by the terminal, like to blank out the screen or to move the cursor to a new location.) void clear_screen(void) { printf ("\033[H\033[J"); } In going from the

th to the 

st generation, you should only redo those positions that changed, either from a blank to a star or vice-versa. Below is another C function move cursor void move_cursor(int x, int y) { printf ("\033[%d;%dH", y, x); }

that will move the cursor to position $#&%('

*) on the screen. (This moves to the column^ # and the row^ ', where

and

. To fit C conventions, you will need the call move cursor(i+1, j+1);.) Assuming that this grid position changed with the new generation, you can then write the appropriate char- acter (blank or star) to the screen. I suggest writing a function disp diff with the two grids as parameters that will make changes based on the differences from one generation to the next. This if a grid positions changes, you should make the change by moving the cursor and writing a blank or a star. Continue in this way for each changed position, first moving and then writing.

I will give a number of possible interesting initial configurations. You should use at least one of them in a final run of your program. Here are three interesting ones: lifedata.abomb lifedata.glider lifedata.monster