【VBAリファレンス】VBAサンプル集オセロを作りながらマクロVBAを学ぼう№11 盤面の判定ロジックと石の裏返し処理の実装

スポンサーリンク

概要

VBAによるオセロ開発シリーズ第11回となる今回は、オセロの最も核心的な機能である「石を置いた際の裏返し処理」に焦点を当てます。これまで盤面の表示やクリックイベントの実装を行ってきましたが、ここからは「置ける場所かどうかの判定」と「挟んだ石を反転させるアルゴリズム」という、論理的思考が求められる難所を攻略します。このステップをマスターすることで、配列操作とループ処理のスキルが飛躍的に向上します。

詳細解説:石を挟むロジックの設計思想

オセロにおける石の裏返し処理は、単なる色塗りではありません。置いた石から見て「上下左右、および斜め方向の8方向」を探索し、相手の石が連続し、その先に自分の石があるかを判定するプロセスです。

この判定を効率的に行うためには、方向を表す「増分値」の概念が不可欠です。例えば、右方向は「行の増分0、列の増分1」、右下方向は「行の増分1、列の増分1」として定義します。この増分値を配列として保持し、ループ処理で各方向を順番に走査するのがスマートな実装です。

判定の手順は以下の通りです。
1. 指定した座標に石が既にないか確認する。
2. 8方向それぞれについて、相手の石が続く限り探索を進める。
3. 相手の石の先に自分の石が見つかった場合、そこまでの座標をリストアップする。
4. リストアップされた座標の石を自分の色に書き換える。

この処理において、特に重要なのが「配列の境界外チェック」です。盤面外へ探索が突き抜けてエラーにならないよう、IF文で厳密に制御する必要があります。

サンプルコード:石を裏返す処理の実装

以下に、オセロ盤の特定のセルに石を置いた際、周囲の石を裏返すための核心的なロジックを提示します。


' 方向を定義する配列(上、右上、右、右下、下、左下、左、左上)
Dim dr As Variant, dc As Variant
dr = Array(-1, -1, 0, 1, 1, 1, 0, -1)
dc = Array(0, 1, 1, 1, 0, -1, -1, -1)

Sub ReverseStones(row As Integer, col As Integer, color As Integer)
    Dim i As Integer, j As Integer
    Dim r As Integer, c As Integer
    Dim opponent As Integer
    opponent = IIf(color = 1, 2, 1) ' 相手の色

    For i = 0 To 7
        ' 探索の開始
        r = row + dr(i)
        c = col + dc(i)
        
        ' 最初の隣接セルが相手の色かチェック
        If IsOnBoard(r, c) And Cells(r, c).Value = opponent Then
            ' 相手の石が続く限り進む
            Do While IsOnBoard(r, c) And Cells(r, c).Value = opponent
                r = r + dr(i)
                c = c + dc(i)
            Loop
            
            ' 最後に自分の石があるかチェック
            If IsOnBoard(r, c) And Cells(r, c).Value = color Then
                ' 裏返し処理を実行
                ReversePath row, col, dr(i), dc(i), color
            End If
        End If
    Next i
End Sub

Sub ReversePath(r As Integer, c As Integer, dr As Integer, dc As Integer, color As Integer)
    r = r + dr
    c = c + dc
    Do While Cells(r, c).Value <> color
        Cells(r, c).Value = color
        ' 視覚的な更新(必要に応じて)
        Call UpdateCellVisual(r, c, color)
        r = r + dr
        c = c + dc
    Loop
End Sub

Function IsOnBoard(r As Integer, c As Integer) As Boolean
    IsOnBoard = (r >= 1 And r <= 8 And c >= 1 And c <= 8)
End Function

実務アドバイス:可読性とデバッグ手法

実務でこのような複雑なロジックを組む際、最も避けるべきは「マジックナンバー(意味不明な数値)」の乱用です。今回のコードでは方向を配列で定義しましたが、これは保守性を高めるためです。もし「斜め方向の判定をスキップしたい」といった仕様変更があった場合、配列を修正するだけで対応可能です。

また、デバッグの際には「イミディエイトウィンドウ」を活用してください。`Debug.Print "探索中: " & r & "," & c` のように記述することで、プログラムがどのセルを走査し、どこで判定が終了したかをリアルタイムで追跡できます。VBA初心者ほど、一度にすべてを書こうとしてエラーに苦しみますが、プロは必ず小さな関数に分割し、それぞれを単体テストしてから結合します。この「分割統治法」こそが、大規模なVBAツールを開発する際の鉄則です。

さらに、パフォーマンス面のアドバイスとして、`Cells(r, c).Value` へのアクセスは、シートが再描画されるたびにコストがかかります。もし盤面が非常に大きい場合(例えばオセロではなく100x100のグリッドなど)、一度メモリ上の配列に値を読み込んで計算を行い、最後にまとめてシートに書き戻す手法を推奨します。今回のような8x8の盤面であれば直接操作でも問題ありませんが、大規模開発の視点を持つことは非常に重要です。

まとめ

今回の第11回では、オセロの最も面白い部分である「石の裏返し」のロジックを学びました。8方向への探索、境界チェック、そして再帰的あるいはループによる石の更新処理。これらはゲーム開発だけでなく、業務自動化におけるデータ整合性のチェックや、複雑な条件分岐を持つ帳票作成システムなど、あらゆる場面で応用できるアルゴリズムです。

コードを打ち込み、実際に盤面上の石がパタパタと裏返る瞬間は、プログラミング学習において最も達成感を感じる瞬間の一つです。ぜひ、自分で数値を変更して挙動を確認したり、特定の色の石が置けないように制限を加えるといった改造にも挑戦してみてください。次回は、「パスの判定」と「勝敗判定」の実装について解説します。盤面が完成に近づくにつれ、VBAでここまでできるという自信が、あなたのエンジニアとしてのスキルを底上げしてくれるはずです。継続こそが力なり。次回のステップアップへ向けて、今回のコードを完全に自分のものにしてください。

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