単なる長方形ではなく、複雑な形をした領域の「塗りつぶし」を行うアルゴリズムを考えてみます。ここで考える領域とは、「指定された点と繋がっている同じ色の場所の集合」であり、その領域内に指定された色を置いて行くアルゴリズムを検討してみましょう。 最初はそもそもJava で再帰が上手く働くか不安だったのですが、小さい領域ではうまく動くようです。最も、大きくなるとどうなるか不安は残りますが。 まず、配列の各要素を0が白で1が黒、2を赤に対応させます。つまり、画面にこの配列の様子を表示する時には0なら白、1なら黒、2なら赤という風に表示するわけです。配列の大きさは32*32ですが、隅の1ドットは3(青)で囲っておき、塗りつぶしの出発点は(16、16)という事にしました。 自分の周囲を見て出発点と同じ色なら塗りつぶす処理をする、というのは上下左右を見て出発点と同じ要素があれば、それを指定された数値に書き換える、というアルゴリズムになります。
という関数を初めにfill(16,16)と呼び出せば良い事になります(cl が最初(16、16)にあった数値)。この関数を一度呼び出せば、連続する領域内を再帰的に走査して、すべて塗り終えた(領域内に最初の色がなくなった)段階で関数は終了するからです。このアルゴリズムの処理を、図で考えてみましょう。 まず、(1)では緑色で示した出発点(白だったとします)が塗りつぶされ、ー1(赤で表示)になります。次に、その上を見ると「出発点と同じ色」(if (dot[x][y-1]==cl))という条件を満たすので、そこの座標を引数に自分自身を再度呼びました。すると、その座標も塗りつぶされ(2)、if 文の条件が調べられます。 と、このように次々に領域が走査され塗りつぶされるわけです。こうして領域がすべて塗りつぶされると関数は終了し、呼び出し元へ順次帰っていきます(これが再帰の終了条件)。帰って行く過程ではすでに領域内のすべての点が出発点とは異なるー1になっているので、関数内のif 文はすべて偽となり再び自分自身を呼び出す事はあり得ません。 プログラムでは、32*32のマス(2次元配列 dot[x][y])の各要素を表示してあります。グラフ内の点をクリック・ドラッグすると値を変えられるので、適当な領域を作ったらG o ボタンで塗りつぶしてみましょう。 |