/**************************************************************
* ライフ・ゲーム (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