ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

ライフゲームコミュのC言語でライフゲームを作る

  • mixiチェック
  • このエントリーをはてなブックマークに追加
C言語でライフゲームを作りたいと考えているのですが、

プログラムは苦手でどんな風に作ったらいいのかさっぱりわからないのです。

そこでみなさんにお願いなのですが、

ライフゲームのC言語での作り方を教えていただけないでしょうか?

どうぞよろしくお願いします。

コメント(44)

僕はCは10年ぐらい触ってないので所々修正が必要だと思いますが…。
骨組みはこんな感じで、これに境界条件とか描画処理とか足していけばいいと思います。


void main()
{
  int field1[100][100];
  int field2[100][100];
  int i,j,k;
  int x,y;
  int cnt;

  /* 初期値設定 */
  for(i=0;i<100;i++){
    for(j=0;j<100;j++){
      /*生存セルをランダムに設定(2割)*/
      if(rand()%10<2){
        field1[i][j]=1;
      }else{
        field1[i][j]=0;
      }
    }
  }

  /*無限ループ*/
  while(1){
    /*表示*/
    for(i=0;i<100;i++){
      for(j=0;j<100;j++){
        /*前回の状態を保持*/
        field2[i][j]=field1[i][j];
        /*ライフが1なら…*/
        if(field1[i][j]==1){
          /*ここに描画処理*/
        }
      }
    }
    /*計算*/
    for(i=0;i<100;i++){
      for(j=0;j<100;j++){
        cnt=0;
        /*周囲8個+自分の状態を調査*/
        for(k=0;k<9;k++){
          x=i+k%3-1;
          y=j+k/3-1;
          /*境界条件=有限*/
          if(x>=0 && x<100 && y>=0 && y<100){
            if(field2[x][y]==1){
              cnt++;
            }
          }
        }
        /*周囲8個+自分の状態によって分岐*/
        switch(cnt){
          /*周囲2+自分1 or 周囲3+自分0 →生存*/
          case 3:
            field1[i][j]=1;
            break;
          /*周囲3+自分1 or 周囲4+自分0 →不変*/
          case 4:
            field1[i][j]=field2[i][j];
            break;
          /*それ以外は死亡*/
          default:
            field1[i][j]=0;
            break;
        }
      }
    }
  }
}
ィヶッィォさん>
なるほどこんな風に考えればいいのですね。
プログラムを実際に見せてもらうと理解しやすいです。
本当にありがとうございます。
>5: ィヶッィォさん

ィヶッィォさんのプログラムに付け足しです。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
と先頭に付ける。

rand() がある for 文の前に
srand(time(NULL));
を付け足し。

rand()%10<2
を
(double)rand()/RAND_MAX < 0.2
に変更。

この方がいい乱数だと思います。どうでしょうか??
Cの乱数よく知らなかったんで適当に書いちゃいました。笑
補足ありがとうございます!
>8: ィヶッィォさん

いえいえ、ィヶッィォさんこそプログラムをきちんと書いてくれて、ありがとうございます。

周期境界条件バージョン

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define XSIZE 100
#define YSIZE 100

int xindex(int index)
{
while (index < 0) {
index += XSIZE;
}
while (index >= XSIZE) {
index -= XSIZE;
}
return index;
}

int yindex(int index)
{
while (index < 0) {
index += YSIZE;
}
while (index >= YSIZE) {
index -= YSIZE;
}
return index;
}


void main()
{
  int field1[XSIZE][YSIZE];
  int field2[XSIZE][YSIZE];
  int i,j,k;
  int x,y;
  int cnt;

rand()%10<2

  /* 初期値設定 */
  for(i=0;i<XSIZE;i++){
    for(j=0;j<YSIZE;j++){
      /*生存セルをランダムに設定(2割)*/
      if((double)rand()/RAND_MAX < 0.2){
        field1[i][j]=1;
      }else{
        field1[i][j]=0;
      }
    }
  }

  /*無限ループ*/
  while(1){
    /*表示*/
    for(i=0;i<XSIZE;i++){
      for(j=0;j<YSIZE;j++){
        /*前回の状態を保持*/
        field2[i][j]=field1[i][j];
        /*ライフが1なら…*/
        if(field1[i][j]==1){
          /*ここに描画処理*/
        }
      }
    }
    /*計算*/
    for(i=0;i<XSIZE;i++){
      for(j=0;j<YSIZE;j++){
        cnt=0;
        /*周囲8個+自分の状態を調査*/
        for(k=0;k<9;k++){
          x=i+k%3-1;
          y=j+k/3-1;
          /*境界条件=周期*/
          cnt += field2[xindex(x)][yindex(y)];
        }
        /*周囲8個+自分の状態によって分岐*/
        switch(cnt){
          /*周囲2+自分1 or 周囲3+自分0 →生存*/
          case 3:
            field1[i][j]=1;
            break;
          /*周囲3+自分1 or 周囲4+自分0 →不変*/
          case 4:
            field1[i][j]=field2[i][j];
            break;
          /*それ以外は死亡*/
          default:
            field1[i][j]=0;
            break;
        }
      }
    }
  }
}
杵搗き餅@研究中さん、ィヶッィォさん>
御二方とも詳しく説明してくださってありがとうございます。
とりあえずあとは描画部分ですね。
私はCで簡単な文字を表示させることや計算した数字を表示することは習ったのですが、
今回のライフゲームように図(絵?)を描画するということを習っていないのです。
調べてもイマイチよくわからなくて;;
どうしたらいいんでしょうか??
>10: たっきーさん

