C#で迷路をつくります。

考え方は

等間隔に点をつくる。
出発点から別の点に移動する。すでに通過した点には移動できないとする。
移動できる点がない場合は一つ前に戻って移動できる点があるか探す。
移動できる点が見つからない場合は見つかるまで遡って探す。
すべての点を通過したら終了。

ではさっそくこのようなクラスを作成してみましょう。

以下は移動できる方向を示す列挙体です。

分岐点を管理するBranchPointクラスの作成

分岐点を管理するBranchPointクラスを作成します。

コンストラクタではその分岐点は左から何列目か(0からはじまる)、上から何行目か(0からはじまる)、分岐点と分岐点の間隔、描画するときに左と上にどれだけマージンをとるかを指定します。

Usedプロパティはその分岐点は使用されているかどうかを示します。すべてが使用されているのであれば迷路は完成していることになります。Pointプロパティは分岐点が存在する座標、MoveDirectsプロパティはその分岐点から移動できる方向を示します。

分岐点と分岐点をつなぐ線分を描画するためのLineクラス

次に分岐点と分岐点をつなぐ線分を描画するために必要な座標を管理するLineクラスを示します。

コンストラクタはふたつの点の座標です。

迷路を生成するMaseGeneratorクラス

次に迷路を生成するMaseGeneratorクラスを示します。

コンストラクタは分岐点が全部で何列存在するか、何行存在するか、それぞれの間隔、左側のマージン、上側のマージンを指定します。

最初にcolumMax列でrowMax行の分岐点を生成します。そして最初の現在位置を中心にある分岐点にします。現在位置はすでに使用されているのでBranchPoint.Usedプロパティをtrueにします。そしてConnectedPointsのなかに格納します。これは中心から繋がっている分岐点のリストです。最後にCreateMazeメソッドを呼び出して迷路をつくっていきます。

ColumMaxプロパティとRowMaxプロパティは迷路を構成する分岐点が何列、何行存在するかを示します。BranchPointsプロパティはすべての分岐点のリスト、Linesは分岐点の座標のペアを示します。

CreateMazeメソッドは迷路をつくります。まずConnectedPointsの最後にある要素を調べて移動できる方向がいくつあるか調べます。これが0の場合は移動できないということなので、ConnectedPointsの最後にある要素は取り除いて過去に通過した分岐点に遡って移動できる分岐点が存在するところまで戻ります。

現在位置が移動できる方向が存在する分岐点である場合は移動する方向を乱数で求めてその方向に移動します。

NumberOfRecursionプロパティはCreateMazeメソッドを再帰呼び出しした回数です。

MovePointメソッドは現在位置から移動できる点があるかどうか探し、存在する場合は移動してtrueを返します。存在しない場合はfalseを返します。

GetMoveDirectメソッドは引数として渡された分岐点から移動できる方向のリストを返します。このリストが空ならここから移動できる点は存在しないということになります。

CanMoveLeftメソッドは引数として渡された分岐点から左に移動できるかどうかを返します。引数として渡された分岐点のColumプロパティが0であればここが左端なので移動できないということになります。_branchPointsからColumプロパティが1小さい分岐点を探して、そこが使用されていないのであれば移動可能であるといえます。

MoveLeftメソッドは実際に現在位置を左に移動します。まずここから左に移動可能であるという情報を現在位置の分岐点に追加します。また移動先の分岐点にもここから右、すなわち移動元に移動できるという情報を追加します。

そして現在位置のUsedプロパティをtrueにします。そして現在位置をConnectedPointsに格納します。最後に分岐点同士を線分でつなぐことができるように両分岐点の座標のペアを_linesに格納します。

上に移動できるかを調べる処理と実際に上に移動する処理を示します。

右に移動できるかを調べる処理と実際に右に移動する処理を示します。

下に移動できるかを調べる処理と実際に下に移動する処理を示します。

仕上げ

Form1クラスはどのようにすればいいのでしょうか?

MaseGenerateメソッドでMaseGeneratorのインスタンスを生成します。何度でも生成できるようにメニューも追加します。

描画するときは以下のようにします。

これで迷路を生成して描画することができました。

次回:ゲームとして遊べるようにする C#で迷路をつくる(2)