はじめに
「VBAサンプル集オセロを作りながらマクロVBAを学ぼう」シリーズも、いよいよ№5となりました。これまでの回では、オセロゲームの基本的な構造を理解し、盤面を表現するためのデータ構造や、駒の初期配置、そして簡単な盤面表示の基本を習得しました。今回は、さらに一歩進んで、VBAを使ってオセロ盤面を動的に描画し、駒を配置する具体的な方法に焦点を当てます。
オセロ盤面は、2次元配列で表現するのが一般的ですが、それをExcelのセル上に視覚的に表現するには、セルの色や文字(駒の色を表す)を操作する必要があります。このプロセスをVBAで実装することで、配列操作とExcelオブジェクト操作の連携を深く理解できるでしょう。特に、繰り返し処理(For Each、For Next)や条件分岐(If Then Else)を効果的に活用することが、効率的な盤面描画の鍵となります。
本稿では、以下の内容を詳細に解説していきます。
* オセロ盤面をExcelシート上に描画するVBAコード
* 盤面上の指定された位置に駒を配置するVBAコード
* 駒の色(黒・白)をセルに反映させる方法
* 描画処理を関数化・サブルーチン化する際の注意点
これらの技術を習得することで、単にオセロゲームの盤面を描画するだけでなく、Excel上で複雑な表やグラフを動的に生成する際の応用力も養われます。ぜひ、この機会にVBAのスキルをさらに向上させましょう。
詳細解説:オセロ盤面の描画と駒の配置
オセロ盤面をExcelシート上に描画する基本的な考え方は、シート上の各セルを盤面のマス目に見立て、そのセルの背景色やフォント色を操作することです。オセロ盤は通常8×8なので、Excelシートの特定の範囲(例えばA1からH8)に描画することになります。
1. 盤面描画の準備
まず、描画先のシートを準備します。既存のシートを利用するか、新しいシートを作成して利用するかは、ゲーム全体の設計によります。ここでは、アクティブなシートに描画するものとします。盤面を描画する前に、既存の描画内容をクリアしておくと、再描画時に混乱を防ぐことができます。
Sub ClearBoard()
‘ 描画範囲をクリアする
With ThisWorkbook.Sheets(“Sheet1”) ‘ 描画先のシート名を指定
.Cells.ClearContents ‘ セルの内容をクリア
.Cells.Interior.ColorIndex = xlNone ‘ 背景色をクリア
.Cells.Font.ColorIndex = xlAutomatic ‘ フォント色をリセット
.Cells.Borders.LineStyle = xlNone ‘ 罫線をクリア
End With
End Sub
このコードは、指定したシートの全セルをクリアし、背景色、フォント色、罫線を初期状態に戻します。
2. 盤面のマス目(背景色)の描画
オセロ盤のマス目は、通常、交互に異なる色で塗られています。ここでは、軽快な緑色と白を交互に配置してみましょう。
Sub DrawBoardBackground()
Dim ws As Worksheet
Dim row As Integer
Dim col As Integer
Dim boardColor1 As Integer ‘ マス目の色1 (例: 緑)
Dim boardColor2 As Integer ‘ マス目の色2 (例: 白)
Set ws = ThisWorkbook.Sheets(“Sheet1”) ‘ 描画先のシート名を指定
boardColor1 = RGB(0, 128, 0) ‘ 緑色 (RGB指定)
boardColor2 = RGB(255, 255, 255) ‘ 白色 (RGB指定)
‘ 8×8の盤面を描画
For row = 1 To 8
For col = 1 To 8
‘ 行と列の合計が偶数か奇数かで色を決定
If (row + col) Mod 2 = 0 Then
ws.Cells(row, col).Interior.Color = boardColor1
Else
ws.Cells(row, col).Interior.Color = boardColor2
End If
‘ セルの高さを統一 (任意)
ws.Cells(row, col).RowHeight = 30
‘ セルの幅を統一 (任意)
ws.Cells(row, col).ColumnWidth = 5
Next col
Next row
End Sub
このコードでは、`For row`と`For col`のループを使って8×8のセルを走査します。`(row + col) Mod 2`という条件分岐により、行番号と列番号の合計が偶数か奇数かを判定し、交互に異なる背景色を設定しています。`RGB()`関数を使うと、より多様な色を指定できます。また、`RowHeight`と`ColumnWidth`プロパティでセルのサイズを調整することで、見た目の良い盤面を作成できます。
3. 駒の配置
盤面が描画されたら、次に駒を配置します。駒は、セルのフォント色や文字(例えば「●」や「○」)で表現します。オセロの初期配置は、中央の4マスに白と黒の駒が配置された状態です。
駒を表す定数や変数を用意しておくと、コードが読みやすくなります。
* `PIECE_NONE = 0` (駒なし)
* `PIECE_BLACK = 1` (黒駒)
* `PIECE_WHITE = 2` (白駒)
Sub PlaceInitialPieces()
Dim ws As Worksheet
Dim board(1 To 8, 1 To 8) As Integer ‘ 盤面データを保持する配列 (例)
Set ws = ThisWorkbook.Sheets(“Sheet1”) ‘ 描画先のシート名を指定
‘ 初期配置の盤面データを設定 (例)
‘ 実際には、ゲームロジックでこの配列を操作します
board(4, 4) = 2 ‘ 白
board(4, 5) = 1 ‘ 黒
board(5, 4) = 1 ‘ 黒
board(5, 5) = 2 ‘ 白
‘ 盤面配列に基づいて駒を描画
Call DrawPieces(board)
End Sub
Sub DrawPieces(board() As Integer)
Dim ws As Worksheet
Dim row As Integer
Dim col As Integer
Dim piece As Integer
Set ws = ThisWorkbook.Sheets(“Sheet1”) ‘ 描画先のシート名を指定
For row = 1 To 8
For col = 1 To 8
piece = board(row, col) ‘ 盤面配列から駒の情報を取得
With ws.Cells(row, col)
.ClearContents ‘ 既存の文字をクリア
.Font.Bold = True ‘ 駒を太字にする (任意)
.HorizontalAlignment = xlCenter ‘ 中央揃え
.VerticalAlignment = xlCenter ‘ 中央揃え
Select Case piece
Case 1 ‘ 黒駒
.Value = “●” ‘ 文字で黒駒を表現
.Font.Color = RGB(0, 0, 0) ‘ 黒色
Case 2 ‘ 白駒
.Value = “○” ‘ 文字で白駒を表現
.Font.Color = RGB(255, 255, 255) ‘ 白色
Case Else ‘ 駒なし
‘ 何も表示しない
End Select
End With
Next col
Next row
End Sub
`PlaceInitialPieces` サブルーチンは、オセロ盤の初期配置を表現する2次元配列 `board` を作成し、それを `DrawPieces` サブルーチンに渡します。`DrawPieces` サブルーチンは、渡された盤面配列 `board` を参照し、各セルに駒を表示します。駒がない場合はセルをクリアします。駒の色は `Font.Color` プロパティで設定し、文字で「●」や「○」を表示することで、視覚的に駒を表現しています。
4. 盤面全体を再描画する
ゲームの進行に合わせて盤面が変化するため、盤面全体を再描画するサブルーチンがあると便利です。これは、盤面の背景色を描画する `DrawBoardBackground` と、駒を描画する `DrawPieces` を組み合わせたものです。
Sub RefreshBoard(board() As Integer)
‘ 盤面の背景色を再描画
Call DrawBoardBackground
‘ 駒を再描画
Call DrawPieces(board)
End Sub
この `RefreshBoard` サブルーチンを呼び出すことで、ゲームの各ステップで盤面を最新の状態に更新することができます。
サンプルコード:オセロ盤面操作の統合
これまでの解説を統合し、オセロ盤面を描画し、初期駒を配置する一連のコードを以下に示します。このコードを実行すると、指定したExcelシートにオセロ盤が描画され、初期配置の駒が表示されます。
‘=========================================================
‘ オセロ盤面描画・駒配置サンプル (№5)
‘=========================================================
‘ 駒の種類を定義する定数 (グローバル変数として宣言する場合)
Const PIECE_NONE As Integer = 0
Const PIECE_BLACK As Integer = 1
Const PIECE_WHITE As Integer = 2
Sub Main_DrawOthelloBoard()
Dim ws As Worksheet
Dim board(1 To 8, 1 To 8) As Integer ‘ 盤面データを保持する配列
On Error Resume Next ‘ エラー発生時に処理を続行
Set ws = ThisWorkbook.Sheets(“OthelloBoard”) ‘ 描画用のシート名
If ws Is Nothing Then
‘ シートが存在しない場合は新しく作成
Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = “OthelloBoard”
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
‘ 盤面をクリア
Call ClearBoard(ws)
‘ 盤面の背景色を描画
Call DrawBoardBackground(ws)
‘ 初期配置の盤面データを設定
board(4, 4) = PIECE_WHITE
board(4, 5) = PIECE_BLACK
board(5, 4) = PIECE_BLACK
board(5, 5) = PIECE_WHITE
‘ 駒を描画
Call DrawPieces(ws, board)
MsgBox “オセロ盤面が描画されました!”, vbInformation
End Sub
‘ 盤面描画範囲をクリアするサブルーチン
Sub ClearBoard(ByRef ws As Worksheet)
With ws
.Cells.ClearContents
.Cells.Interior.ColorIndex = xlNone
.Cells.Font.ColorIndex = xlAutomatic
.Cells.Borders.LineStyle = xlNone
‘ セルの幅と高さをリセット (任意)
.Columns.ColumnWidth = 2.5 ‘ 調整可能な値
.Rows.RowHeight = 15 ‘ 調整可能な値
End With
End Sub
‘ 盤面の背景色を描画するサブルーチン
Sub DrawBoardBackground(ByRef ws As Worksheet)
Dim row As Integer
Dim col As Integer
Dim boardColor1 As Long ‘ RGB値はLong型で扱う
Dim boardColor2 As Long
boardColor1 = RGB(139, 69, 19) ‘ 茶色 (例)
boardColor2 = RGB(245, 245, 220) ‘ ベージュ (例)
With ws
For row = 1 To 8
For col = 1 To 8
If (row + col) Mod 2 = 0 Then
.Cells(row, col).Interior.Color = boardColor1
Else
.Cells(row, col).Interior.Color = boardColor2
End If
‘ セルの高さを統一 (任意)
.Cells(row, col).RowHeight = 30
‘ セルの幅を統一 (任意)
.Cells(row, col).ColumnWidth = 5
Next col
Next row
End With
End Sub
‘ 盤面配列に基づいて駒を描画するサブルーチン
Sub DrawPieces(ByRef ws As Worksheet, ByRef board() As Integer)
Dim row As Integer
Dim col As Integer
Dim piece As Integer
With ws
For row = 1 To 8
For col = 1 To 8
piece = board(row, col)
With .Cells(row, col)
.ClearContents
.Font.Bold = True
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.Font.Size = 14 ‘ フォントサイズを調整
Select Case piece
Case PIECE_BLACK ‘ 黒駒
.Value = “●”
.Font.Color = RGB(0, 0, 0) ‘ 黒
Case PIECE_WHITE ‘ 白駒
.Value = “○”
.Font.Color = RGB(255, 255, 255) ‘ 白
Case Else ‘ 駒なし
‘ 何も表示しない
End Select
End With
Next col
Next row
End With
End Sub
この統合サンプルでは、以下の点が改善されています。
* **シート管理:** 「OthelloBoard」という名前のシートを自動的に作成または選択するようにしました。
* **引数渡し:** 各サブルーチンに `Worksheet` オブジェクト (`ws`) を引数として渡すように変更し、汎用性を高めました。
* **定数使用:** 駒の種類を定数 (`PIECE_NONE`, `PIECE_BLACK`, `PIECE_WHITE`) で定義し、コードの可読性と保守性を向上させました。
* **エラーハンドリング:** シートが存在しない場合のエラーを適切に処理しています。
* **色指定:** `RGB()`関数による色指定は `Long` 型で扱うのが一般的です。
実務アドバイス:効率化と応用への道
オセロ盤面を描画する技術は、Excel VBAで様々な視覚的な表現を作成するための基礎となります。以下に、実務で役立つアドバイスをいくつかご紹介します。
1. 盤面データの管理を徹底する
Excelシート上に盤面を描画するだけでなく、盤面の状態(どのマスにどの駒があるか)をVBAの2次元配列で管理することが非常に重要です。この配列がゲームの「真実」となり、画面表示はその配列を反映する形になります。これにより、ゲームロジック(駒の配置、ひっくり返し処理など)と画面描画処理を分離でき、コードの見通しが格段に良くなります。
‘ 盤面データをグローバル変数またはモジュールレベル変数として宣言
Public g_board(1 To 8, 1 To 8) As Integer
このようにグローバル変数やモジュールレベル変数で盤面データを宣言しておくと、どのサブルーチンからでもアクセスできるようになり、コードの連携が容易になります。
2. 描画処理の関数化・サブルーチン化
今回のサンプルコードでも行いましたが、盤面の描画処理を独立したサブルーチン (`DrawBoardBackground`, `DrawPieces`) に分けることで、コードの再利用性が高まります。また、必要に応じて特定のマスだけを更新するような、より詳細な描画サブルーチンを作成することも可能です。
例えば、駒を置いたマスだけを更新するサブルーチンは以下のようになります。
Sub UpdatePiece(ByRef ws As Worksheet, row As Integer, col As Integer, pieceType As Integer)
Dim targetCell As Range
Set targetCell = ws.Cells(row, col)
With targetCell
.ClearContents
.Font.Bold = True
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.Font.Size = 14
Select Case pieceType
Case PIECE_BLACK
.Value = “●”
.Font.Color = RGB(0, 0, 0)
Case PIECE_WHITE
.Value = “○”
.Font.Color = RGB(255, 255, 255)
Case PIECE_NONE
‘ 何も表示しない
End Select
End With
End Sub
この `UpdatePiece` サブルーチンを使えば、盤面全体を再描画するよりも高速に、変更があったマスだけを更新できます。
3. パフォーマンスの考慮
Excel VBAは、大量のセル操作を行うとパフォーマンスが低下する傾向があります。特に、盤面全体を何度も再描画するような処理は、時間がかかることがあります。
* **`Application.ScreenUpdating = False`**: 描画処理の前後で画面更新を無効にすると、処理速度が向上します。
* **`Application.Calculation = xlCalculationManual`**: 数式が多く含まれるシートで数式計算を一時的に無効にすると、パフォーマンスが改善されることがあります。
Sub RefreshBoardOptimized(ByRef ws As Worksheet, ByRef board() As Integer)
Application.ScreenUpdating = False ‘ 画面更新を停止
Application.Calculation = xlCalculationManual ‘ 計算を一時停止
‘ 盤面の背景色を再描画
Call DrawBoardBackground(ws)
‘ 駒を再描画
Call DrawPieces(ws, board)
Application.Calculation = xlCalculationAutomatic ‘ 計算を再開
Application.ScreenUpdating = True ‘ 画面更新を再開
End Sub
これらの最適化テクニックは、ゲームが複雑化し、描画処理が増えるにつれてその効果を発揮します。
4. ユーザーインターフェースの向上
駒を配置するだけでなく、マウスイベントを使って駒を置けるようにしたり、合法手を表示したりする機能を追加すると、よりゲームらしくなります。これは `Worksheet_SelectionChange` や `Worksheet_BeforeDoubleClick` といったイベントプロシージャを活用することで実現できます。
例えば、セルがダブルクリックされたら、そのマスに駒を置く処理を呼び出すといった実装が考えられます。
‘ シートモジュールに記述
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim selectedRow As Integer
Dim selectedCol As Integer
‘ ダブルクリックされたセルが盤面内かチェック
If Target.Row >= 1 And Target.Row <= 8 And Target.Column >= 1 And Target.Column <= 8 Then
selectedRow = Target.Row
selectedCol = Target.Column
' ここで、合法手チェックなどのロジックを挟む
' 例: If IsLegalMove(selectedRow, selectedCol) Then
' Call PlaceAndFlipPiece(selectedRow, selectedCol) ' 駒を置き、ひっくり返す処理
' Call RefreshBoard(g_board) ' 盤面を更新
' End If
' ユーザーが編集しないようにダブルクリックイベントをキャンセル
Cancel = True
End If
End Sub
このように、イベントプロシージャと連携させることで、インタラクティブなExcelアプリケーションを構築できます。
まとめ
本稿では、「VBAサンプル集オセロを作りながらマクロVBAを学ぼう №5」として、オセロ盤面の描画と駒の配置に焦点を当て、具体的なVBAコードと共に解説しました。
* Excelシートのセルをマス目に見立て、`Interior.Color` プロパティで背景色を、`Font.Color` および `Value` プロパティで駒の色と形状を表現する方法を学びました。
* `For` ループと `If` 文を組み合わせることで、交互の色を持つ盤面や、指定された位置への駒の配置を効率的に実装できることを確認しました。
* 駒の種類を定数で定義することの重要性や、盤面データをVBA配列で管理するアプローチの有効性についても触れました。
* さらに、描画処理をサブルーチン化すること、パフォーマンス最適化のテクニック(`ScreenUpdating`、`Calculation`)、そしてイベントプロシージャとの連携によるインタラクティブな操作の可能性についても言及しました。
これらの技術は、オセロゲームに限らず、Excel上で様々な表形式のデータを視覚的に表現したり、簡易的なシミュレーションツールを作成したりする際に非常に役立ちます。VBAの学習は、単にマクロを記録・実行するだけでなく、このように具体的なアプリケーションを設計・実装していくことで、より実践的で応用力のあるスキルへと昇華していきます。
次回も、オセロゲーム開発を通じて、さらに実践的なVBAのテクニックを探求していきますので、ご期待ください。
