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)
./life ancho alto rondas: un tablero deanchoxalto, todo muerto.- Por
stdinllegan comandos para un boli que empieza arriba a la izquierda, levantado. w a s dmueven el boli (arriba, izquierda, abajo, derecha). En el borde se queda quieto.xbaja o levanta el boli. Con el boli bajado, cada casilla por la que pasa queda viva.- Al acabar los comandos: juegas
rondasveces al juego de la vida e imprimes (Oviva, espacio muerta).
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]));
- 3 vecinos → viva (nace o sigue).
- 2 vecinos → sigue como estaba.
- Otro número → muerta.
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
| Parte | Qué hace |
|---|---|
| argumentos | tiene que haber 3 · atoi para pasarlos a número |
| tableros | board[2][h + 2][w + 2] con marco · los dos todo a 0 |
| dibujar | read de 1 en 1 hasta el final · mover / x · boli bajado → viva |
| rondas | para cada casilla: contar vecinos → regla → board[!cur] · cur = !cur |
| imprimir | putchar('O') o putchar(' ') · '\n' al final de cada fila |
Checklist
- el boli empieza en
(1, 1)y levantado (pen = 0) w= arriba =y--·s= abajo =y++- vecinos: el 3x3 menos yo
- escribir en
board[!cur], luegocur = !cur 'O'es la letra o mayúscula, no el cero
Otras soluciones
Las cinco dan la misma salida en los ejemplos del subject. Cambia cómo se escriben.
| Versión | Borde | Saltar la propia celda | Dos tableros | Ojo |
|---|---|---|---|---|
| Optim | sí | n -= board[cur][i][j] | cur = !cur | la más corta con borde |
| Fácil | sí | if (di || dj) | next y copiar | un doble bucle más, pero nada que alternar |
| Funciones | sí | return n - b[i][j] | cur = !cur | firmas largas: char b[h + 2][w + 2] |
| stc71 ↗ | no | (di || dj) | next y copiar | sin borde: un if de 4 límites · no comprueba negativos |
| mohaben ↗ | sí | if (dx != 0 || dy != 0) | it % 2 | el 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.