/**************************************************************
*  ライフ・ゲーム (2) 継承を使う                           *
*   LIFE02  ver 1.0                                           *
*  Copyright(c) 1999 Yamada,K    (1999.03.07)                 *
*                                                             *
*  スペースキーで終了する                                     *
***************************************************************
*/
#include <iostream.h>
#include <time.h>
#include "glibw32.h"// グラフィックス・クラスライブラリ GLIBW32

const int N = 40; // 正方形の升目の数
enum state{ DYING, LIVING, STATES};

class life; // 前方宣言
typedef life* field[N][N];

// 生命体の抽象クラス
class life{
    public:
        virtual state getstate() const = 0;  //状態識別
        virtual life* next(field) = 0;       //次の状態
        virtual void draw(GRAPH *) = 0;      //描画
    protected:
        int row, col; // 位置
        void count(field w, int sum[]) const;
};

// 隣接した生命体の状態をカウント
void life::count(field w, int sum[]) const
{
    sum[DYING] = sum[LIVING] = 0;
    for(int i = -1; i <= 1; ++i)
        for(int j = -1; j <= 1; ++j)
            sum[w[row + i][col +j]->getstate()]++;

    sum[w[row][col]->getstate()]--; // 自分の状態は数えない
}


// 生きている生命体のクラス
class living : public life{
    public:
        living(int r, int c) { row = r; col = c; }
        state getstate() const { return LIVING; }
        life* next(field);
        void draw(GRAPH *);
};

// 死んでいる生命体のクラス
class dying : public life{
    public:
        dying(int r, int c) { row = r; col = c; }
        state getstate() const { return DYING; }
        life* next(field);
        void draw(GRAPH *) { }
};

// 次の世代の状態を決定する
life* living::next(field w)
{
    int sum[STATES];

    count(w, sum);
    if(sum[LIVING] == 2 || sum[LIVING] == 3)
        return (new living(row, col));
    else
        return (new dying(row, col));

}

// 次の世代の状態を決定する
life* dying::next(field w)
{
    int sum[STATES];

    count(w, sum);
    if(sum[LIVING] == 3)
        return (new living(row, col));
    else
        return (new dying(row, col));
}

// 描画
void living::draw(GRAPH *g)
{
    g->frectangle(row*10+3,col*10+3,row*10+7,col*10+7, WHITE);
}


// オブジェクトの生成
void init(field w)
{
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < N; ++j)
            w[i][j] = new dying(i,j);
}

// 生命体の初期設定
void create(field w, int i, int j)
{
    // 生命体の生息パターン
    delete(w[i][j+1]);
    w[i][j+1] = new living(i,j+1);
    delete(w[i-1][j]);
    w[i-1][j] = new living(i-1,j);
    delete(w[i][j]);
    w[i][j] = new living(i,j);
    delete(w[i+1][j]);
    w[i+1][j] = new living(i+1,j);
    delete(w[i+1][j-1]);
    w[i+1][j-1] = new living(i+1,j-1);
}

// 世代交代
void update(field w)
{
    field w_temp; // 一時的なポインタ
    int i,j;

    // 次の状態を一時的に記憶
    for(i = 1; i < N-1; ++i)
        for(j = 1; j < N-1; ++j)
            w_temp[i][j] = w[i][j]->next(w);

    for(i = 1; i < N-1; ++i)
        for(j = 1; j < N-1; ++j){
            delete(w[i][j]);        // 古い状態を削除
            w[i][j] = w_temp[i][j]; // 新しい状態をコピー
        }

}

// オブジェクトの削除
void dele(field w)
{
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < N; ++j)
            delete (w[i][j]);
}

// 描画関数
void draw(GRAPH *g, field w)
{
    g->cls();
    for(int i = 0; i < N; ++i)
        for(int j = 0; j < N; ++j)
            w[i][j]->draw(g);
    Sleep(100); // 遅延関数(100ミリ秒間停止する)
}


int main()
{
    int no;
    cout << "このライフゲームは、あらかじめ決まったパターンの配置(種)\n"
    << "から開始します。それぞれの種の中心位置は乱数で決定します。\n"
    << "スペースキーで描画を終了します。\n\n"
    << "種の個数を入力してください:";
    cin >> no;
    ginit( N*10, N*10 ); // グラフィックスの初期化

    GRAPH g; // GRAPH オブジェクトの生成
    field w;
    init(w); // life オブジェクトの生成

    time_t t;
    srand((unsigned) time(&t));	//乱数の初期化

    if(no < 1) no = 1;
    while(no--){
        int i = rand() % (N-5) + 3;
        int j = rand() % (N-5) + 3;
        create(w, i, j); // 生命体の設定
    }

    while( vkey()  != VK_SPACE ){ // スペースキーが押されるまで
        draw(&g, w);
        update(w); // 世代交代
    }
    dele(w); // life オブジェクトの削除

    gend(); // グラフィックスの終了

    return 0;
}


| 戻る |

Copyright(c) 1999 Yamada,K