【初心者向け】Excelでナンプレを簡単に作成・解く方法と便利マクロ5選

Excelを使えば、数独(ナンプレ)の作成と解く作業をデジタル化できるので、紙とペンの作業よりも効率的です。
初心者でも直感的に扱えるように、セル書式やVBAマクロを組み合わせて、手間を大幅に削減する方法を紹介します。

Excelでナンプレボードを作る

セルに枠線を引く

  1. 9×9 の範囲(例:A1:I9)を選択。
  2. 「ホーム」>「罫線」>「外枠」を選択し、さらに「線の種類」で太線(黒)を設定。
  3. 3×3 のブロックごとに太線を引くには、セルをドラッグして「罫線」>「枠線」を再度選択し、同様の手順で太線にします。
  4. 全体で完了したら、見やすいフォント(例:MS ゴシック、サイズ16)に設定します。

入力規則で数字の制限

  • A1:I9 を選択した状態で「データ」>「データの入力規則」を開き、「セルの値」「1以上9以下」の数値を許可します。
  • これで余計な文字が投入されるのを防ぎます。

数独の作成と保存

ボードは「空」の状態(セルに何も入力していない)で作成し、手順に沿って数を埋めていきます。
完成したパズルを別シートにコピーして保存することで、別途「解答」と「作業用」の二重化が可能です。

数独の解法をサポートする関数

Excel の関数だけでも簡易的に数独の正当性を確認できます。
以下の式をセル J1 から J9 に入力し、各列を横にコピーします(J1:J9 = 公式1)。

=SUMPRODUCT(1/COUNTIF(A1:I1,A1:I1))
  • 公式1はその行に重複がなければ 9 を返し、重複があれば 9 未満を返します。
  • 同様に列とブロック(1〜9 のブロックごとに COUNTIF)をチェックし、結果を すべて9 であれば正しい配置になります。

VBAで自動チェックマクロ

VBA を使うと、もっと柔軟にチェックと入力補助ができます。

1. 数値入力時のリアルタイムチェック

Private Sub Worksheet_Change(ByVal Target As Range)
    If Intersect(Target, Range("A1:I9")) Is Nothing Then Exit Sub
    If Not IsNumeric(Target.Value) Or Target.Value < 1 Or Target.Value > 9 Then
        MsgBox "1〜9 の整数を入力してください。"
        Target.ClearContents
        Exit Sub
    End If
    If Not IsUniqueInRow(Target) Or Not IsUniqueInColumn(Target) Or Not IsUniqueInBlock(Target) Then
        MsgBox "重複が検出されました。"
        Target.ClearContents
    End If
End Sub

Function IsUniqueInRow(ByVal Rng As Range) As Boolean
    Dim RowVals As Variant, i As Long, cnt As Long
    RowVals = Application.Transpose(Rng.EntireRow.Value)
    For i = LBound(RowVals) To UBound(RowVals)
        If RowVals(i) <> "" Then
            cnt = cnt + WorksheetFunction.CountIf(Range("A" & Rng.Row & ":I" & Rng.Row), RowVals(i))
            If cnt > 1 Then
                IsUniqueInRow = False
                Exit Function
            End If
        End If
    Next i
    IsUniqueInRow = True
End Function

Function IsUniqueInColumn(ByVal Rng As Range) As Boolean
    Dim ColVals As Variant, i As Long, cnt As Long
    ColVals = Range(Rng.Column & "1:" & Rng.Column & "9").Value
    For i = LBound(ColVals, 1) To UBound(ColVals, 1)
        If ColVals(i, 1) <> "" Then
            cnt = cnt + WorksheetFunction.CountIf(Range("A1:I9").Columns(Rng.Column), ColVals(i, 1))
            If cnt > 1 Then
                IsUniqueInColumn = False
                Exit Function
            End If
        End If
    Next i
    IsUniqueInColumn = True
End Function

Function IsUniqueInBlock(ByVal Rng As Range) As Boolean
    Dim StartRow As Long, StartCol As Long, i As Long, j As Long, cnt As Long, val As Variant
    StartRow = (Int((Rng.Row - 1) / 3) * 3) + 1
    StartCol = (Int((Rng.Column - 1) / 3) * 3) + 1
    For i = StartRow To StartRow + 2
        For j = StartCol To StartCol + 2
            val = Cells(i, j).Value
            If val <> "" Then
                cnt = cnt + WorksheetFunction.CountIf(Range("A1:I9").Cells(i - StartRow + 1, j - StartCol + 1), val)
                If cnt > 1 Then
                    IsUniqueInBlock = False
                    Exit Function
                End If
            End If
        Next j
    Next i
    IsUniqueInBlock = True
End Function
  • これでセルに入力するとすぐに重複判定が行われ、エラーがあれば自動でクリアされます。

