オセロ開発で極めるVBAのオブジェクト指向とロジック構築
Excel VBAは単なる事務作業の自動化ツールに留まりません。その柔軟なメモリ管理とイベント駆動型のプログラミング構造を理解すれば、高度なゲーム開発すら可能です。本連載の第10回目となる今回は、オセロ(リバーシ)の核となる「石を置く判定ロジック」と「盤面の更新処理」に焦点を当てます。
多くの初学者が陥る罠は、条件分岐を力任せに記述し、コードの可読性を損なうことです。本記事では、プロフェッショナルな視点から、拡張性と保守性を重視した設計手法を解説します。
オセロロジックの核心:8方向探索アルゴリズム
オセロのルールにおいて最も重要なのは、「相手の石を挟んでいるか」の判定です。これを実現するためには、置いた場所から「上、下、左、右、右上、右下、左上、左下」の8方向を走査する必要があります。
この処理をif文の羅列で行うのはナンセンスです。ベテランのエンジニアは、方向ベクトル(Direction Vector)という概念を活用します。X軸とY軸の変化量を配列として定義し、ループ処理で回すことで、コード量を劇的に削減し、バグの混入を防ぐことができます。
詳細解説:盤面管理とデータ構造
Excelのシートをそのまま盤面として扱うことも可能ですが、パフォーマンスと論理分離の観点から、内部的には「2次元配列(8×8)」で盤面状態を保持することを強く推奨します。
1. 盤面状態の保持: 0(空)、1(黒)、2(白)という数値で状態を管理します。
2. 探索の終了条件: 相手の石が連続し、その先に自分の石がある場合にのみ「挟んだ」と判定します。
3. イベントの連鎖: 石を置いた後、盤面を更新し、相手のターンへ移行する一連の流れをサブルーチン化します。
サンプルコード:石の配置判定と更新ロジック
以下に、8方向を探索し、条件を満たす場合に石を反転させるプロシージャのサンプルを示します。このコードはクラスモジュールや標準モジュールに組み込むことを想定しています。
' 8方向のベクトル定義
Private Function GetDirections() As Variant
GetDirections = 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))
End Function
' 指定位置に石を置けるか判定し、置けるなら反転させる
Public Function TryPlaceDisk(ByVal r As Integer, ByVal c As Integer, ByVal color As Integer) As Boolean
Dim directions As Variant
Dim i As Integer, j As Integer, k As Integer
Dim dr As Integer, dc As Integer
Dim nr As Integer, nc As Integer
Dim canFlip As Boolean
Dim opponent As Integer
opponent = IIf(color = 1, 2, 1)
directions = GetDirections()
canFlip = False
' 既に石がある場合は終了
If Board(r, c) <> 0 Then Exit Function
' 8方向を順次探索
For i = LBound(directions) To UBound(directions)
dr = directions(i)(0)
dc = directions(i)(1)
nr = r + dr
nc = c + dc
' 相手の石が隣接しているか確認
If IsOnBoard(nr, nc) And Board(nr, nc) = opponent Then
' 直線上に自分の石があるか探索
Do While IsOnBoard(nr, nc) And Board(nr, nc) = opponent
nr = nr + dr
nc = nc + dc
Loop
' 自分の石が見つかった場合、反転処理を実行
If IsOnBoard(nr, nc) And Board(nr, nc) = color Then
FlipDisks r, c, dr, dc, color
canFlip = True
End If
End If
Next i
If canFlip Then Board(r, c) = color
TryPlaceDisk = canFlip
End Function
' 実際に石を反転させる処理
Private Sub FlipDisks(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 Board(nr, nc) <> color
Board(nr, nc) = color
nr = nr + dr
nc = nc + dc
Loop
End Sub
実務アドバイス:VBA開発の作法
オセロのような複雑なロジックを実装する際、以下の3点に注意してください。
第一に、マジックナンバーを避けることです。コード内の「1」や「2」といった数値は、定数(Const)または列挙型(Enum)として定義してください。これにより、後から「黒を0、白を1」に変更したいといった仕様変更にも一瞬で対応できます。
第二に、画面描画の最適化です。Excelのセルを書き換える処理は非常に重い操作です。`Application.ScreenUpdating = False` を使用し、処理中のちらつきを抑え、パフォーマンスを向上させましょう。また、盤面の更新は「配列の更新」と「セルへの書き出し」を分離し、必要なタイミングでのみ描画を行う設計が望ましいです。
第三に、デバッグ手法です。VBAのイミディエイトウィンドウを活用し、`Debug.Print`で盤面状態を随時出力してください。GUIの作成に時間を割く前に、ロジック部分が確実に動作することを確認するのが、プロのエンジニアの鉄則です。
まとめ:ロジックの抽象化が鍵となる
今回のオセロ開発を通じて学んだことは、複雑な問題をどのように小さなパーツに分解し、再利用可能なコードに落とし込むかという点です。方向ベクトルを用いた探索は、オセロだけでなく、チェスや将棋、さらには迷路探索アルゴリズムなど、多岐にわたるゲーム開発に応用可能です。
VBAは、その気になれば高度な計算処理もこなせる強力なツールです。今回作成したロジックをベースに、次は「CPUの思考ルーチン(AI)」の実装に挑戦してみてください。盤面の評価値を計算し、最善手を探索するアルゴリズムを導入することで、あなたのオセロは単なるプログラムから「対戦相手」へと進化します。
コードを書くことは、論理を構築することです。常に「より読みやすく、より速く、より拡張しやすく」という視点を忘れずに、日々の開発に取り組んでください。VBAの可能性は、あなたの設計力次第で無限に広がります。
