Boardクラス, Boardcanvasクラス

このページでは、「詰めオセロ」、「拾い碁」、「梅花碁」、「8Qeenゲーム」、「面積最大の領域」、「数独」などで共通して利用する予定のクラスの説明をしています。
「詰めオセロ」「梅花碁」などのプログラムは、すべて2次元の盤データを扱います。この盤データを扱うクラスを毎回毎回作成していては、手間ですし、似たようなでもそれぞれが微妙に違うクラスがたくさん出来てしまうため、共通で利用できる Boardクラスとその描画を受け持つBoardCanvasクラスを作成することにしました。

作成したのは、以下のクラスとインターフェースです。

■Board.cs
Board 2次元の盤を扱うクラス
Location ボード上の位置を示す
BoardChangedEventArgs 盤に変化があった時に発生するイベントの EventArgs
IPiece Boardにおける駒を示すインターフェース
IColorPiece 色を持つ駒を示すインターフェース
BlackPiece 黒石
WhitePiece 白石
GuardPiece 番兵用の石
EmptyPiece NullObject (何も置かれていないことを示す)
Pieces 良く利用する上記4つのPieceのインスタンスを保持
BoardCanvas 描画を受け持つクラス (Boardの内容を可視化する)
BoardType 罫線の上に石を置くか罫線の間に石を置くかを示す

■BoardCanvas.cs
BoardCanvas 描画を受け持つクラス (Boardの内容を可視化する)
BoardType 罫線の上に石を置くか罫線の間に石を置くかを示す

中心的なクラスは、BoardクラスとBoardCanvasクラスです。
Board.csは、usingで名前空間だけ変更すれば、WindowsFormsやコンソールアプリでも利用できます。
実際、Board.csのデバッグは、コンソールアプリで行いました。
描画を受け持つBoardCanvas.csは、Silverlight専用のクラスになっています。

■Boardクラス

Boardクラスは、盤データを表すクラスです。内部ではデータは、2次元配列ではなく、一次元配列を使っています。
なお、盤の周り(四方)に番兵を置いています。これにより範囲外かどうかの判断を簡単に出来るようにしています。

この配列の要素には、IPieceインターフェースを実装したクラスインスタンスが格納されます。
この要素にアクセスする方法は、様々な問題に対応できるように、位置情報は、Location型、1次元配列、2次元配列の3つを用意しています。
X座標、Y座標は、0 からではなく、1から始まります。
つまり、board[1,1] は、いちばん左上を示し、8×8の盤ならば、board[8,8]が右下を示すことになります。



上の図は 4×4の盤を表していますが、グレー部分が番兵が置いてある盤の周囲で、水色部分が実際の盤です。数値は、1次元配列のインデックスとなります。

例えば、


のようなアクセスができます。その問題を解くのに都合の良いアクセス方法を選べるようにしています。

なお、Boardクラスを利用するプログラムの多くは、Location によるアクセスか、1次元のインデックスによるアクセスを行っています。一重ループで処理が書けるので、コードが簡潔になるからです。
また、空いている箇所を全て取得するメソッドや、指定した種類の駒が置いてある箇所をすべて取得するメソッドなどは、戻り値を IEnumerable<int>, IEnumerable<Location> とすることで、LINQのメソッドが利用できるようにしています。
例えば、空いている箇所を全て取得するメソッド では、


の2つを用意しています。IEnumerable<T>が戻り値ですから、


とすれば、駒が置かれていない座標を列挙できます。

具体的に、どのようなメソッド、プロパティが用意されているかは、当ページの最後に掲載するソースコードを見てください。簡単なコメントもつけていますし、ひとつひとつのメソッドは短いですから、読み解くのに時間はかからないと思います。

ただし、様々なプログラムから利用されることを想定しているので、メソッド、プロパティを盛り込みすぎたかもしれません。もしかしたら使われない機能もあるかもしれないです。

Boardクラスは、Silverlightに依存しない作りになっています。

■BoardCanvasクラス

Boardおよび駒(PIece)の表示を担当するクラスです。
中心的なメソッドは、DrawRuledLines と UpdatePiece です。

DrawRuledLinesは、罫線を引くメソッドです。碁盤タイプ(罫線が交わったところに駒を置く)か、チェスタイプの2つのモードがあります。

UpdatePieceは、指定した位置の駒の描画/消去を行うメソッドです。UpdatePieceは、関連づけされた Boardオブジェクトに変化があったときに、呼び出されます。
BoardCanvasが描画できるのは、IColorPieceを実装したクラスだけです、それ以外の IPieceクラスについては、BoardCanvas を継承したクラスを定義し、DrawPieceメソッド(UpdatePiece から呼び出される)を overrideする必要があります。

なお、プログラムで解を求めている間(Boardオブジェクトの内容が頻繁に更新されている間)は、UpdatePieceを呼び出す必要はないので、Synchronizeプロパティを用意し、trueの時だけ、Boardオブジェクトと同期するようになっています。
求まった解を表示(盤の状態を表示)するため、強制的にBoardオブジェクトの状態を反映させるには、Invalid()メソッドを呼び出します。

BoardとBoardCanvasの一部の動きを確認するための簡単なデモプログラムを作成していました。
以下がそのプログラムです。デモプログラムのソースコードはこちらにあります。

盤上をクリックすると、黒 → 白 → 消去 を繰り返します。


各プログラムで共通で利用するBoard.csとBoardCanvas.csのソースコードは、GitHub - gushwell/GushwellEtudes/BoardDemoで公開しています。なお、公開しているソースはSilverlightではなくWPF用のコードです。