C では、ちゃんとした絵を書くのは難しいですね。
ASCIIアートが限界じゃないでしょうか?
例えば、
1→*
0→半角スペース
というように表すとして、printf()関数で表示してはどうでしょう?

上記のソースの注意は、字下げを「全角スペース」で行っているので、実際に作るときにはタブに置き換えてください。
杵搗き餅@研究中さん>
なるほど、そういう手があるんですね。
今から試してみます。
全角スペースのことは自分もコンパイラを通してエラーが出て気がついたので修正してやっています。
描画処理部分を以下のようにしたのですが、これでいいのでしょうか?

/*表示*/
for(i=0;i<XSIZE;i++){
 for(j=0;j<YSIZE;j++){
  /*前回の状態を保持*/
  field2[i][j]=field1[i][j];
  /*ライフが1なら…*/
  if(field1[i][j]==1){
   /*ここに描画処理*/
   //1=*とする//
   printf("*");
  }else{
   //0= とする//
   printf(" ");
  }
 }
}
適当な位置に printf("\n"); を入れないと一行になっちゃう気が…
あと左上の開始座標も設定しなきゃいけないかなぁ
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define XSIZE 100
#define YSIZE 100

int xindex(int index){
 while(index < 0){
  index+=XSIZE;
 }
 while(index>=XSIZE){
  index-=XSIZE;
 }
 return index;
}

int yindex(int index){
 while(index<0){
  index+=YSIZE;
 }
 while(index>=YSIZE){
  index-=YSIZE;
 }
 return index;
}

void main(){
 int field1[XSIZE][YSIZE];
 int field2[XSIZE][YSIZE];
 int i,j,k,l;
 int x,y;
 int cnt;

/* 初期値設定 */
 for(i=0;i<XSIZE;i++){
  for(j=0;j<YSIZE;j++){
 /*生存セルをランダムに設定*/
   if((double)rand()/RAND_MAX < 0.2){
    field1[i][j]=1;
   }else{
    field1[i][j]=0;
   }
  }
 }

/*無限ループ*/
 while(1){
 /*表示*/
  for(i=0;i<XSIZE;i++){
   for(j=0;j<YSIZE;j++){
  /*前回の状態を保持*/
    field2[i][j]=field1[i][j];
/*ライフが1なら…*/
     if(field1[i][j]==1){
/*ここに描画処理*/
//1→*とする//
      printf("*");
     }else{
//0→ とする//
      printf(" ");
     }
    }
    printf("\n");
   }

   /*計算*/
   for(i=0;i<XSIZE;i++){
    for(j=0;j<YSIZE;j++){
     cnt=0;
    /*周囲8個+自分の状態を調査*/
     for(k=0;k<3;k++){
      x=i+k%3-1;
      for(l=0;l<3;l++){
       y=j+l%3-1;
      /*境界条件=周期*/
       cnt += field2[xindex(x)][yindex(y)];
      }
     }
/*周囲8個+自分の状態によって分岐*/
     switch(cnt){
    /*周囲2+自分1 or 周囲3+自分0 →生存*/
      case 3:
       field1[i][j]=1;
       break;
    /*周囲3+自分1 or 周囲4+自分0 →不変*/
      case 4:
       field1[i][j]=field2[i][j];
       break;
    /*それ以外は死滅*/
      default:
       field1[i][j]=0;
       break;
     }
   }
  }
 }
}

自分なりに少し変えてみたのですが、どうでしょうか?
あと左上の開始座標の設定はどうすればいいのでしょうか?
ィヶッィォさん>
この部分で初期値設定はしているみたいですが、
これと左上の開始座標とは違うんですか?

/* 初期値設定 */
 for(i=0;i<XSIZE;i++){
  for(j=0;j<YSIZE;j++){
 /*生存セルをランダムに設定*/
   if((double)rand()/RAND_MAX < 0.2){
    field1[i][j]=1;
   }else{
    field1[i][j]=0;
   }
  }
 }
あっ、左上の開始座標ってのは、1度目の処理で文字("*"か" ")を100字×100行分出力するので、2度目の処理に行く前にまた最初の位置から出力させないと101行目からになっちゃうってことですあせあせ(飛び散る汗)
ィヶッィォさん>
その場合の処理はどうすればいいのでしょうか??
プログラムは本当に苦手で…。
すいませんが、ご指導の方よろしくお願いします。
>18: たっきーさん

