life

Código comentado línea a línea y paso a paso:

Entregas: life.h, life.c. Flags: gcc -Wall -Wextra -Werror

Qué pide (en palabras normales)

Subject (enunciado original)
Assignment name  : life
Expected files   : *.c *.h
Allowed functions: atoi, read, putchar, malloc, calloc, realloc, free
--------------------------------------------------------------------------------

You must write a program that will simulate a game of life.
The prototype of this program is the following:
./life width height iterations

Width and height are the dimensions of the board and iterations is the number of
iterations of the game of life.

The initial configuration of the board will be drawn by a sequence of commands
in the standard input.

Imagine a pen starting in the top left corner of the board.
Each command is one of these characters:
'w', 'a', 's', 'd': move the pen up, left, down, and right.
'x': lift or lower the pen in order to start or stop drawing. Default is: pen not drawing.

Your pen is not moving outside of the board, and will stay still if a command asks for it.
Your pen does nothing in case of invalid command.

Once end of file is reached, your program must simulate a game of life on this
board and print the result in stdout (each cell alive will be represented by
the character 'O' and each dead cell will be represented by a space).

Each cell outside of the array will be considered dead.

Example:
$> echo 'sdxddssaaww' | ./a.out 5 5 0 | cat -e
     $
 OOO $
 O O $
 OOO $
     $
$> echo 'sdxssdswdxddddsxaadwxwdxwaa' | ./a.out 10 6 0 | cat -e
          $
 O   OOO  $
 O     O  $
 OOO  O   $
  O  OOO  $
          $
$> echo 'dxss' | ./a.out 3 3 0 | cat -e
 O $
 O $
 O $
$> echo 'dxss' | ./a.out 3 3 1 | cat -e
   $
OOO$
   $
$> echo 'dxss' | ./a.out 3 3 2 | cat -e
 O $
 O $
 O $

Vídeos

El mismo ejemplo (dxss, 3x3) con el código escribiéndose en tiempo real.

Optim, paso a paso

Partido en funciones

4 piezas

1. El marco

char	board[2][h + 2][w + 2];

Dos tableros: board[cur] es el de ahora y board[!cur] el de la ronda siguiente. Cada uno lleva una casilla de más por cada lado, siempre muerta. Las de verdad van de 1 a h y de 1 a w. Así, al contar vecinos en el borde, nunca te sales: caes en el marco, que vale 0. Es lo que dice el subject: fuera del tablero, todo muerto.

2. El boli

if (c == 'w' && y > 1)
	y--;
...
else if (c == 'x')
	pen = !pen;
if (pen)
	board[0][y][x] = 1;

Moverse solo si no estás en el borde. Después de cada comando, si el boli está bajado, la casilla donde estás queda viva (también justo al bajarlo con x).

3. Contar vecinos

int	n = 0;
for (int di = -1; di <= 1; di++)
	for (int dj = -1; dj <= 1; dj++)
		n += board[cur][i + di][j + dj];
n -= board[cur][i][j];

Sumas el cuadrado 3x3 que te rodea (viva = 1, muerta = 0). Ese 3x3 te incluye a ti, por eso al final te restas.

4. Las reglas (no vienen en el subject)

board[!cur][i][j] = (n == 3 || (n == 2 && board[cur][i][j]));

Lo nuevo va a board[!cur], no a board[cur]: si escribieras en el de ahora mientras cuentas, estropearías los vecinos de las casillas que aún no has mirado. Al acabar la ronda, cur = !cur: el siguiente pasa a ser el de ahora, sin copiar nada.

El main por partes

ParteQué hace
argumentostiene que haber 3 · atoi para pasarlos a número
tablerosboard[2][h + 2][w + 2] con marco · los dos todo a 0
dibujarread de 1 en 1 hasta el final · mover / x · boli bajado → viva
rondaspara cada casilla: contar vecinos → regla → board[!cur] · cur = !cur
imprimirputchar('O') o putchar(' ') · '\n' al final de cada fila

Checklist

Otras soluciones

Las cinco dan la misma salida en los ejemplos del subject. Cambia cómo se escriben.

VersiónBordeSaltar la propia celdaDos tablerosOjo
Optimsín -= board[cur][i][j]cur = !curla más corta con borde
Fácilsíif (di || dj)next y copiarun doble bucle más, pero nada que alternar
Funcionessíreturn n - b[i][j]cur = !curfirmas largas: char b[h + 2][w + 2]
stc71 ↗no(di || dj)next y copiarsin borde: un if de 4 límites · no comprueba negativos
mohaben ↗síif (dx != 0 || dy != 0)it % 2el main acaba sin return

Para estudiar: Fácil. Junta el borde de Optim, el if (di || dj) y la regla en if/else de mohaben, y la copia de stc71. Sin cur ni restas.

stc71 y mohaben no se copian aquí (sin licencia): el enlace ↗ lleva a su código en GitHub.