迷路を自動で作って、自動で解く、そんなプログラムを作りたいと前々から思っていました。

試行錯誤しながら作ってみると、なんと、作るのも解くのも同じアルゴリズムでできることが分かりました。

youtube 動画にもupしました。こちらは迷路のサイズを変えながら、迷路を作って、それを解く、を繰り返します。

プログラムは、こちら
https://github.com/itoshin-tech/maze

迷路を生成する方法

それでは迷路を作る方法を説明します。まず、fieldという2次元の配列変数を考え、ここに道を作っていくとします。

fieldの要素は初めは全て0です。0をブランクと呼ぶことにします。ここに、道のid(2, 3, 4…)で書き換えることで道を作っていきます。idが2からなのは、迷路を解く方法と整合性を得るためで深い意味はありません。

まず、スタート地点をランダムに決め、その要素を2にします。そして、上下左右方向に一つ飛ばした先のセルを調べます。セルがブランク(0)であれば、そちらに道を伸ばすことができます。進める方向が複数ある場合には、ランダムで1つの方向を選びます。

選んだ方向に進みます。伸ばした道にはidである2を代入します。ここからまた同様に、4方向を調べ、ブランクの方向に道を伸ばします。

これを繰り返しながら道を伸ばしていきますが、いずれ進めなくなります。

進めなくなったら、作ってきた道で、分岐方向を選んできた座標を確認します(オレンジの枠)。そして、矢印で示した(x=1, y=5)の位置から分岐を伸ばそうと考えます。

ここで少しプログラムのことを考えます。

作る関数は、以下のようなfill_with_road()という関数です。この関数は、(x, y)の地点から道を伸ばし、0の領域を道で満たす、という働きを想定しています。

はじめから考えて、x=3, y=3 のスタート地点をセットして、fill_with_road(x=3, y=3, id)を実行したと想定します。そして、はじめの一本道を伸ばし終えて、(x=1, y=5)から分岐を伸ばすフェーズになっているとします。まだ、fill_with_road(x=3, y=3, id)の中です。

(x=1, y=5)から分岐を作るために、この箇所をスタート地点としたfill_with_road(x=1, y=5, id=id+1)を実行します。idは今のidから一つ増やすします(id を変えるのは単にアルゴリズムの動きを知るためです)。しつこいようですが、これはfill_with_road(x=3, y=3, id)の中で実行します。

同様に、fill_with_road(x=3, y=3, id)の中で、全ての分岐ができる可能性のあるオレンジの箇所から、fill_with_roadを実行します。

これでアルゴリズムの概要は終わりです。

このようにすることで、分岐の先でも、さらなる分岐が起き、その先でも分岐を起こすことができるのです。理論上は、何段階でも分岐を起こすことができるのです。

ややこしいのですが面白いですよね。このように、関数の中で自分自身の関数を呼ぶ方法を再帰と呼びます。

今の例の続きを考えると、3の道が作られ、更に下のオレンジの枠で分岐が起こり、4の道が伸びていきます。ここで新しい道を作るスペースがなくなるので迷路が完成します。

あとは、field の要素で1以上の部分を全て1に直して迷路が完成です。

1を迷路の道、0を壁と解釈します。スタート地点とゴール地点はどこにおいても成り立ちます。

実は、迷路を解くときにもfill_with_road()が使えます。1の部分をbrankと解釈し、そこに道を充填していけばよいのです。

迷路を解く方法

迷路を解く方法です。左上がスタート、右下がゴールだとします。今度は、1をブランクとします。1の上にid=2, 3, 4, … の道を作っていくことを考えます。

迷路生成時ではブランクの空間は広い長方形でしたが、今回のブランクは迷路のくねくねした廊下の形状です。しかし、fill_with_roadは、単に隙間があったらそこに道を伸ばしていくアルゴリズムなので、ブランクの形状には関係なく動作します。

よって、ここでも、迷路生成時とほとんど同じアルゴリズムで道を伸ばしていけば、いつかゴールにまで道(?)が到達します。

ただし、前回使ったfill_with_roadの以下の部分だけ、変更します。

隣り合った4方向でbrank=1の方向に道を進めます。行ける方向が分かったら、2マス進めます。この要領で道を長くしていきます。

結果、以下のような行き止まりにたどり着きました。ここからは、方向を決定した箇所全てにおいて分岐を試します。

分岐をするときにはidに1を加えるとすれば、以下のような道が生成され、ゴールにたどり着くことができます。

以上で迷路の作り方・解き方の説明は終わりです。読んでいただきありがとうございました。

プログラムは github にもupload しています。
https://github.com/itoshin-tech/maze

ファイルは1つなので以下にも出しておきます。