概要:将棋における「成る」という特殊ルールの実装
将棋プログラムをExcel VBAで構築する際、最もロジックが複雑化しやすく、かつバグを誘発しやすいのが「駒の成る(プロモーション)」処理です。単に駒の画像や文字を差し替えるだけでなく、成った後の移動範囲の変化、さらには持ち駒になった際に元の状態に戻すという「可逆性」の管理が重要になります。本稿では、VBAを用いた将棋開発の第11回目として、盤上の駒が敵陣に侵入した際の「成る・成らない」の判定と、それに対応するデータ構造の更新処理を徹底解説します。
詳細解説:成りの判定基準とデータ管理
将棋のルールにおいて、駒が成るためには「自分の駒が敵陣(3段目以内)に侵入する、または敵陣から出る」という移動の完了がトリガーとなります。VBAでこれを実装するには、以下の3つのステップが必要です。
1. 移動先座標の判定:移動先が敵陣の行(先手なら1~3行目、後手なら7~9行目)に含まれているか。
2. ユーザーへの確認:駒を動かす際、成る権利がある場合に「成りますか?」というダイアログを表示するか、自動判定のフラグを立てるか。
3. 駒のID変換:駒の種類を保持する配列やセル値に対し、成った状態に対応するID(例:「歩」を「と金」へ)を書き換える。
特に重要なのは「駒のID管理」です。私は開発において、駒を「1~14」の数値で管理し、成った状態を「101~114」のようにオフセットを加えて定義する方法を推奨しています。これにより、条件分岐が簡素化され、コードの可読性が飛躍的に向上します。
サンプルコード:成る処理の実装
以下に、選択した駒の移動先が敵陣である場合に、駒のIDを変換して盤面を更新する標準的なコードを示します。
' 駒を成る処理のメイン関数
' komaID: 駒の現在のID
' targetRow: 移動先の行
' isSente: 先手かどうか
Public Function PromoteKoma(ByVal komaID As Integer, ByVal targetRow As Integer, ByVal isSente As Boolean) As Integer
Dim isEnemyTerritory As Boolean
' 敵陣判定ロジック
If isSente Then
If targetRow <= 3 Then isEnemyTerritory = True
Else
If targetRow >= 7 Then isEnemyTerritory = True
End If
' 成る権利がある場合、ユーザーに確認(または自動判定)
' 今回は簡略化のため、特定の駒種であれば無条件で変換するロジックを例示
If isEnemyTerritory Then
Select Case komaID
Case 1: PromoteKoma = 11 ' 歩 -> と金
Case 2: PromoteKoma = 12 ' 香 -> 成香
Case 3: PromoteKoma = 13 ' 桂 -> 成桂
Case 4: PromoteKoma = 14 ' 銀 -> 成銀
Case 6: PromoteKoma = 16 ' 角 -> 竜馬
Case 7: PromoteKoma = 17 ' 飛 -> 竜王
Case Else: PromoteKoma = komaID ' 成れない駒はそのまま
End Select
Else
PromoteKoma = komaID
End If
End Function
' 盤面更新のトリガーとなるプロシージャ
Sub MoveAndPromote(fromCell As Range, toCell As Range)
Dim currentID As Integer
currentID = GetKomaID(fromCell)
' 成る判定を実行
Dim newID As Integer
newID = PromoteKoma(currentID, toCell.Row, IsSentePlayer())
' 盤面配列と表示の更新
UpdateBoardArray toCell.Row, toCell.Column, newID
RefreshBoardDisplay
End Sub
実務アドバイス:バグを防ぐための設計思想
VBAで将棋を開発する際、最も陥りやすい罠は「盤面の状態と配列の不一致」です。特に「成る」処理は、移動・成る・表示更新という複数の工程が絡むため、途中でエラーが発生すると盤面の整合性が崩れます。
1. トランザクション処理:移動と成りの処理は一括して行い、途中でエラーが発生した場合はロールバックできる設計にする。
2. 状態の可視化:イミディエイトウィンドウに「どの駒がどの座標で成ったか」をデバッグ出力する習慣をつけましょう。
3. 成りの取り消し(持ち駒):駒を取った際に、成った状態の駒を元のIDに戻す関数(DemoteKoma)を必ず用意してください。これを忘れると、持ち駒にした際に「と金」がそのまま持ち駒として盤面に置かれるという致命的なバグになります。
また、Excelのシート上で駒を表示している場合、条件付き書式やShapeオブジェクトの差し替えを多用することになりますが、これらは計算負荷が高いです。頻繁に更新が発生する「成る」処理では、描画のタイミングを制御する「Application.ScreenUpdating = False」を適切に活用することが、滑らかな操作感を実現する秘訣です。
まとめ:Excel VBA将棋の完成度を高めるために
「駒を成る」ロジックは、将棋プログラムの心臓部の一つです。単純な条件分岐に見えますが、その背後には「駒の属性管理」「敵陣判定」「可逆性の確保」という、プログラミングの基礎かつ奥義が詰まっています。
今回紹介したID変換の手法は、他の多くのゲーム開発や業務アプリケーションでのステータス管理にも応用可能です。もし、さらに高度な実装を目指すのであれば、成るか成らないかをプレイヤーが選択する「ユーザーフォーム」の呼び出し処理を追加してみてください。
Excelは単なる表計算ソフトではありません。VBAを駆使すれば、今回のような論理的思考を要するゲームエンジンの構築も十分に可能です。本講座のコードをベースに、自分だけの将棋システムを完成させてください。次回の第12回では、いよいよ「王手・詰みの判定」という、将棋プログラムの最大の難関に挑みます。引き続き、コードの研鑽に励みましょう。