とりあえず、描画する前に何個か改行を入れてはどうでしょう?
杵搗き餅@研究中さん>
改行は一箇所だけ入れてあるのですが、それでは不十分なのでしょうか??
>20: たっきーさん

見易ければ、好きな個数で良いですよ。
「何個か」=「1個以上」と考えてました。
杵搗き餅@研究中さん>
そうですか、わかりました。
あとはィヶッィォさんの指摘している2度目の処理の問題ですね。
どうしたらいいことやら。。。
このへんを参考にしたらいいかと思います
http://hp.vector.co.jp/authors/VA001944/c-begin/text07.html


てゆーか現時点でコンパイル実行するとどうなりますか?
現時点でコンパイル実行すると
*と半角スペースがランダム?に表示され無限ループします。
表示は100×100の枠に収まってますか?

脳内コンパイルで発言してるので僕の思い過ごしかもしれないです(--;)
とりあえずプロンプト画面には100字が入りきれていないので、
上下に80字と20字にわけて表示されていて、それが無限ループしています。

あと2次元のメッシュ(格子)の上にパターンを出力するように改造するにはどうしたらいいのでしょうか?
http://www.orchid.co.jp/computer/cgame/index.html

上記を参考にすれば2次元のメッシュの上にパターンを出力できるみたいなんですが、自分にはなんのことやらさっぱりで;;
本当にすいませんが、力をお貸しください。
■はみ出してしまうのであればXSIZEとYSIZEを適当な値に調整してみてください。
例)
#define XSIZE 20
#define YSIZE 20

■2次元のメッシュは、#defineで枠サイズを定義しておいて、
表示の際にgl_rectangleを使えばできるのかなぁ?
こんな感じでいけると思います。

例)
/*メッシュ枠のサイズ*/
#define RECTSIZE 5


/*表示*/
for(i=0;i<XSIZE;i++){
 for(j=0;j<YSIZE;j++){
  /*前回の状態を保持*/
  field2[i][j]=field1[i][j];
  /*ライフが1なら…*/
  if(field1[i][j]==1){
   /*ここに描画処理*/
   //1=塗りつぶしあり(白)の四角形//
   gl_rectangle(i * RECTSIZE, j * RECTSIZE, i * RECTSIZE + RECTSIZE, j * RECTSIZE + RECTSIZE, 1, 1, 65535, 65535);
  }else{
   //0=塗りつぶしなし(黒)の四角形//
   gl_rectangle(i * RECTSIZE, j * RECTSIZE, i * RECTSIZE + RECTSIZE, j * RECTSIZE + RECTSIZE, 1, 1, 65535, 0);
  }
 }
}
ィヶッィォさん>
上記でやってみたんですが、コンパイルエラーがでました。
どうもgl_rectangleの部分でエラーが出ているみたいです。
gl_rectangleはStudyCに付属してるライブラリなのかなぁ?
購入しなきゃいけないっぽいですね(--;)

ようは各格子の始点X座標(i*RECTSIZE)と始点Y座標(j*RECTSIZE)からそれぞれサイズを足した分(+RECTSIZE)まで四角を書くような処理を書いていけばOKです
「C言語 グラフィック」などで検索してみるといいかも。


"*"と" "を使うのを止めて"■"と"□"にしたら擬似的に格子っぽくなりますけどね・・・笑
StudyCを購入しなきゃいけないんですかね…。。。
前途多難;;
その処理をプログラムで書くと、どんなものになるんですか??
>32: たっきーさん

正直言うと、グラフィックにこだわるなら、C とは別の方法を考えた方がいいですよ。

gnuplot とかを使うのがいいのではないでしょうか?
杵搗き餅@研究中さん>
gunplotって言語使ったことが全くないんです。
他の言語だとどういうものがいいんでしょうか??
>34: たっきーさん

それぞれ、「gnuplot」「プログラミング言語 グラフィック」とかで、ググってみてください。
調べてみましたが自分には理解できないことばかりで。。。
今までに習ったのがCとJava、OpenGLしかないので
できればこの中のどれかを使ってライフゲームを作りたいのです。
今の時点で自分ができるプログラムはこの程度なので…。
この中のどれかを使ってライフゲームを作ることはできないでしょうか??
>36: たっきーさん

OpenGLって確か描画できましたよね?
そこを頑張っていくのが、いいのではないでしょうか?
わかりましたOpenGLに今までのプログラムを移植してみようと思います。
またわからないところがあれば質問したいと思いますので、
そのときはよろしくお願いします。
「ウェブ上のライフゲームに関する文章」のほうに昔書いたやつですが、
JavaScriptで作ったものがあるので紹介します。
http://shrine.cwdap.com/life/
VBで作ったスクリーンセーバーも落とせます。
>38: たっきーさん
>OpenGLに今までのプログラムを移植

それもいいかもしれませんが、OpenGL は C から使えますよ。

ログインすると、残り9件のコメントが見れるよ

mixiユーザー
ログインしてコメントしよう!

ライフゲーム 更新情報

ライフゲームのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。