図1.は毎日新聞に掲載されたパズルです。表中の数字は 斜め方向を含む隣接マスに存在する爆弾の数で、これを根拠に位置を求めます。図1.右は解答です。このパズルには手筋があまりありませんが、図で、b8:c8, h3:i3 セルのように外周枠に接し 1〜4 の同じ数字が並んでいる場合 m7:m9, p2:p4 には x が確定します。基本的には例えば将棋で何手か先まで読むような感じで進めます。縦横の最大のマス数は25にしています。
次の例題はかなり手強いですが、コンピューターの強みで解けます。難問では Give up します。
なお、問題範囲全体を枠線で囲む必要があり シートの A1 セルから始めた場合には自動的に、行および列が挿入されます。エラーを回避するためです。
1 | 2 | 1 | 1 | ||||||
3 | 3 | 3 | |||||||
1 | 1 | 3 | 2 | 2 | |||||
3 | 3 | 3 | |||||||
4 | 2 | 3 | 2 | ||||||
4 | 3 | 4 | 3 | ||||||
3 | 2 | 2 | |||||||
3 | 4 | 3 | 3 | 2 | |||||
1 | 1 | 3 | |||||||
1 | 1 | 2 | 2 |
Sub bomber() Dim Rng As Range '---[ Bomber Puzzle Ver 4.1 ]--- Call SelStart(w): Set c0 = Range(w) If c0.Row = 1 Or c0.Column = 1 Then c0.EntireRow.Insert: c0.EntireColumn.Insert For y = 1 To 25: If c0.Cells(y + 1, 1).Borders(xlLeft).LineStyle <> 1 Then Exit For Next For x = 1 To 25: If c0.Cells(1, x + 1).Borders(xlTop).LineStyle <> 1 Then Exit For Next: Set Rng = Range(c0, c0.Cells(y, x)) 'Rng 問題範囲 With Rng: .HorizontalAlignment = xlCenter: .ColumnWidth = 3.4: .RowHeight = 22.6 .Borders.Weight = 2: .BorderAround Weight:=xlThick: End With Call Init(Rng): a = MsgBox("Start?", vbYesNo): If a = vbNo Then End Rng.SpecialCells(xlCellTypeBlanks).Font.Size = 1 Do: Erc = 0 For Each c In Rng.SpecialCells(xlCellTypeBlanks): Arr = Rng: ok = False c.Value = "●": Call Exct(Rng, Er): Rng = Arr If Er = True Then Er = False: ok = True: Erc = Erc + 1: c.Value = "×" If ok = True Then Else Arr = Rng: c.Value = "×": Call Exct(Rng, Er): Rng = Arr If Er = True Then Er = False: Erc = Erc + 1: c.Value = "●" Next Loop While Erc > 0 And WorksheetFunction.CountBlank(Rng) > 0 Rng.Font.Size = 11: MsgBox "Give UP": Call Init(Rng) End Sub Sub SelStart(w) For I = 1 To 8: For j = 1 To 8: Set b = Cells(j, I).Borders(xlEdgeLeft) If b.LineStyle = 1 Then w = Cells(j, I).Address: Exit Sub ' 開始セル番地取得 Next: Next: MsgBox "問題範囲の外周枠を線引きする必要があります。": End End Sub Sub Init(Rng) For Each c In Rng: If IsNumeric(c) = False Then c.Value = "" Next End Sub Sub Exct(Rng, Er) Do: ok = "": For Each c In Rng If c.Value Like "[0-8]" Then Set c1 = c.Offset(-1, -1): Set c2 = c.Range("b2") n = c.Value: Set Rn = Intersect(Range(c1, c2), Rng) bl = WorksheetFunction.CountBlank(Rn): bm = WorksheetFunction.CountIf(Rn, "●") If n = 0 Then Rn.Replace What:="", Replacement:="×" If bl > 0 And bl + bm = n Then Rn.Replace What:="", Replacement:="●": ok = True If bl > 0 And bm = n Then Rn.Replace What:="", Replacement:="×": ok = True If bm > n Or bl + bm < n Then Er = True: Exit Sub End If: Next Loop While ok = True If WorksheetFunction.CountBlank(Rng) = 0 Then Rng.Font.Size = 11: MsgBox "Completed": End End Sub