NSSetとライフゲーム(その4、セルの保持) [プログラミング - NSSetとライフゲーム]
ライフゲームの続き。
前回作ったGoLAliveCellを生きているセルとして保持するNSSetを持っているクラスをGoLSparseGameOfLifeとする。ヘッダの最初は
@interface GoLSparseGameOfLife : NSObject { NSMutableSet *aliveCells; int generation; } - (id)initCells:(NSArray *)pointArray; - (int)generation; - (int)numberOfServives; - (BOOL)evolve; ...
みたいな感じ。セルを保持するNSMutableSetと世代数をインスタンス変数に持つ。
初期化は座標値GoLPointをNSValueに入れたNSArrayであるpointArrayを貰ってその位置のセルを生成してSetに詰める。numberOfServivesと言うメソッドは名前の通りでSetの要素数を返すだけである。
evloveメソッドが動作の中心となる。これが呼ばれるとひと世代進めたセルに中身を書き換えてgeneration変数を一つインクリメントする。次の世代が生成できたときevolveメソッドがYESを返す。次の世代が生成できなかったときNOを返すが、今回の実装ではこれはセルが全部死に絶えるか変化が無いときだけである。本当なら準定常状態でもNOを返すべきだろうけどチェックが難しい。
簡単な表示のためにGoLSparseGameOfLifeを継承したGoLSparseGameOfLifeWithImageを用意することにした。生きているセルの位置をドットで表したNSImageを返すimageメソッドを持つ。
他のメソッドもちょっと必要なのでヘッダを書くと
@interface GoLSparseGameOfLifeWithImage : GoLSparseGameOfLife { GoLPoint origin; unsigned int *cTable; unsigned int numberOfColors; float enlargeRatio; } - (id)initCells:(NSArray *)pointArray withColorTable:(GoLColorTable *)colorTable; - (void)setColorTable:(GoLColorTable *)colorTable; - (NSImage *)image; - (void)setEnlargeRatio:(float)ratio; - (float)enlargeRatio; ...
と言う具合。imageメソッドで、生きているセルに対応する位置にドットを置いたNSImageを返す。ドットの色を生き残り世代数に合わせて表示する場合、GoLColorTableを生成して渡す。セル一つで1ドットになるのでゴミみたいだけど簡単なので。もっと見栄えのいいものにしたければ他のサブクラスにすれば良い。僕はもういいや、これで。
この程度なら継承を使わなくてもたいしたことは無いし、Objective-Cの流儀ではあまり深い継承関係は使われないが、わかりやすさを優先してこうしましょう。
originは初期データの中心を保持する。cTableとnumberOfColorsはカラーテーブルから変換した内部データ。enlargeRatioはNSImageのサイズを指定するためのもの。
最初、生きているセルを含む最小の長方形のビットマップを作って表示することを考えた。ところがそれを使って描いてみると端にあるセルが生まれたし死んだりするたびに表示される位置が動いて見にくいことおびただしい。かといってあまり難しいことはしたくないので、とりあえず(こればっかだな)初期データの中心の位置が常に中心になるようなすべての生きているセルを含む長方形(bounds)を返すことにした。これで表示はちらちらしなくなった。そのためにoriginを保持する。このoriginはNSViewなどであるような右下隅ではない。
初期化は親クラスの初期化にカラーテーブルを追加したもの。colorTableにnilが渡るとクラッシュするのでカラーテーブルが無い場合は[[[GoLColorTable alloc] init] autorelease]を必ず渡すことにする。
次回はカラーテーブルをどうしようか考えるつもり。
コメント 0