1989年開業 情報工学部門 文部科学省登録番号 第22082号 公益社団法人日本技術士会会員 東大阪商工会議所会員

≫サンプルプログラム一覧 

オープンソース/C言語サンプルプログラム 粒子の凝集シミュレーション(アスキーアート)

※2021. 9.16 プログラムを訂正しました。(下から2行目)
   { printf("%.*s",XMAX,&buf[y][0]); } // 1行分表示
          ↓
   { printf("%.*s\n",XMAX,&buf[y][0]); } // 1行分表示

●粒子が一定のルールに従って凝集した様子を表示するプログラムです。
●ルールは次のとおりです。
 (1) 縦 YMAX 行、横 XMAX 桁の矩形領域を画面上に想定する。(配列 buf[][] で実装)
 (2) 粒子を領域の上端 (y=0) に一つ発生させる。桁位置 x は乱数によって決める。
 (3) 粒子は、下、右、左の方向にランダムに1コマずつ進む。
 (4) 粒子が領域の底か他の粒子に接したら、吸着されたとしてその位置に止める。
 (5) 粒子が領域の外に出たら、その粒子は終了とする。
 (6) あらかじめ決めておいた粒子の数だけ、(2)から(5)の操作を繰り返す。
 (7) すべての粒子の操作が終わったら、結果を画面に表示する。
●乱数の種にはtime関数で得られた時刻を使うので、実行するたびにちがうパターンになります。


≫ソースファイルのダウンロード: gyousyuu02.C
【問題】
●粒子を表す文字を '*' から他の文字に変更してみよう。
 ※文字によってはパターンが気持ち悪く感じられる場合があるので、敏感な方は注意してください。
●画面の行数や粒子の数を変えて試してみよう 。
●乱数の種を変数 seed ではなく、定数(0など)にすると、毎回同じパターンになることを確認しよう。
●乱数の種を定数にして粒子数を多くしていくと、途中からパターンが変わらなくなることを確認し、意味を考察してみよう 。
●粒子の進む方向を下だけに改造して、得られる結果を比較してみよう。
●変数 seed の値を画面に表示し、気に入ったパターンを再現できるように改造してみよう。

//  粒子の凝集シミュレーション(アスキーアート)
//  粒子は領域の上からランダムにやって来て下、左、右に移動する
//  粒子は領域の底に到達したら吸着する
//  粒子は他の粒子に接すると吸着する
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define  PMAX  300                                      // 粒子の数
#define  XMAX  80                                       // 水平方向MAX
#define  YMAX  20                                       // 垂直方向MAX

void  main( )
{
    unsigned long  seed;                                // 乱数の種
    char  buf[YMAX][XMAX];                              // 1画面分のマス
    char  pc='*';                                       // 粒子の文字
    int   n,x,y;                                        // 粒子位置
    int   ir;                                           // 吸着
    int   i;

    printf("粒子の凝集シミュレーション(AA)\n");

    memset(&buf[0][0],' ',XMAX*YMAX);                   // 配列を空白で初期化
    time(&seed);                                        // 時刻取得(秒)
    srand(seed);                                        // 乱数の種をまく

    for( i=0; i<PMAX; i++ )                             // 粒子発生
      {
        x=rand( )%XMAX; y=0;                            // 最初の位置

        if ( buf[y][x]==pc ) continue;                  // すでに粒子あり

        while( 1 )
          {
            ir=1;                                       // 吸着(仮)

            if ( y==YMAX-1 ) break;                     // 領域の底

            if ( buf[y+1][x]==pc ) break;               // 下に粒子あり

            if ( x<XMAX-1 )
              { if ( buf[y+1][x+1]==pc ) break; }       // 右下に粒子あり

            if ( x<XMAX-1 )
              { if ( buf[y][x+1]==pc ) break; }         // 右に粒子あり

            if ( x<XMAX-1 && y>0 )
              { if ( buf[y-1][x+1]==pc ) break; }       // 右上に粒子あり

            if ( y>0 )
              { if ( buf[y-1][x]==pc ) break; }         // 上に粒子あり

            if ( x>0 && y>0 )
              { if ( buf[y-1][x-1]==pc ) break; }       // 左上に粒子あり

            if ( x>0 )
              { if ( buf[y][x-1]==pc ) break; }         // 左に粒子あり

            if ( x>0 )                                  // 左下に粒子あり
              { if ( buf[y+1][x-1]==pc ) break; }

            ir=0;                                       // 吸着なし

            //--移動--
            n=rand( )%3;                                // 3方向

            switch( n )
              {
                case 0: y++; break;                     // 下
                case 1: x++; break;                     // 右
                case 2: x--; break;                     // 左
              }

            if ( y<0 || y>=YMAX ) break;                // 領域の外
            if ( x<0 || x>=XMAX ) break;                // 領域の外
          }

        if ( ir==1 ) buf[y][x]=pc;                      // 粒子吸着
      }

    //--結果表示--
    for( y=0; y<YMAX; y++ )
      { printf("%.*s\n",XMAX,&buf[y][0]); }             // 1行分表示
}
   

※SSL暗号化通信対応

佐伯英子技術士事務所 〒542-0073 大阪市中央区日本橋 1-14-13 サンオフィス日本橋601  E-mail: info@saeki-pe.com