ナンバーリンク(パズル)を解くVBAに挑戦№5
さて、ここまでくると、後は何が無駄なのでしょうか。
chkClose
chkClose2
再帰呼び出しで、次々に空白セルを辿ります。
では、これを組み込んだコードです。
Option Explicit
Private SuAry(1 To 10, 1 To 10) As String
Private SuAry2(1 To 10, 1 To 10) As String
Sub main()
Debug.Print Now()
Dim iR As Integer
Dim iC As Integer
For iR = 1 To 10
For iC = 1 To 10
With Cells(iR + 1, iC + 1)
If .Value = "" Or Not IsNumeric(.Value) Then
.Value = ""
.Font.Size = 9
.Font.Bold = False
.NumberFormat = "@"
SuAry(iR, iC) = ""
Else
SuAry(iR, iC) = .Value
End If
End With
Next
Next
iR = 1
iC = 0
Call getStart(iR, iC)
Do
If getAdvance(iR, iC, iR, iC, 0) = "完了" Then
Exit Do
End If
Loop
Call dispCell(True)
Debug.Print Now()
End Sub
Private Function getAdvance(ByVal iR As Integer, ByVal iC As Integer, _
ByVal iR2 As Integer, ByVal iC2 As Integer, _
ByVal tryCnt As Integer) As String
Dim iR3 As Integer
Dim iC3 As Integer
Dim iR4 As Integer
Dim iC4 As Integer
Dim i As Integer
Dim strMust As String
Dim rtn As String
Call getEnd(iR4, iC4, SuAry(iR, iC))
Select Case True
Case iR4 = iR2 - 1 And iC4 = iC2, _
iR4 = iR2 And iC4 = iC2 + 1, _
iR4 = iR2 + 1 And iC4 = iC2, _
iR4 = iR2 And iC4 = iC2 - 1
Call dispCell(True)
tryCnt = 0
If getStart(iR, iC) = False Then
getAdvance = "完了"
Exit Function
End If
rtn = getAdvance(iR, iC, iR, iC, tryCnt)
Select Case rtn
Case "完了"
getAdvance = "完了"
Exit Function
Case "終点"
getAdvance = "終点"
tryCnt = 0
If getStart(iR, iC) = False Then
getAdvance = "完了"
Exit Function
End If
Case "破綻"
getAdvance = "破綻"
Exit Function
End Select
End Select
For i = 1 To 4
Select Case True
Case iR4 > iR2 And iC4 > iC2
Select Case i
Case 1
iR3 = iR2 + 1
iC3 = iC2
Case 2
iR3 = iR2
iC3 = iC2 + 1
Case 3
iR3 = iR2 - 1
iC3 = iC2
Case 4
iR3 = iR2
iC3 = iC2 - 1
End Select
Case iR4 > iR2 And iC4 <= iC2
Select Case i
Case 1
iR3 = iR2 + 1
iC3 = iC2
Case 2
iR3 = iR2
iC3 = iC2 - 1
Case 3
iR3 = iR2
iC3 = iC2 + 1
Case 4
iR3 = iR2 - 1
iC3 = iC2
End Select
Case iR4 < iR2 And iC4 > iC2
Select Case i
Case 1
iR3 = iR2 - 1
iC3 = iC2
Case 2
iR3 = iR2
iC3 = iC2 + 1
Case 3
iR3 = iR2 + 1
iC3 = iC2
Case 4
iR3 = iR2
iC3 = iC2 - 1
End Select
Case iR4 = iR2 And iC4 > iC2
Select Case i
Case 1
iR3 = iR2
iC3 = iC2 + 1
Case 2
iR3 = iR2
iC3 = iC2 - 1
Case 3
iR3 = iR2 - 1
iC3 = iC2
Case 4
iR3 = iR2 + 1
iC3 = iC2
End Select
Case iR4 < iR2 And iC4 <= iC2
Select Case i
Case 1
iR3 = iR2 - 1
iC3 = iC2
Case 2
iR3 = iR2
iC3 = iC2 - 1
Case 3
iR3 = iR2 + 1
iC3 = iC2
Case 4
iR3 = iR2
iC3 = iC2 + 1
End Select
Case iR4 = iR2 And iC4 <= iC2
Select Case i
Case 1
iR3 = iR2
iC3 = iC2 - 1
Case 2
iR3 = iR2
iC3 = iC2 + 1
Case 3
iR3 = iR2 - 1
iC3 = iC2
Case 4
iR3 = iR2 + 1
iC3 = iC2
End Select
End Select
If iC3 >= 1 And iC3 <= 10 And iR3 >= 1 And iR3 <= 10 Then
If SuAry(iR3, iC3) = "" Then
If chkAdvance(iR3, iC3, SuAry(iR, iC)) = True Then
If chkClose(iR3, iC3, SuAry(iR, iC)) = True Then
If chkRout(iR, iC) = True Then
tryCnt = tryCnt + 1
Call dispCell(True, iR3, iC3, SuAry(iR, iC) & "-" & tryCnt)
rtn = getAdvance(iR, iC, iR3, iC3, tryCnt)
Select Case rtn
Case "完了"
getAdvance = "完了"
Exit Function
End Select
If Not IsNumeric(SuAry(iR3, iC3)) Then
tryCnt = tryCnt - 1
Call dispCell(True, iR3, iC3, "")
End If
End If
End If
End If
End If
End If
Next
If IsNumeric(SuAry(iR2, iC2)) Then
getAdvance = "破綻"
Else
tryCnt = tryCnt - 1
Call dispCell(True, iR2, iC2, "")
getAdvance = "別ルート探索"
End If
End Function
Private Function chkAdvance(ByVal iR As Integer, ByVal iC As Integer, ByVal i As Integer) As Boolean
Dim cnt As Integer
cnt = 0
If iR <> 1 And iC <> 1 Then
If InStr(SuAry(iR - 1, iC - 1), i & "-") > 0 Or SuAry(iR - 1, iC - 1) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR - 1, iC), i & "-") > 0 Or SuAry(iR - 1, iC) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR, iC - 1), i & "-") > 0 Or SuAry(iR, iC - 1) = CStr(i) Then
cnt = cnt + 1
End If
If cnt >= 3 Then
chkAdvance = False
Exit Function
End If
End If
cnt = 0
If iR <> 10 And iC <> 1 Then
If InStr(SuAry(iR + 1, iC - 1), i & "-") > 0 Or SuAry(iR + 1, iC - 1) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR + 1, iC), i & "-") > 0 Or SuAry(iR + 1, iC) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR, iC - 1), i & "-") > 0 Or SuAry(iR, iC - 1) = CStr(i) Then
cnt = cnt + 1
End If
If cnt >= 3 Then
chkAdvance = False
Exit Function
End If
End If
cnt = 0
If iR <> 1 And iC <> 10 Then
If InStr(SuAry(iR - 1, iC + 1), i & "-") > 0 Or SuAry(iR - 1, iC + 1) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR - 1, iC), i & "-") > 0 Or SuAry(iR - 1, iC) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR, iC + 1), i & "-") > 0 Or SuAry(iR, iC + 1) = CStr(i) Then
cnt = cnt + 1
End If
If cnt >= 3 Then
chkAdvance = False
Exit Function
End If
End If
cnt = 0
If iR <> 10 And iC <> 10 Then
If InStr(SuAry(iR + 1, iC + 1), i & "-") > 0 Or SuAry(iR + 1, iC + 1) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR + 1, iC), i & "-") > 0 Or SuAry(iR + 1, iC) = CStr(i) Then
cnt = cnt + 1
End If
If InStr(SuAry(iR, iC + 1), i & "-") > 0 Or SuAry(iR, iC + 1) = CStr(i) Then
cnt = cnt + 1
End If
If cnt >= 3 Then
chkAdvance = False
Exit Function
End If
End If
chkAdvance = True
End Function
Private Sub dispCell(ByVal blnDisp As Boolean, _
Optional ByVal iR As Integer = 0, Optional ByVal iC As Integer = 0, _
Optional ByVal dispStr As String = "")
If iR <> 0 And iC <> 0 Then
SuAry(iR, iC) = dispStr
End If
If blnDisp = True Then
Range("B2:K11").Value = SuAry
DoEvents
End If
End Sub
Private Function getStart(ByRef iR As Integer, ByRef iC As Integer) As Boolean
iC = iC + 1
If RowColAjust(iR, iC) = False Then
getStart = False
Exit Function
End If
Do
If IsNumeric(SuAry(iR, iC)) Then
If chkEnd(iR, iC) <> True Then
getStart = True
Exit Function
End If
End If
iC = iC + 1
If RowColAjust(iR, iC) = False Then
getStart = False
Exit Function
End If
Loop
End Function
Private Function RowColAjust(ByRef iR As Integer, ByRef iC As Integer) As Boolean
If iC > 10 Then
iR = iR + 1
iC = 1
End If
If iR > 10 Then
RowColAjust = False
Exit Function
End If
RowColAjust = True
End Function
Private Function chkEnd(ByVal iR As Integer, ByVal iC As Integer) As Boolean
Dim iR2 As Integer
Dim iC2 As Integer
Call getEnd(iR2, iC2, SuAry(iR, iC))
If iR2 = iR And iC2 = iC Then
chkEnd = True
Else
chkEnd = False
End If
End Function
Private Sub getEnd(ByRef iR2 As Integer, ByRef iC2 As Integer, ByVal i As String)
iR2 = 10
iC2 = 10
Do
If SuAry(iR2, iC2) = i Then
Exit Sub
End If
iC2 = iC2 - 1
If iC2 < 1 Then
iR2 = iR2 - 1
iC2 = 10
End If
If iR2 < 1 Then
Exit Sub
End If
Loop
End Sub
Private Function chkRout(ByVal iR1 As Integer, ByVal iC1 As Integer) As Boolean
Dim iR2 As Integer
Dim iC2 As Integer
Dim iR3 As Integer
Dim iC3 As Integer
Dim i As Integer
Dim j As Integer
chkRout = True
For i = 1 To 10
For j = 1 To 10
SuAry2(i, j) = SuAry(i, j)
Next
Next
If getStart(iR1, iC1) = False Then
chkRout = True
Exit Function
End If
Call getEnd(iR2, iC2, SuAry(iR1, iC1))
If chkRout2(iR1, iC1, iR2, iC2) = False Then
chkRout = False
End If
If chkRout(iR1, iC1) = False Then
chkRout = False
End If
End Function
Private Function chkRout2(ByVal iR1 As Integer, ByVal iC1 As Integer, ByVal iR2 As Integer, ByVal iC2 As Integer) As Boolean
Dim i As Integer
Dim iR3 As Integer
Dim iC3 As Integer
Select Case True
Case iR1 = iR2 - 1 And iC1 = iC2, _
iR1 = iR2 And iC1 = iC2 + 1, _
iR1 = iR2 + 1 And iC1 = iC2, _
iR1 = iR2 And iC1 = iC2 - 1
chkRout2 = True
Exit Function
End Select
For i = 1 To 4
Select Case i
Case 1
iR3 = iR2 + 1
iC3 = iC2
Case 2
iR3 = iR2
iC3 = iC2 + 1
Case 3
iR3 = iR2 - 1
iC3 = iC2
Case 4
iR3 = iR2
iC3 = iC2 - 1
End Select
If iC3 >= 1 And iC3 <= 10 And iR3 >= 1 And iR3 <= 10 Then
If SuAry2(iR3, iC3) = "" Then
SuAry2(iR3, iC3) = "●"
If chkRout2(iR1, iC1, iR3, iC3) = True Then
chkRout2 = True
Exit Function
End If
End If
End If
Next
chkRout2 = False
End Function
Private Function chkClose(ByVal iR1 As Integer, ByVal iC1 As Integer, ByVal iNo As Integer) As Boolean
Dim iR2 As Integer
Dim iC2 As Integer
Dim cnt As Integer
Dim i As Integer
Dim j As Integer
chkClose = True
For i = 1 To 10
For j = 1 To 10
SuAry2(i, j) = SuAry(i, j)
Next
Next
SuAry2(iR1, iC1) = "●"
cnt = 0
If iR1 > 1 Then
If SuAry2(iR1 - 1, iC1) = "" Then
Call chkClose2(iR1 - 1, iC1, cnt, iNo)
If cnt <= 1 Then
chkClose = False
Exit Function
End If
End If
End If
For i = 1 To 10
For j = 1 To 10
SuAry2(i, j) = SuAry(i, j)
Next
Next
SuAry2(iR1, iC1) = "●"
cnt = 0
If iR1 < 10 Then
If SuAry2(iR1 + 1, iC1) = "" Then
Call chkClose2(iR1 + 1, iC1, cnt, iNo)
If cnt <= 1 Then
chkClose = False
Exit Function
End If
End If
End If
For i = 1 To 10
For j = 1 To 10
SuAry2(i, j) = SuAry(i, j)
Next
Next
SuAry2(iR1, iC1) = "●"
cnt = 0
If iC1 > 1 Then
If SuAry2(iR1, iC1 - 1) = "" Then
Call chkClose2(iR1, iC1 - 1, cnt, iNo)
If cnt <= 1 Then
chkClose = False
Exit Function
End If
End If
End If
For i = 1 To 10
For j = 1 To 10
SuAry2(i, j) = SuAry(i, j)
Next
Next
SuAry2(iR1, iC1) = "●"
cnt = 0
If iC1 < 10 Then
If SuAry2(iR1, iC1 + 1) = "" Then
Call chkClose2(iR1, iC1 + 1, cnt, iNo)
If cnt <= 1 Then
chkClose = False
Exit Function
End If
End If
End If
End Function
Private Sub chkClose2(ByVal iR1 As Integer, ByVal iC1 As Integer, ByRef cnt As Integer, ByVal iNo As Integer)
Dim i As Integer
Dim iR3 As Integer
Dim iC3 As Integer
If cnt >= 2 Then
Exit Sub
End If
For i = 1 To 4
Select Case i
Case 1
iR3 = iR1 + 1
iC3 = iC1
Case 2
iR3 = iR1
iC3 = iC1 + 1
Case 3
iR3 = iR1 - 1
iC3 = iC1
Case 4
iR3 = iR1
iC3 = iC1 - 1
End Select
If iC3 >= 1 And iC3 <= 10 And iR3 >= 1 And iR3 <= 10 Then
If SuAry2(iR3, iC3) = "" Then
SuAry2(iR3, iC3) = "●"
Call chkClose2(iR3, iC3, cnt, iNo)
Else
If SuAry2(iR3, iC3) = CStr(iNo) Then
cnt = 2
Exit Sub
End If
If IsNumeric(SuAry2(iR3, iC3)) Then
SuAry2(iR3, iC3) = "●"
cnt = cnt + 1
If cnt >= 2 Then
Exit Sub
End If
End If
End If
End If
Next
End Sub
だいぶ、それらしい動きにはなってきました。
(テスト機は、Windows7、Corei5、4Gメモリ)
ナンバーリンク(パズル)を解くVBAに挑戦 : №1 №2 №3 №4 №5 №6 №7 №8
同じテーマ「マクロVBAサンプル集」の記事
アメブロの記事本文をVBAでバックアップする№1
数独(ナンプレ)を解くVBAに挑戦№1
数独(ナンプレ)を解くアルゴリズムの要点とパフォーマンスの検証№1
ナンバーリンク(パズル)を解くVBAに挑戦№1
ナンバーリンクを解くVBAのパフォーマンス改善№1
オセロを作りながらマクロVBAを学ぼう
他ブックへのリンクエラーを探し解除
Excelシートの複雑な計算式を解析するVBA
Excel将棋:マクロVBAの学習用(№1)
Excel囲碁:万波奈穂先生に捧ぐ
Excel囲碁:再起動後も続けて打てるように改造
新着記事NEW ・・・新着記事一覧を見る
付録:AI×VBA実践リソース集|生成AI活用研究(2025-05-25)
おわりに:AI×VBAはあなたの未来を変える強力な武器|生成AI活用研究(2025-05-25)
第7章:さらなる高みへ!AI×VBA応用テクニックと未来への備え|生成AI活用研究(2025-05-24)
第6章:AIとVBAを学び続ける!あなたの「超効率化」を止めないヒント|生成AI活用研究(2025-05-22)
第5章:AI×VBAでつまづかない!トラブルシューティングとAIとの付き合い方
|生成AI活用研究(2025-05-21)
第4章:【事例で学ぶ】AIとVBAでExcel作業を劇的に効率化する!
|生成AI活用研究(2025-05-20)
第3章:AIを「自分だけのVBA先生」にする!質問・相談の超実践テクニック|生成AI活用研究(2025-05-19)
第2章 VBAって怖くない!Excelを「言葉で動かす」(超入門)|生成AI活用研究(2025-05-18)
第1章:AIって一体何?あなたのExcel作業をどう変える?(AI超基本)|生成AI活用研究(2025-05-18)
AI時代のExcel革命:AI×VBAで“書かない自動化”超入門|生成AI活用研究(2025-05-17)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.ひらがな⇔カタカナの変換|エクセル基本操作
6.RangeとCellsの使い方|VBA入門
7.メッセージボックス(MsgBox関数)|VBA入門
8.セルのクリア(Clear,ClearContents)|VBA入門
9.FILTER関数(範囲をフィルター処理)|エクセル入門
10.条件分岐(Select Case)|VBA入門
- ホーム
- マクロVBA応用編
- マクロVBAサンプル集
- ナンバーリンク(パズル)を解くVBAに挑戦№5
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。