2.1 生命体クラス 1999/03/11(初版) アイデアは前述のC言語の場合と同じです。生命体が棲息するフィールドを、たとえ ば40×40の正方形の碁盤の升目とすると、その2次元配列配を用意します。ただし、 各配列要素は生命体を表現するクラスのオブジェクトへのポインタです。生命体クラス は、フィールドの位置と状態(生か死か)の属性を持ちます。これらを privateなデー タメンバーとし、データの値にはpublicメンバー関数を介してアクセスします。
#include <iostream.h> #include <time.h> #include "glibw32.h"// グラフィックス・クラスライブラリ GLIBW32 const int N = 40; // 正方形の升目の数 class life; // 前方宣言 typedef life* field[N][N]; enum state{ DYING, LIVING, STATES }; // 状態 // 生命体クラス class life{ public: life( int r, int c, state s = DYING ) // コンストラクタ { row = r; col = c; state_now = s; state_next = DYING; } state getstate() const { return state_now; } //状態識別 void next(field w); void active() { state_now = LIVING; } void update() { state_now = state_next; } private: int row, col; // 位置 state state_now; // 現在の状態 state state_next; // 次の世代 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() ]--; // 自分の状態は数えない } |
// 次の世代の状態を決定する void life::next(field w) { int sum[STATES]; count(w, sum); // 隣の状態を数える if(state_now == LIVING){ // 現在生きている if(sum[LIVING] == 2 || sum[LIVING] == 3) state_next = LIVING; else state_next = DYING; } else{ // 現在死んでいる(あるいは空) if(sum[LIVING] == 3) state_next = LIVING; else state_next = DYING; } } |
// オブジェクトの生成 void init(field w) { for(int i = 0; i < N; ++i) for(int j = 0; j < N; ++j) w[i][j] = new life(i,j); } |
// 生命体の初期設定 void create(field w, int i, int j) { // 生命体の生息パターン w[i][j+1]->active(); w[i-1][j]->active(); w[i][j]->active(); w[i+1][j]->active(); w[i+1][j-1]->active(); } |
// 世代交代 void update(field w) { int i,j; // 境界を避ける for(i = 1; i < N-1; ++i) for(j = 1; j < N-1; ++j) w[i][j]->next(w); // 次の世代を求める for(i = 1; i < N-1; ++i) for(j = 1; j < N-1; ++j) w[i][j]->update(); // 世代交代 } // 描画関数 void draw(GRAPH *g, field w) { g->cls(); // 画面消去 for(int i = 0; i < N; ++i) for(int j = 0; j < N; ++j){ if(w[i][j]->getstate() == LIVING) // 生きているなら描画する g->frectangle(i*10+3,j*10+3,i*10+7,j*10+7, WHITE); } Sleep(100); // 遅延関数(100ミリ秒間停止する) } |
// オブジェクトの削除 void dele(field w) { for(int i = 0; i < N; ++i) for(int j = 0; j < N; ++j) delete (w[i][j]); } |
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; } |
実行ファイルとソースファイルのダウンロードはこちらです、
ライフゲーム (1)
実行ファイルとソース・ファイル Windows 95/ 98上で動作します。 |
life01.lzh (47KB) |
* このソフトウェアは、SYMANTEC. NORTON AntiVirus 5.0 でウィルス検査を 行っています。 * ファイルは吉崎栄泰氏による LHA (Copyright(c)1988-92 H.Yoshizaki)を 使って圧縮しています。
Copyright(c) 1999 Yamada,K