【VBAリファレンス】VBAサンプル集オセロを作りながらマクロVBAを学ぼう№14

スポンサーリンク

オセロ開発で学ぶVBAの真髄:オブジェクト指向的アプローチとロジックの可視化

Excel VBAを用いてオセロゲームを開発するという試みは、単なるプログラミング学習の枠を超えた、ソフトウェアエンジニアリングの縮図です。盤面の管理、石の配置ロジック、裏返し判定、そして勝敗判定に至るまで、すべての要素が「データ構造」と「アルゴリズム」の調和によって成り立っています。本稿では、オセロ開発の第14回目として、最も重要かつ難解な「石の裏返し判定ロジック」に焦点を当て、プロフェッショナルな視点から詳細に解説します。

詳細解説:石の裏返しロジックの核心

オセロのルールにおいて、最も計算コストがかかり、かつバグを生み出しやすいのが「石を置いた際に、どの方向の石を裏返すか」という判定です。8方向(上下左右および斜め)のベクトルを走査し、相手の石が連続して並んでいるかを正確にトレースしなければなりません。

この処理を実装する際、多くの初心者は「If文を8回並べる」という冗長なコードを書きがちです。しかし、ベテランエンジニアは、方向性を表す「増分値(Delta)」を配列として定義し、ループ構造によって処理を抽象化します。

具体的には、以下の3つのフェーズでロジックを構築します。
1. 方向の定義:行方向(dr)と列方向(dc)の増分をペアで管理する。
2. 探索の実行:指定した方向へ1マスずつ進み、相手の石が存在するかを確認する。
3. 確定と更新:相手の石が連続した後に自分の石があれば、その経路上の石を裏返す。

このアプローチを取ることで、コードの保守性が飛躍的に高まり、将来的な機能拡張(AIの導入や履歴機能の追加)にも柔軟に対応できるようになります。

サンプルコード:8方向走査による裏返し処理の実装

以下に、オセロの盤面(8×8のセル範囲)において、指定したセルに石を置いた際の裏返し処理を実行する汎用的なプロシージャを示します。


' 盤面サイズ定数
Private Const BOARD_SIZE As Integer = 8

' 石を置いた際の裏返しメイン処理
Public Sub PlaceDisc(ByVal r As Integer, ByVal c As Integer, ByVal playerColor As Integer)
    Dim dr As Integer, dc As Integer
    Dim i As Integer
    
    ' 8方向の定義(上、下、左、右、および4つの斜め)
    Dim dirR As Variant, dirC As Variant
    dirR = Array(-1, -1, -1, 0, 0, 1, 1, 1)
    dirC = Array(-1, 0, 1, -1, 1, -1, 0, 1)
    
    For i = LBound(dirR) To UBound(dirR)
        If CanFlip(r, c, dirR(i), dirC(i), playerColor) Then
            ExecuteFlip r, c, dirR(i), dirC(i), playerColor
        End If
    Next i
    
    ' 最後に自分の石を配置
    Cells(r, c).Value = playerColor
End Sub

' 指定方向の裏返し判定
Private Function CanFlip(r As Integer, c As Integer, dr As Integer, dc As Integer, color As Integer) As Boolean
    Dim nr As Integer, nc As Integer
    Dim opponent As Integer
    opponent = IIf(color = 1, 2, 1)
    
    nr = r + dr
    nc = c + dc
    
    ' 隣が相手の石か確認
    If IsInBoard(nr, nc) And Cells(nr, nc).Value = opponent Then
        Do
            nr = nr + dr
            nc = nc + dc
            If Not IsInBoard(nr, nc) Then Exit Function
            If Cells(nr, nc).Value = color Then
                CanFlip = True
                Exit Function
            End If
        Loop While Cells(nr, nc).Value = opponent
    End If
End Function

' 実際に石を裏返す処理
Private Sub ExecuteFlip(r As Integer, c As Integer, dr As Integer, dc As Integer, color As Integer)
    Dim nr As Integer, nc As Integer
    nr = r + dr
    nc = c + dc
    Do While Cells(nr, nc).Value <> color
        Cells(nr, nc).Value = color
        nr = nr + dr
        nc = nc + dc
    Loop
End Sub

' 盤面内判定
Private Function IsInBoard(r As Integer, c As Integer) As Boolean
    IsInBoard = (r >= 1 And r <= BOARD_SIZE And c >= 1 And c <= BOARD_SIZE)
End Function

実務アドバイス:コードの品質を高めるために

VBAでゲーム開発を行う際、最も注意すべきは「画面の描画更新」と「計算ロジック」の分離です。上記のコードはセルの値を直接書き換えていますが、規模が大きくなると、内部データ(配列変数)で盤面を管理し、最後に一括でセルへ反映させる「モデル・ビュー分離」の設計が推奨されます。

また、デバッグの際は「イミディエイトウィンドウ」を積極的に活用してください。`Debug.Print` を用いて、どの方向で裏返しが判定されたのか、あるいは判定がループから抜けてしまったのかをログ出力することで、視覚的に見えないロジックの挙動を追跡できます。

さらに、プロフェッショナルなコードを目指すなら、エラーハンドリングを忘れないでください。ユーザーが既に石が置かれているセルをクリックした際、あるいは盤面外を操作しようとした際に、プログラムが強制終了しないようなガード節(Guard Clause)を適切に配置することが、堅牢なアプリケーションへの第一歩です。

まとめ:VBAという道具を使いこなす

オセロの裏返しロジックを実装することは、配列操作、ループ制御、条件分岐、そして関数間のデータ受け渡しという、VBAにおける主要な概念をすべて網羅する素晴らしいトレーニングです。

今回のコードは、単に「動く」だけでなく、方向を配列で管理することで「拡張性を持たせる」という設計思想に基づいています。今後、このプロジェクトをさらに発展させるなら、次は「パス判定」や「石のカウント機能」の実装に挑戦してみてください。

VBAは古くから存在する言語ですが、その本質は「論理的な思考をコードという形に落とし込むこと」にあります。オセロという完成されたゲームルールを紐解き、自らの手で再構築していくプロセスを通じて、皆さんのエンジニアリング能力は確実に一段上のレベルへと引き上げられるはずです。次回も引き続き、より高度なゲームエンジンの構築を目指して邁進しましょう。

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