以下は、グローバル変数が多い、読みにくいコード。状態が遷移した回数だけgif画像を出力する(要ImageMagick)。
LIM回状態が遷移するか、状態が変わらなかったとき、終了する。ダブルバッファリングなどの洒落た機能は入れて無いので、画面がチラチラするかもしれない。
#include <stdio.h> #include <string.h> #include <eggx.h> #define EGGX_BLACK 0 #define EGGX_WHITE 1 /* 最大100*100マスまで許容する */ #define MAX_SIZE 100 #define CELL_WIDTH 20 #define CELL_HEIGHT 20 #define DEAD 0 #define LIVE 1 /* 最大1000回まで状態を遷移させる */ #define LIM 1000 /* 状態遷移間隔(ミリ秒) */ #define DELAY 200 int win; int w, h; int width, height; int board[MAX_SIZE][MAX_SIZE]; int prev[MAX_SIZE][MAX_SIZE]; void init(void); int next_state(int y, int x); void change_cells(void); void draw_cell(int y, int x); void draw_cells(void); void init(void) { int x, y; memset(prev, -1, sizeof(prev)); scanf("%d %d", &w, &h); width = w*CELL_WIDTH; height = h*CELL_HEIGHT; for (y = 0; y < h; y++) for (x = 0; x < w; x++) scanf("%d", &board[y][x]); } int next_state(int y, int x) { int i, live; int dy[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; int dx[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; live = 0; for (i = 0; i < 8; i++) { int ty = y+dy[i], tx = x+dx[i]; if (!(0 <= ty && ty < h)) continue; if (!(0 <= tx && tx < w)) continue; if (board[ty][tx] == LIVE) live++; } switch (live) { case 2: return board[y][x]; case 3: return LIVE; default: return DEAD; } } void change_cells(void) { int y, x; int buf[MAX_SIZE][MAX_SIZE]; memset(buf, 0, sizeof(buf)); for (y = 0; y < h; y++) for (x = 0; x < w; x++) buf[y][x] = next_state(y, x); memcpy(board, buf, sizeof(buf)); } void draw_cell(int y, int x) { int kind; int px, py; kind = board[y][x]; newpen(win, kind==DEAD?EGGX_WHITE:EGGX_BLACK); px = x*CELL_WIDTH; py = (h-1-y)*CELL_HEIGHT; fillrect(win, px, py, CELL_WIDTH, CELL_HEIGHT); } void draw_cells(void) { int y, x; for (y = 0; y < h; y++) for (x = 0; x < w; x++) if (board[y][x] != prev[y][x]) draw_cell(y, x); newpen(win, EGGX_BLACK); drawrect(win, 0, 0, width-1, height-1); } int main(void) { int i; init(); win = gopen(width, height); for (i = 0; i < LIM; i++) { if (memcmp(board, prev, sizeof(board))==0) break; winname(win, "turn %d", i); draw_cells(); saveimg(win, 0, 0, 0, width-1, height-1, "convert", 16, "img%d.gif", 1000+i); memcpy(prev, board, sizeof(board)); change_cells(); msleep(DELAY); } gclose(win); return 0; }
入力例と、それに対応する出力された画像をまとめたgif動画。入力のはじめ一行の二値は、それぞれ幅と高さを意味する。それに続くデータは、0なら死、1なら生を表す。
10 10 0 1 0 0 0 0 0 0 0 0 0 0 1 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0