【VBAリファレンス】VBAサンプル集Excel将棋:終局(詰み)判定と打ち歩詰め(№16)

スポンサーリンク

Excel VBAで構築する将棋エンジン:終局判定と禁じ手「打ち歩詰め」の実装

将棋プログラムをExcel VBAで開発する際、最も難易度が高く、かつ重要なのが「ルールの厳密な実装」です。特に、対局の終了条件である「詰み」の判定と、反則負けを定義する「打ち歩詰め」の処理は、盤面管理の深淵に触れる部分です。本稿では、オブジェクト指向的なアプローチを取り入れつつ、効率的かつ堅牢な終局判定ロジックを解説します。

終局判定のアルゴリズム:王手と合法手の関係性

将棋における終局(詰み)とは、「王手が掛かっており、かつ、その王手を解除する合法手が一つも存在しない状態」を指します。これをプログラムで判定するには、以下のステップを順に踏む必要があります。

1. 現在の盤面において、敵の駒が自陣の玉に利いているか(王手の検知)。
2. 王手が掛かっている場合、玉を逃がす、合駒をする、王手をしている駒を取る、という3つの対応策をシミュレートする。
3. すべての対応策を試した結果、依然として王手が掛かっている状態が続く場合のみ「詰み」と判定する。

この処理において重要なのは、盤面を書き換えては戻す「バックトラック(再帰的探索)」の考え方です。VBAにおいては、盤面を配列としてコピーし、シミュレーション後に破棄することで、メインの対局状態を汚さずに判定を行うのが定石です。

打ち歩詰め判定の技術的詳細

打ち歩詰めは、日本将棋連盟のルールの中でも特に例外が多く、実装を複雑にする要因です。定義は「歩を打つことによって、相手の玉が詰む状態」ですが、以下の条件をすべて満たす場合のみ反則となります。

– 打った歩が、相手の玉に対して直接王手になっていること。
– その歩が取れないこと。
– その歩が他の利きによってサポートされていないこと。
– 相手の玉が、その歩を取る以外に逃げ道がないこと。

これを実装する際は、まず「歩を打つ」という操作を仮定し、盤面を更新した直後に「詰み判定関数」を呼び出すのが最も効率的です。もしその結果が「詰み」であれば、その手は「打ち歩詰め」であり、反則として処理を拒否します。

実装サンプルコード:終局判定と打ち歩詰めの検証

以下に、盤面を走査し、現在の状態が「詰み」であるかを判定するプロシージャの骨子を示します。


' 詰み判定のメイン関数
Public Function IsCheckmate(ByVal turn As Integer) As Boolean
    Dim boardBackup As Variant
    boardBackup = CurrentBoard ' 現在の盤面を退避
    
    ' 自分の王の現在地を取得
    Dim kingPos As Long
    kingPos = FindPiece(turn, KING)
    
    ' 王の逃げ場所、合駒、駒取りをすべて試行
    Dim moveList As Collection
    Set moveList = GenerateAllLegalMoves(turn)
    
    Dim move As Variant
    For Each move In moveList
        ' 盤面を更新
        ApplyMove move
        
        ' 相手のターンで王手が掛かっていないか確認
        If Not IsUnderAttack(GetKingPos(turn), GetOpponent(turn)) Then
            ' 合法手が存在するため詰みではない
            RestoreBoard boardBackup
            IsCheckmate = False
            Exit Function
        End If
        
        ' 盤面を戻す
        RestoreBoard boardBackup
    Next move
    
    ' すべての手を試しても王手が解除できない=詰み
    IsCheckmate = True
End Function

' 打ち歩詰めチェック用のラッパー
Public Function IsForbiddenMove(ByVal move As Move) As Boolean
    If move.PieceType = FU And move.IsDrop Then
        ' 歩を打つ手の場合、一時的に盤面に配置
        ApplyMove move
        If IsCheckmate(Opponent) Then
            ' 打ち歩詰めの成立を確認
            UndoMove move
            IsForbiddenMove = True
            Exit Function
        End If
        UndoMove move
    End If
    IsForbiddenMove = False
End Function

実務的アドバイス:パフォーマンスと保守性の両立

VBAで将棋エンジンを開発する場合、最大の敵は実行速度です。盤面のコピー処理(配列のコピー)は非常にコストが高いため、大規模な探索を行う場合は、配列を直接操作するのではなく、ビットボード(Bitboard)技術の導入を検討してください。

ビットボードとは、64マスを8バイト(LongLong型)の数値として表現する手法です。これにより、盤面の状態を「AND」「OR」「XOR」「シフト演算」といったCPUレベルの高速処理で判定できるようになります。VBAのLongLong型(64bit)は、将棋盤の表現に最適です。

また、コードの保守性を高めるために、ルール判定ロジックを独立したクラスモジュール(例:`clsRuleEngine`)に切り出すことを強く推奨します。これにより、将来的に「二歩」や「千日手」といった他の反則ルールの追加が容易になり、メインの対局管理プログラムが複雑化するのを防げます。

まとめ:ロジックの積み重ねが最強のエンジンを作る

Excel VBAを用いた将棋プログラムの開発は、一見すると不向きな環境に思えるかもしれませんが、実はプログラミングの基礎と論理的思考を鍛えるには最高の教材です。

終局判定は、単なる条件分岐の羅列ではなく、盤面という閉じた世界における「数学的な証明」です。「打ち歩詰め」のような例外ルールを一つずつ確実に実装していくプロセスこそが、バグの少ない堅牢なシステム構築に繋がります。

今回紹介したバックトラック法や、将来的なビットボードへの拡張を意識することで、あなたのVBA将棋エンジンは、単なる「動くおもちゃ」から、本格的な対局シミュレータへと進化を遂げるでしょう。まずは、小さな盤面(3×3など)でこれらの判定ロジックが正しく機能するかをテストし、徐々に正規の9×9盤面へと拡張していくアプローチを強くお勧めします。プロフェッショナルなエンジニアとして、コードの美しさと論理の正確さを追求し続けてください。

タイトルとURLをコピーしました