5つの便利マクロ集

1. 盤面の自動クリア

Sub ClearBoard()
    Range("A1:I9").ClearContents
    MsgBox "盤面をクリアしました。"
End Sub

2. 盤面に数値をランダムに入力(簡易パズル作成)

Sub FillRandomNumbers()
    Dim i As Long, j As Long, n As Long
    Call ClearBoard
    Randomize
    For i = 1 To 9
        For j = 1 To 9
            If Rnd() < 0.4 Then ' 約40% を埋める
                n = Int((9 * Rnd) + 1)
                Cells(i, j).Value = n
            End If
        Next j
    Next i
    MsgBox "簡易パズルが生成されました。"
End Sub

3. 正答チェック(解答と照合)

先に正解を別シート("Answer")に入力しておく前提です。

Sub CheckAnswer()
    Dim i As Long, j As Long, diff As Long
    diff = 0
    For i = 1 To 9
        For j = 1 To 9
            If Cells(i, j).Value <> Worksheets("Answer").Cells(i, j).Value Then diff = diff + 1
        Next j
    Next i
    If diff = 0 Then
        MsgBox "提出されたパズルはすべて正しいです!"
    Else
        MsgBox diff & " 個のセルが誤っています。"
    End If
End Sub

4. 複数の手順(解法アルゴリズム)を実行して自動解く

最も簡易的な「単純推理」だけを行うマクロです。

Sub SimpleSolver()
    Dim changed As Boolean, i As Long, j As Long, rowVals, colVals, blockVals
    Do
        changed = False
        For i = 1 To 9
            For j = 1 To 9
                If Cells(i, j).Value = "" Then
                    rowVals = Application.Transpose(Range(Cells(i, 1), Cells(i, 9)).Value)
                    colVals = Application.Transpose(Range(Cells(1, j), Cells(9, j)).Value)
                    blockVals = Application.Transpose(Range(Cells((Int((i - 1) / 3) * 3) + 1, (Int((j - 1) / 3) * 3) + 1), Cells((Int((i - 1) / 3) * 3) + 3, (Int((j - 1) / 3) * 3) + 3)).Value)
                    Dim possible As Collection, k As Variant, v As Variant
                    Set possible = New Collection
                    For v = 1 To 9
                        On Error Resume Next
                        If IsError(Application.Match(v, rowVals, 0)) And _
                           IsError(Application.match(v, colVals, 0)) And _
                           IsError(Application.match(v, blockVals, 0)) Then
                            possible.Add v
                        End If
                        On Error GoTo 0
                    Next v
                    If possible.Count = 1 Then
                        Cells(i, j).Value = possible(1)
                        changed = True
                    End If
                End If
            Next j
        Next i
    Loop While changed
    MsgBox "簡易自動解答を完了しました。"
End Sub

5. 数字の候補をセル内に小文字で表示(ペン印)

セル内に小さいフォントで候補を表示し、手書きのように可視化します。

Sub ShowCandidates()
    Dim i As Long, j As Long, rowVals, colVals, blockVals
    For i = 1 To 9
        For j = 1 To 9
            If Cells(i, j).Value = "" Then
                rowVals = Application.Transpose(Range(Cells(i, 1), Cells(i, 9)).Value)
                colVals = Application.Transpose(Range(Cells(1, j), Cells(9, j)).Value)
                blockVals = Application.Transpose(Range(Cells((Int((i - 1) / 3) * 3) + 1, (Int((j - 1) / 3) * 3) + 1), Cells((Int((i - 1) / 3) * 3) + 3, (Int((j - 1) / 3) * 3) + 3)).Value)
                Dim possible As String, v As Variant
                For v = 1 To 9
                    If IsError(Application.Match(v, rowVals, 0)) And _
                       IsError(Application.match(v, colVals, 0)) And _
                       IsError(Application.match(v, blockVals, 0)) Then
                        possible = possible & v
                    End If
                Next v
                Cells(i, j).Font.Size = 6
                Cells(i, j).Value = possible
            End If
        Next j
    Next i
    MsgBox "候補表示を完了しました。"
End Sub

まとめ

Excel で数独を作成・解く際に、以下のポイントを押さえれば手間を劇的に減らせます。

  1. 罫線と入力規則でボードを整備。
  2. 行列・ブロックごとのチェック関数で重複を自動検知。
  3. 5 つのVBAマクロを組み合わせることで、クリア、生成、解答照合、簡易自動解法、候補表示などをワンクリック。

初心者であっても、数回マクロを実行すれば数独の作業は紙とペンを使った時より効率化されます。
ぜひ自分専用の数独テンプレートを作り、遊びと脳トレの両方を満喫してください。

コメント

タイトルとURLをコピーしました