CS1101C Practical Exam

Session 5 (1400 - 1545 hours)

Game of Life

The name of your C program file must be called life.c, files with any other name will not be marked.

The deadline for this lab is Tuesday 18 April 2006, 15:45:59 hours. Strictly no submissions will be accepted after the deadline.

Background

The game of life is not a game in the conventional sense. There are no players, and no winning or losing. Once the "pieces" are placed in the starting position, the rules determine everything that happens later. Nevertheless, Life is full of surprises! In most cases, it is impossible to look at a starting position (or pattern) and see what will happen in the future. The only way to find out is to follow the rules of the game.

Rules of the Game of Life

Life is played on a grid of square cells --- like a chess board but extending infinitely in every direction. For simplicity, we assume that our board is of size 20 x 20. A cell can be live or dead. A live cell is shown by putting a marker on its square. A dead cell is shown by leaving the square empty. Each cell in the grid has a neighborhood consisting of the eight cells in every direction including diagonals. To apply one step of the rules, we count the number of live neighbours for each cell. What happens next depends on this number.
  1. A dead cell with exactly three live neighbours becomes a live cell (birth).

  2. A live cell with two or three live neighbours stays alive (survival).

  3. In all other cases (less than two or more than three life neighbours), a cell dies or remains dead (overcrowding or loneliness).

Note: The number of live neighbours is always based on the cells before the rule was applied. In other words, we must first find all of the cells that change before changing any of them. Sounds like a job for a computer!

Example

Here is an example to show how the rules are applied. Supposing we have this initial configuration, which we call generation 0. We use '.' to mark a dead / empty cell, and '*' to mark a live cell.

...
***
...

First, we apply rule 1 and mark all the dead / empty cells that are "going to be born":

.@.
***
.@.

Then, we apply rule 3 and mark all the live cells that are "going to die" (in this case they die due to "loneliness"):

.@.
X*X
.@.

Note that when counting the number of neighbours for a live cell, it is dependent on how many current live neighbours it has. In another words, the neighbouring dead / empty cells that are "going to be born" (those marked with a '@') do not affect if a live cell is "going to survive or die".

Finally, we replace all '@' with '*', and replace all 'X' with '.'

.*.
.*.
.*.

The above is the next generation and is called generation 1. Subsequent generations are called generation 2, generation 3, etc.

Data File

Here is a sample data file called life1.txt which has been copied into your directory.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15

The board is a 20 x 20 board. The first twenty lines consist of the board layout, with 0 used to represent a dead / empty square, and 1 used to represent a square that is alive. This is followed by a single number (which we call n) that represents the nth generation we wish to display.

Task

Your task is to read the board layout from the data file called life1.txt (you may assume that the file always exists), read the value of n, then display the nth generation. Remember that the initial layout is called generation 0. You may assume that 1 <= n <= 9999, and that all numbers in the data file are valid. No error checking is required.

Sample Output

The following is the sample output using the above file. Remember that we will test your program with other input files.
Generation 0:
....................
....................
....................
....................
....................
....................
....................
....................
....................
.........***........
..........*.........
....................
....................
....................
....................
....................
....................
....................
....................
....................

Generation 15:
....................
....................
....................
....................
....................
....................
.........***........
....................
.......*.....*......
.......*.....*......
.......*.....*......
....................
.........***........
....................
....................
....................
....................
....................
....................
....................

You are reminded to follow the sample output exactly; else marks will be deducted.

Do not use any structures in your program, else no credit will be given.

Remember to submit your program using the submit life.c command, and check your submission using the check command.

All the best!

UNIX commands

Some useful UNIX commands (in case you forgot what you did in Lab 0):

  1. dir”: lists all the files in the directory.
  2. cp a.txt b.txt”: copies a.txt to b.txt.
  3. mv a.txt b.txt”: moves / renames a.txt to b.txt.
  4. cat a.txt”: shows the contents of a.txt.