概要
Excel VBAは単なる事務作業の自動化ツールではありません。その柔軟なオブジェクトモデルとプログラミング能力を駆使すれば、複雑なロジックを要する「麻雀ゲーム」さえも構築可能です。本稿では、VBAを用いて麻雀の牌構成、配牌アルゴリズム、そして役判定という、ゲーム開発における難所をどのように突破すべきかを詳述します。単なるサンプルコードの提示にとどまらず、メモリ効率と可読性を両立させたアーキテクチャ設計に焦点を当てます。
詳細解説:麻雀ロジックの核となるデータ構造
麻雀ゲーム開発において最も重要なのは「牌をいかに管理するか」という点です。初心者はついセルの位置情報で牌を管理しようとしますが、これは拡張性を損なう悪手です。プロフェッショナルな設計では、牌を1から34の整数値(萬子1-9、筒子1-9、索子1-9、字牌1-7)にマッピングし、配列としてメモリ上で管理します。
1. 牌の表現:1~34のID管理
– 1-9: 萬子
– 10-18: 筒子
– 19-27: 索子
– 28-34: 字牌(東南西北白發中)
このマッピングを行うことで、役判定時の「順子(シュンツ)」チェックが非常に容易になります。例えば、IDが連続しているかを確認するだけで、順子の判定が完了するからです。
2. シャッフルアルゴリズム
ExcelのRnd関数を用いる際、単なるランダムソートでは偏りが生じることがあります。フィッシャー・イェーツ・シャッフル(Fisher-Yates Shuffle)アルゴリズムを実装し、136枚の牌を完全にランダム化することが不可欠です。
3. 役判定の深淵
役判定は「再帰呼び出し」を駆使した探索アルゴリズムが最適です。手牌14枚から「雀頭」を確定させ、残りの12枚を「刻子(コーツ)」または「順子(シュンツ)」に分解できるかを再帰的に判定します。この際、バックトラッキングの手法を用いることで、効率的に役の有無を検証できます。
サンプルコード:牌の生成と初期化
以下のコードは、麻雀の牌を生成し、ランダムにシャッフルする基礎モジュールです。
Option Explicit
' 牌の総数
Public Const TOTAL_TILES As Integer = 136
' 牌のシャッフルと配牌の初期処理
Sub InitializeMahjongGame()
Dim tiles(1 To TOTAL_TILES) As Integer
Dim i As Integer, j As Integer, temp As Integer
Dim rndIndex As Integer
' 牌のIDを生成 (34種を4枚ずつ)
For i = 1 To TOTAL_TILES
tiles(i) = ((i - 1) Mod 34) + 1
Next i
' フィッシャー・イェーツ・シャッフル
Randomize
For i = TOTAL_TILES To 2 Step -1
rndIndex = Int(Rnd * i) + 1
temp = tiles(i)
tiles(i) = tiles(rndIndex)
tiles(rndIndex) = temp
Next i
' デバッグ用出力:シートの1行目に牌を表示
For i = 1 To 14
Cells(1, i).Value = GetTileName(tiles(i))
Next i
End Sub
' 牌IDから名称へ変換するヘルパー関数
Function GetTileName(id As Integer) As String
Dim names As Variant
names = Array("", "1萬", "2萬", "3萬", "4萬", "5萬", "6萬", "7萬", "8萬", "9萬", _
"1筒", "2筒", "3筒", "4筒", "5筒", "6筒", "7筒", "8筒", "9筒", _
"1索", "2索", "3索", "4索", "5索", "6索", "7索", "8索", "9索", _
"東", "南", "西", "北", "白", "發", "中")
GetTileName = names(id)
End Function
実務アドバイス:VBAゲーム開発の注意点
VBAでゲームを作成する際、最大のボトルネックは「描画速度」です。セルに直接画像を表示させたり、Shapeオブジェクトを多用したりすると、画面のチラつき(フリッカー)が発生します。これを防ぐためのテクニックをいくつか紹介します。
1. Application.ScreenUpdatingの制御
描画処理の前には必ず`Application.ScreenUpdating = False`を宣言し、処理終了後に`True`に戻してください。これにより、処理速度が飛躍的に向上します。
2. イベント駆動の活用
ゲームの進行にはボタン(CommandButton)のクリックイベントだけでなく、`Worksheet_SelectionChange`イベントを活用し、ユーザーがセルを選択したタイミングで牌を打つといった直感的なUIを設計することも可能です。
3. クラスモジュールの活用
「牌」というオブジェクトをクラスモジュール化することで、コードの保守性が格段に上がります。「牌の色」「状態(裏向きか表向きか)」といったプロパティをカプセル化することで、複雑なロジックをクラス内に隠蔽し、メインプロシージャをシンプルに保つことができます。
4. 役判定の最適化
役判定ロジックは最も負荷がかかる箇所です。全ての組み合わせを力技で検証するとPCの動作が重くなります。まずは「手牌の数」をカウントする配列を作成し、その「数」に基づいた枝刈り(Pruning)を行うことが、快適な動作を実現する鍵となります。
まとめ
VBAによる麻雀ミニゲームの開発は、プログラミングスキルの総合力が試される素晴らしいプロジェクトです。データの管理方法、アルゴリズムの選定、そしてユーザーインターフェースの設計まで、一貫したアーキテクチャを意識することで、Excelは単なる事務ツールを超えた「アプリケーション開発プラットフォーム」へと変貌します。
本稿で解説した牌のID管理と再帰的な役判定は、麻雀のみならず他の複雑なボードゲーム開発にも応用可能な汎用技術です。まずは基本的な配牌システムから実装を始め、徐々に役判定や点数計算へと拡張していってください。VBAという限られた環境でいかに効率的なロジックを組むか。その試行錯誤こそが、あなたを真のVBAエンジニアへと成長させるはずです。Excelというキャンバスに、あなただけの麻雀の世界を構築しましょう。
