概要:VBAでオセロ開発の第二歩を踏み出す
前回の第1回では、オセロのプロジェクトにおける設計思想と、ワークシートを盤面に見立てるための「セル制御」の基礎について解説しました。今回は、いよいよ具体的な実装のフェーズに入ります。オセロというゲームの根幹である「8×8マスの盤面描画」と「初期配置の自動セットアップ」をテーマに、VBAの配列操作とセル制御を組み合わせて、動的なアプリケーションの基礎を構築していきます。単にコードをコピーするだけでなく、なぜその処理が必要なのか、VBAのメモリ管理と描画速度の観点から深く掘り下げていきましょう。
詳細解説:盤面データと描画の分離
VBAでゲームを作成する際、最も重要なのは「データの状態」と「画面上の表示」を切り離して考えることです。これを怠ると、処理が複雑になり、バグの温床となります。
今回のアプローチでは、まず8×8の2次元配列を用意します。この配列には、「0=空」「1=黒」「2=白」という数値を格納します。VBAの配列は高速で、セルに直接アクセスするよりもメモリ上での演算が圧倒的に優れています。
描画処理については、各セルを一つずつ塗りつぶすのではなく、あらかじめ定義した「スタイル」を適用する形をとります。Excelのセルはオブジェクトであり、一つずつアクセスするとオーバーヘッドが発生するため、可能な限りまとめて処理するか、画面更新を停止させる工夫が求められます。
サンプルコード:盤面生成と初期配置のロジック
以下のコードは、標準モジュールに貼り付けて実行してください。このコードでは、盤面の初期化、描画、そしてオセロのルールに基づいた中央4マスの初期配置を自動化します。
Option Explicit
' 盤面管理用定数
Public Const BOARD_SIZE As Integer = 8
Public Const CELL_EMPTY As Integer = 0
Public Const CELL_BLACK As Integer = 1
Public Const CELL_WHITE As Integer = 2
' 盤面データ配列
Public BoardData(1 To BOARD_SIZE, 1 To BOARD_SIZE) As Integer
Sub InitializeOthelloBoard()
Dim i As Integer, j As Integer
' 画面更新停止により描画速度を向上
Application.ScreenUpdating = False
' 盤面の初期化
Cells.Clear
Range("A1:H8").Select
With Selection
.ColumnWidth = 5
.RowHeight = 40
.Interior.Color = RGB(0, 128, 0) ' 緑色の盤面
.Borders.LineStyle = xlContinuous
End With
' 配列とセルの初期化
For i = 1 To BOARD_SIZE
For j = 1 To BOARD_SIZE
BoardData(i, j) = CELL_EMPTY
Next j
Next i
' 初期配置(中央の4マス)
BoardData(4, 4) = CELL_WHITE
BoardData(5, 5) = CELL_WHITE
BoardData(4, 5) = CELL_BLACK
BoardData(5, 4) = CELL_BLACK
' 盤面の描画更新
UpdateDisplay
Application.ScreenUpdating = True
End Sub
Sub UpdateDisplay()
Dim i As Integer, j As Integer
For i = 1 To BOARD_SIZE
For j = 1 To BOARD_SIZE
With Cells(i, j)
.ClearContents
If BoardData(i, j) = CELL_BLACK Then
DrawPiece i, j, vbBlack
ElseIf BoardData(i, j) = CELL_WHITE Then
DrawPiece i, j, vbWhite
End If
End With
Next j
Next i
End Sub
Private Sub DrawPiece(r As Integer, c As Integer, colorCode As Long)
' シェイプを利用した石の描画
Dim shp As Shape
Set shp = ActiveSheet.Shapes.AddShape(msoShapeOval, _
Cells(r, c).Left + 5, Cells(r, c).Top + 5, _
Cells(r, c).Width - 10, Cells(r, c).Height - 10)
shp.Fill.ForeColor.RGB = colorCode
End Sub
実務アドバイス:コードの保守性と拡張性を高める
実務におけるVBA開発でも、この「データ構造と表示の分離」は非常に役立ちます。例えば、Excelで複雑な管理表を作る際、シート上の表示形式を頻繁に変える必要があるケースがあるでしょう。今回のように、計算ロジック(BoardData)と描画ロジック(UpdateDisplay)を別々のプロシージャに分けておけば、画面のデザインだけを変えたいときに、計算ロジックを一切触らずに済みます。
また、`Application.ScreenUpdating = False` は必須テクニックです。Excelはデフォルトでセルが書き換わるたびに再描画を行いますが、これを止めるとマクロの実行速度が数倍から数十倍に跳ね上がります。特に今回のようなループ処理を多用するプログラムでは、この一行があるかないかでユーザー体験(待ち時間)が劇的に変わります。
さらに、シェイプの配置に関してですが、`Shapes.AddShape` を繰り返すと、プログラムを再実行するたびに古いシェイプが重なって残ってしまう問題が発生します。実務では必ず「描画前に既存のシェイプを全削除する」か、「特定の名前をつけたオブジェクトを管理する」仕組みを実装してください。今回のサンプルコードでは簡略化していますが、本格的な開発では「ActiveSheet.Shapes.Delete」を初期化プロセスに組み込むことを強く推奨します。
まとめ:次回の展望
今回は、盤面の視覚的な構築と、その裏側にあるデータ構造の基礎を学びました。8×8の配列がメモリ上に存在し、それがセルというインターフェースを通じてユーザーに見える。この仕組みさえ理解できれば、オセロ開発の50%は完了したと言っても過言ではありません。
次回は、いよいよ「石を置く」というインタラクティブなアクションの実装に入ります。`Worksheet_SelectionChange` イベントを利用し、ユーザーがセルをクリックした際に、ルールに基づいた石の配置、そして「相手の石を挟む」というオセロの最も複雑なアルゴリズムである「裏返し処理」を実装していきます。ここからは、条件分岐(If文)とループ(For文)を駆使した、より高度なプログラミングの世界が待っています。ぜひ、今回のコードを動かし、自分なりに色やサイズを変えてカスタマイズしてみてください。手を動かすことこそが、VBA習得の最短ルートです。
