オセロ開発で学ぶVBA:盤面管理と石の配置ロジックの実装
オセロというゲームは、プログラミングの学習において非常に優れた題材です。8×8のグリッドという明確なデータ構造、石を置く際の「挟む」というルール、そして交互に手番を交代するという状態遷移。これらは、Excel VBAにおける「配列操作」「条件分岐」「ループ処理」「イベント駆動」といった基礎から応用までの技術を網羅的に習得するのに最適です。本稿では、VBAによるオセロ実装の第15回目として、最も核心的な部分である「盤面管理」と「石を置く際のロジック実装」に焦点を当てて解説します。
盤面データ構造の設計:二次元配列の活用
VBAでオセロを実装する場合、まず検討すべきは「盤面の状態をどこに保持するか」です。ワークシートのセルを直接参照することも可能ですが、パフォーマンスとコードの可読性を考慮すると、メモリ上で二次元配列を定義して操作するのがプロフェッショナルな設計です。
具体的には、8×8の盤面を「0(空)」「1(黒)」「2(白)」という整数値で管理します。この配列をモジュールレベル変数として定義することで、どのプロシージャからでも現在の盤面状況を参照・更新できるようになります。
石を置くロジック:8方向の走査アルゴリズム
オセロにおいて「石を置けるか」を判定するロジックは、このゲームの心臓部です。ルール上、石を置く場所は「隣接する相手の石を挟んで、その先に自分の石がある」場所です。これを実装するには、置いた場所から「上・下・左・右・右上・右下・左上・左下」の8方向を順番に走査する必要があります。
この判定には、方向ベクトル(dx, dy)を用いるのが定石です。例えば、右方向であれば (dx=1, dy=0) とし、ループを使って隣のマスを順次チェックしていきます。途中で相手の石が続き、最後に自分の石に到達すれば、その間の相手の石をすべて反転させることが可能です。
サンプルコード:石の配置と反転処理の実装
以下に、指定した座標に石を置き、周囲を走査して反転させるためのコアロジックを提示します。
' モジュールレベル変数
Dim Board(1 To 8, 1 To 8) As Integer
Dim CurrentPlayer As Integer ' 1:黒, 2:白
' 石を置くメインプロシージャ
Public Sub PlaceDisc(r As Integer, c As Integer)
Dim i As Integer
Dim directions As Variant
directions = Array(Array(-1, -1), Array(-1, 0), Array(-1, 1), _
Array(0, -1), Array(0, 1), _
Array(1, -1), Array(1, 0), Array(1, 1))
If Board(r, c) <> 0 Then Exit Sub
Dim canFlip As Boolean
canFlip = False
' 8方向をループ
For i = LBound(directions) To UBound(directions)
If CheckAndFlip(r, c, directions(i)(0), directions(i)(1)) Then
canFlip = True
End If
Next i
If canFlip Then
Board(r, c) = CurrentPlayer
CurrentPlayer = 3 - CurrentPlayer ' 手番交代
UpdateDisplay ' 画面更新用プロシージャ
End If
End Sub
' 特定方向への走査と反転判定
Private Function CheckAndFlip(r As Integer, c As Integer, dr As Integer, dc As Integer) As Boolean
Dim nr As Integer, nc As Integer
Dim opponent As Integer
opponent = 3 - CurrentPlayer
nr = r + dr
nc = c + dc
' 直隣が相手の石か確認
If nr < 1 Or nr > 8 Or nc < 1 Or nc > 8 Then Exit Function
If Board(nr, nc) <> opponent Then Exit Function
' 相手の石が続く限り進む
Do While nr >= 1 And nr <= 8 And nc >= 1 And nc <= 8
nr = nr + dr
nc = nc + dc
If nr < 1 Or nr > 8 Or nc < 1 Or nc > 8 Then Exit Function
' 自分の石が見つかったら反転開始
If Board(nr, nc) = CurrentPlayer Then
' 逆走して反転
Dim tr As Integer, tc As Integer
tr = r + dr
tc = c + dc
Do While tr <> nr Or tc <> nc
Board(tr, tc) = CurrentPlayer
tr = tr + dr
tc = tc + dc
Loop
CheckAndFlip = True
Exit Function
ElseIf Board(nr, nc) = 0 Then
' 空白があれば挟めない
Exit Function
End If
Loop
End Function
実務におけるVBA開発の極意
上記のコードを見て、「なぜわざわざCheckAndFlip関数を分けているのか」と疑問に思う方もいるかもしれません。実務的なVBA開発において重要なのは「責務の分離」です。配置判定と反転処理を一つの巨大なプロシージャに詰め込むと、後々のデバッグやメンテナンスが困難になります。
また、Excel VBAでは画面更新(ScreenUpdating)の制御がパフォーマンスに直結します。石を置くたびにシート上の全セルを再描画していては、動作が重くなります。配列でロジックを完結させ、最後にまとめてシートに書き出す、あるいは変更があったセルのみを更新するような工夫が必要です。
さらに、プロフェッショナルな設計を目指すなら「クラスモジュール」の活用を推奨します。`clsBoard`のようなクラスを作成し、盤面をプロパティとして保持し、`PlaceDisc`をメソッドとして公開することで、他のExcelブックやプロジェクトからも再利用可能なライブラリとして機能させることができます。
エラーハンドリングとデバッグの重要性
VBAでゲームを作成する際、最も厄介なのが「予期せぬ位置への配置」や「盤面外参照」によるランタイムエラーです。上記のコードでは、`nr < 1 Or nr > 8`といった境界チェックを徹底していますが、実務レベルではこれをさらに進め、`On Error GoTo`を用いたエラーハンドリングを実装すべきです。
特に、ユーザーが誤って盤面以外のセルをクリックしたり、処理中にEscapeキーを押して中断したりした際の挙動を制御することは、アプリケーションとしての完成度を大きく左右します。`Application.EnableEvents = False`を適切に活用し、処理の競合を防ぐことも忘れてはなりません。
まとめ
オセロという古典的なゲームをVBAで実装するプロセスは、単なるプログラミングの練習を超え、アルゴリズム的思考を養う最高のトレーニングです。今回解説した「二次元配列による盤面管理」と「8方向走査によるロジック判定」は、どのようなゲーム開発においても共通する基礎技術です。
VBAはレガシーな言語と揶揄されることもありますが、Excelという強力なインターフェースと組み合わせることで、今なお業務自動化やシミュレーションツール作成において圧倒的な威力を発揮します。今回のコードをベースに、次は「パス判定」や「COMAI(簡単な思考ルーチン)」の実装に挑戦してみてください。VBAの可能性は、あなたの設計力次第で無限に広がります。まずはこのコードを実際に打ち込み、デバッガで変数の推移を追いかけることから始めてみてください。それがプロフェッショナルへの第一歩です。
