C++
練習

セルオートマトンによる雪の結晶シミュレーション

初めに

雪の結晶は同じ形のものがないといってもいいほど様々な形がある。
その成長は分子レベルで観察すると先端で進行していることが分かっている。
それらをプログラムで再現してみる。

方針

下の図のようにセルを配置する。
21.png
セルに分子が吸着した状態を1(●)とし、何もない状態を0(〇)として表現する。

注目しているセルの周囲に分子が吸着したセルがが1つ存在する場合、次の時刻にそのセルに分子を吸着させる。
22.png
それ以外の場合(分子が吸着しているセルが0個や2個以上の時)は変化させないこととする。
23.png

プログラム

#define   _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define X 300
#define Y 300
int main(){
    FILE* xy = fopen("xy", "w");

    FILE* fp2;


    int time, TIME = 100;
    int cell[X][Y] = { 0 }, change[X][Y] = { 0 };
    int x, y;
    int goukei;

    char filename[60];

    FILE* fp = fopen("script", "w");
    fprintf(fp, "set terminal gif animate optimize delay 2 loop 1 size 1280,960\n");
    fprintf(fp, "set   output    ' ANIMA.gif ' \n");
    fprintf(fp, "set xrange[0:%d]\n",X);
    fprintf(fp, "set yrange[0:%d]\n",Y);
    for (time = 1; time < TIME; time++){
        fprintf(fp, "plot'%d'\n", time);
        fprintf(fp, "pause 1\n");
    }
    fprintf(fp, "set out\n");

    cell[X/2][Y/2+1] = 1; //初期状態の代入(核となる分子を仕込む)

    for (time = 1; time<TIME; time++){                          
        for (x = 0; x<X; x++)for (y = 0; y<Y; y++)change[x][y] = 0;  

        //次に各セルの状態を調べる
        for (x = 1; x<(X-1); x++)for (y = 1; y<(Y-1); y++){
            if (cell[x][y] == 0){
                if (x % 2 == 0){
                    goukei = cell[x][y + 1] + cell[x][y - 1] + cell[x - 1][y] + cell[x - 1][y - 1] + cell[x + 1][y] + cell[x + 1][y - 1];
                }
                if (x % 2 != 0){
                    goukei = cell[x][y + 1] + cell[x][y - 1] + cell[x - 1][y] + cell[x - 1][y + 1] + cell[x + 1][y] + cell[x + 1][y + 1];
                }
                if (goukei == 1){
                    change[x][y] = 1;
                }// セルの変更箇所を確定します
            }
        }

        for (x = 1; x < (X-1); x++){  
            for (y = 1; y < (Y-1); y++){
                cell[x][y] += change[x][y];
            }// セルの変更箇所を上書き更新します
        }

        sprintf(filename,"%d%",time);

        fp2 = fopen(filename, "w");
        for (x=1; x < (X-1); x++){
            for (y = 1; y < (Y-1); y++){
                if (cell[x][y] != 0){
                    if (y % 2 != 0)fprintf(fp2, "%lf  %lf\n", (double)x, (double)y);
                    if (y % 2 == 0)fprintf(fp2, "%lf  %lf\n", (double)x + 0.5, (double)y);
                }
            }
        }
        fclose(fp2);
    } //time

    //  ファイルへ結晶化したセルの位置座標を出力する
    for (x = 1; x < (X-1); x++){
        for (y = 1; y <(Y-1); y++){
            if (cell[x][y] != 0){
                if (y%2!=0)fprintf(xy, "%lf  %lf\n", (double)x, (double)y);   // yが偶数番ならば、(x,y)を出力
                if (y%2==0)fprintf(xy, "%lf  %lf\n", (double)x + 0.5, (double)y);     // yが奇数番ならば、(x+0.5,y)を出力
            }
        }
    }
} // main

結果

次のGIFがプログラムによって作成した雪の結晶の成長シミュレーションである。
 ANIMA.gif