#00. はじめに
C初学者ですので、だらだらとした無駄の多いソースかもしれません。
「ビギナーのクソザコソースなんて読みたかねぇ」ならブラウザバック願います。
#01. ライフゲームとは?
ライフゲーム (Conway's Game of Life) は1970年にイギリスの数学者ジョン・ホートン・コンウェイ (John Horton Conway) が考案した生命の誕生、進化、淘汰などのプロセスを簡易的なモデルで再現したシミュレーションゲームである。単純なルールでその模様の変化を楽しめるため、パズルの要素を持っている。
生物集団においては、過疎でも過密でも個体の生存に適さないという個体群生態学的な側面を背景に持つ。セル・オートマトンのもっともよく知られた例でもある。
(Wikipediaより引用)
ルールもWikipediaがどのサイトよりも一番わかりやすいので説明を放棄するようで申し訳ないが、この際全部Wikipediaで読んできてほしい。[Wikipedia]ライフゲーム
#02. 作ってみる
環境は以下の通り
OS:MacOS Mojave(ver 10.14.5)
PC:MacBookAir(Retina,13-inch,2018)
メモリ:8GB
言語:C
#include<stdio.h>
#include<unistd.h>
#define NONE 0
#define EXIST 1
#define BOARDSIZE 40
//プロトタイプ宣言
int fill(void);
int check_field(void);
int memory_fill(void);
int oplofile(void);
int field[BOARDSIZE][BOARDSIZE] = {0};//盤面表示用配列
int memory_field[BOARDSIZE][BOARDSIZE] = {0};//メモリ配列
int generation = 0;//世代
int main(int argc, char const *argv[]) {
int ol_error = oplofile(); //ファイルオープンエラー
if (ol_error == 1) {
return 0;
}
while (1) {
sleep(1);
printf("現在のフィールドを描画します...\n");
fill();//盤面表示
printf("現在第%d世代\n", ++generation);
printf("\nフィールド計算中...");
check_field();//セル確認・計算・結果をメモリ配列に代入
memory_fill();//フィールド配列にメモリ配列を代入
printf("\n計算完了.");
int reddata = 0;//絶滅判定
for (int i = 0; i < BOARDSIZE; i++) {
for (int j = 0; j < BOARDSIZE; j++) {
if (field[i][j] == EXIST) {
++reddata;
}
}
}
if (reddata == 0) {
printf("第%d世代で絶滅しました.\n終了します\n", generation);
break;
}
}
return 0;
}
int fill(void){ //盤面表示関数
for (int i = 0; i < BOARDSIZE; i++) {
for (int j = 0; j < BOARDSIZE; j++) {
switch (field[i][j]) {
case NONE:
printf("□ ");
break;
case EXIST:
printf("■ ");
break;
default:
printf("N ");
break;
}
}
printf("\n");
}
return 0;
}
int check_field(void){
for (int i = 0; i < BOARDSIZE; i++) { //セルチェック・ルールに従って計算
for (int j = 0; j < BOARDSIZE; j++) {
int flag = 0;
if (field[i + 1][j] == EXIST) flag++;
if (field[i - 1][j] == EXIST) flag++;
if (field[i][j + 1] == EXIST) flag++;
if (field[i][j - 1] == EXIST) flag++;
if (field[i + 1][j + 1] == EXIST) flag++;
if (field[i + 1][j - 1] == EXIST) flag++;
if (field[i - 1][j + 1] == EXIST) flag++;
if (field[i - 1][j - 1] == EXIST) flag++;
if (flag <= 1) memory_field[i][j] = NONE; //結果をメモリ配列に代入
else if (flag == 2)memory_field[i][j] = field[i][j];
else if (flag == 3)memory_field[i][j] = EXIST;
else if (flag >= 4)memory_field[i][j] = NONE;
}
}
return 0;
}
int memory_fill(void){ //メモリ配列をフィールド配列に代入
for (int i = 0; i < BOARDSIZE; i++) {
for (int j = 0; j < BOARDSIZE; j++) {
field[i][j] = memory_field[i][j];
}
}
return 0;
}
int oplofile(void){ //ファイルオープン
FILE *fp;fp = fopen("celldata.csv", "r");
if (fp == NULL) {
printf("ERROR!!\n");
return 1;
}
else {
for (int i = 0; i < BOARDSIZE; i++) for (int j = 0; j < BOARDSIZE; j++) {
fscanf(fp,"%d,",&field[i][j]);
}
fclose(fp);
return 0;
}
}
csvファイルはExcelで作成したのち、.csvで出力すれば良い。
cソースファイルにもあるように、0が死、1が生。エクセルの設定で1の時だけセルの背景を黒にすると、盤面をデザインする際にわかりやすい。
#03. 実行してみる
実行してみると、このようになる
これは8倍速で、実際はもっと遅い。
正直もうターミナル上でやりたくない。
もっと広く、GUIアプリとして作りたいと思った。
それではノシ