どうも、還暦を前に迷えるプログラマKASAです。
今回はプログラムを作るということについて迷路脱出を使って考えてみます。
とりあえず動作するコードを載せていますので、難しく考えず、コピペで動かしてみてください。
迷路を抜け出す基本的な方法として
「右手(左手)を壁につけたまま進めば必ず出口(ゴール)に到着する」
というものがあります。
非常にシンプルですね
ではこれをExcelのマクロでプログラムにしてみましょう
Excelでボタンを1つ(「ボタン1_Click()」)配置して
以下のコードを追加します。
Sub ボタン1_Click()
Dim col
houkou (1)
now = 1
col = MICHI ‘デフォルト(白)
endFlg = False
Do While col <> GOAL
‘ 今の位置を確認
x = ActiveCell.Column
y = ActiveCell.Row
DoEvents
‘移動可能な方向を捜す
chk = checkX(now)
‘右いける
If chk = 1 Then
p = (now + 3) Mod 4
If p = 0 Then p = 4
houkou (p)
susumu (p)
‘前進できる
ElseIf chk = 0 Then
susumu (now)
‘どちらも無理なら進行方向を替える
Else
p = (now + 1) Mod 4
If p = 0 Then p = 4
now = p
houkou (p)
End If
‘ゴールしたか?
If ActiveCell.Interior.Color = GOAL Then
GoTo LOOP_E
End If
Loop
‘ 終わり
LOOP_E:
End Sub
その後
書き込んだボタンのコードの上にコードを追加して
全体として以下のようにします。
Dim tate As Integer
Dim yoko As Integer
Dim now As Integer
Dim endFlg As Boolean
Const MICHI As Long = 16777215 ‘色なし (道の色)
Const KABE As Long = 65535 ‘黄色 (壁の色)
Const GOAL As Long = 255 ‘赤色 (ゴールの色)
‘ 移動方向を決める
Sub houkou(muki As Integer)
If muki = 1 Then ‘下
tate = 1
yoko = 0
ElseIf muki = 2 Then ‘右
tate = 0
yoko = 1
ElseIf muki = 3 Then ‘上
tate = -1
yoko = 0
ElseIf muki = 4 Then ‘左
tate = 0
yoko = -1
End If
End Sub
‘移動可能な方向を捜す(右へ行ければ右、無理なら直進、どちらも無理)
Function checkX(muki As Integer) As Integer
Dim tateC
Dim yokoC
x = ActiveCell.Column
y = ActiveCell.Row
If muki = 1 Then ‘下なら左を見る
tateC = 0
yokoC = -1
ElseIf muki = 2 Then ‘右なら下を見る
tateC = 1
yokoC = 0
ElseIf muki = 3 Then ‘上なら右を見る
tateC = 0
yokoC = 1
ElseIf muki = 4 Then ‘左なら上を見る
tateC = -1
yokoC = 0
End If
houkou (muki)
col1 = Cells(y + tateC, x + yokoC).Interior.Color
col2 = Cells(y + tate, x + yoko).Interior.Color
‘ 右に進めるか
If col1 <> KABE Then
checkX = 1
‘ 進行方向に進めるか
ElseIf col2 <> KABE And col1 = KABE Then
checkX = 0
‘ どちらも無理
Else
checkX = -1
End If
End Function
‘ 進行方向に1つ進む
Sub susumu(muki As Integer)
x = ActiveCell.Column
y = ActiveCell.Row
‘ マーカー
If Cells(y + tate, x + yoko) = “” Then
Cells(y, x) = “・”
Else
Cells(y, x) = “”
End If
‘ 進む
Cells(y + tate, x + yoko).Select
now = muki
End Sub
‘ ===== この上に追加する =====
Sub ボタン1_Click()
Dim col
houkou (1)
now = 1
col = MICHI ‘デフォルト(白)
endFlg = False
Do While col <> GOAL
‘ 今の位置を確認
x = ActiveCell.Column
y = ActiveCell.Row
DoEvents
‘移動可能な方向を捜す
chk = checkX(now)
‘右いける
If chk = 1 Then
p = (now + 3) Mod 4
If p = 0 Then p = 4
houkou (p)
susumu (p)
‘前進できる
ElseIf chk = 0 Then
susumu (now)
‘どちらも無理なら進行方向を替える
Else
p = (now + 1) Mod 4
If p = 0 Then p = 4
now = p
houkou (p)
End If
‘ゴールしたか?
If ActiveCell.Interior.Color = GOAL Then
GoTo LOOP_E
End If
Loop
‘ 終わり
LOOP_E:
End Sub
次にシート上に迷路を作成します。
適当な範囲のセルを黄色で塗りつぶします。
その後塗りつぶしなしでルートを作ります。
ゴールは赤いセルにします。
大きさは自由です。
とりあえずルートを作って実行してみます。
スタートするセル(色なし)をクリックして「Start」ボタンを押します。
ただしループしている部分をスタートに指定すると、そこを回ってゴールできない可能性があります。
ループした状況を解除するにはGOAL(赤)の隣接の色なしセルをクリックしてください。
ルートが「・」で示されると思います。
上のは私が考えた方法です。
正しいかどうかは分かりませんし、見直してあまり出来の良いコードでないなと反省しています。
(まあゴールに到着するようなので良しとしてください)
他にも色々な方法がありますので、皆さんもチャレンジしてみてください。
プログラムを作るというのはこんな感じで、自分で理解した内容をコードにしていく作業です。
この迷路のアルゴリズムも聞くと簡単ですが、「右手を壁から離さないをどう実装するのか」とか
プログラムにするとなると以外と面倒でした。
良いプログラマになろうと思うのであれば、たまにはこんな感じで言葉で簡単に表現できることを
プログラムにしてみるのもありだと思います。
以外と自分の「わかっている」という感覚があいまいなものなんだということが実感できます。
この程度難なくコード化できる方、ぜひ一緒に仕事してください。
お待ちしています。