セルオートマトンでシミュレーションをしよう(4)

4. Game of Life (2)

引き続き、Game of Lifeにグラフィクスを追加する。

グラフィックス版プログラム例

計算部分に変更すべき点は特になく、適当な場所に画面に表示するプログラムを付け加えるだけであるから、変更は簡単だろう。たとえば以下のようなプログラムを書けばよい。少々長いが、これまでに説明したことの寄せ集めであり、小さい部分の組み合わせなので上から順に読んでいけばわかると思う
#include<stdio.h>
#include<eggxlib.h>
#include<stdlib.h>
#define NX 200
#define NY 100
#define EDGE 4
main()
{ 
  int s[NX+2][NY+2], snew[NX+2][NY+2];
  int rule[2][9];
  int x,y,i;
  int step,rseed;
  int state,sum;
  int win;

/* preparation for graphics */
  win=eggx_gopen(NX*EDGE,NY*EDGE);
  eggx_window(win,1,1,NX,NY);
  eggx_gsetbgcolor(win,"white");
  eggx_newcolor(win,"blue");
  eggx_layer(win,0,1);

/* set rule */
  for(i=0;i<9;++i)rule[0][i]=rule[1][i]=0;
  rule[0][3]=1;
  rule[1][2]=rule[1][3]=1;

/* input step and rseed */
  scanf("%d%d",&step,&rseed);
  srandom(rseed);

/* set random initial state */
  for(y=1;y<NY+1;++y){
   for(x=1;x<NX+1;++x)s[x][y]=random()%2;
  }
/* transfer boundary */
  for(x=1;x<NX+1;++x){
   s[x][0] = s[x][NY];
   s[x][NY+1] = s[x][1];
  }
  for(y=0;y<NY+2;++y){
   s[0][y] = s[NX][y];
   s[NX+1][y] = s[1][y];
  }

/* display initial state */
  gclr(win);
  for(y=1;y<NY+1;++y){
   for(x=1;x<NY+1;++x)if(s[x][y]==1) eggx_fillrect(win,x,y,1,1);
  }
  eggx_copylayer(win,1,0);


  for(i=0; i<step; ++i){
/* start one step */
     for(y=1;y<NY+1;++y){
      for(x=1;x<NX+1;++x){
/* one site */
        state=s[x][y];
        sum=s[x-1][y-1]+s[x-1][y]+s[x-1][y+1]
           +s[x][y-1]+s[x][y+1]
           +s[x+1][y-1]+s[x+1][y]+s[x+1][y+1];
        snew[x][y]=rule[state][sum];
     }}
/* transfer snew[][]  to s[][] */
     for(y=1;y<NY+1;++y){
      for(x=1;x<NX+1;++x)s[x][y] = snew[x][y];
     }
/* transfer boundary */
     for(x=1;x<NX+1;++x){
      s[x][0] = s[x][NY];
      s[x][NY+1] = s[x][1];
     }
     for(y=0;y<NY+2;++y){
      s[0][y] = s[NX][y];
      s[NX+1][y] = s[1][y];
     }

/* display one step */
      eggx_gclr(win);
      for(y=1;y<NY+1;++y){
       for(x=1;x<NX+1;++x) if(s[x][y]==1) eggx_fillrect(win,x,y,1,1);
      }
     eggx_copylayer(win,1,0);
     eggx_msleep(10);
/* end of one step */
  }
}
例によって double bufferingを使い、1ステップごとにグラフィックスを表示させるだけである。1次元CAとの違いは、2次元の盤面なので各ステップごとに盤面全体を描き換えることだが、1次元よりこちらのほうがむしろわかりやすいと思う。各ステップごとにまずgclrで全体を背景色(白)で塗りつぶしたのち、値が1であるセルについてだけ青い正方形を描いている。なお、1セルの辺の長さをEDGEとして、windowを使ってそれが1になるような長さの単位に変更してある。これをするかどうかは好き好き。
次へ