概要
囲碁における「石を取る」という処理は、一見単純に見えて、実はプログラミングにおける「再帰処理」や「グラフ探索」の基礎が凝縮された非常に奥深いテーマです。Twitter(現X)などで出題される「詰碁」や「死活問題」をVBAで自動判定しようと考えたとき、避けて通れないのが「連鎖(グループ)」の概念です。本稿では、盤面上の特定の石から隣接する同色の石を辿り、そのグループが「呼吸点(自由度)」をいくつ持っているかを計算し、呼吸点がゼロになった瞬間に石を盤面から除去するというアルゴリズムを完全解説します。Excelという表計算ソフトを、高度な論理演算プラットフォームへと昇華させる技術を学びましょう。
詳細解説
囲碁の石を取るアルゴリズムを構築する際、もっとも重要なのは「連鎖」の抽出です。ある石を置いたとき、その石と上下左右に隣接する同色の石は、一つの「塊」として扱われます。この塊の中に一つでも空所(呼吸点)があれば、その石は盤上に生き残ります。逆に、塊内のすべての石の周囲に空所が一つもなければ、その石は「取られた」と判定されます。
この処理を実現するためには、以下の3つのステップが必要です。
1. 探索の開始: 置かれた石の座標を起点とする。
2. 再帰的探索(DFS: 深さ優先探索): 上下左右を調べ、同色であればグループに追加し、さらにその隣を調べる。この際、既に探索した石をフラグ管理することで無限ループを防ぐ。
3. 呼吸点のカウント: グループに属するすべての石の隣接セルを調べ、値が「空」であるセルの数を合計する。
VBAにおいてこの探索を行う際、再帰呼び出しは強力ですが、スタックオーバーフローに注意が必要です。しかし、一般的な19路盤であっても、一つのグループが盤面全体を埋め尽くすことは稀ですので、標準的な再帰回数制限(最大1000〜2000程度)であれば十分動作します。
サンプルコード
以下のコードは、19×19のセル範囲(A1:S19)を囲碁盤と見立て、指定した座標の石が属するグループの呼吸点を計算し、死んでいる場合に石を除去するロジックの核となる部分です。
Option Explicit
' 盤面状態:0=空, 1=黒, 2=白
Dim Board(1 To 19, 1 To 19) As Integer
Dim Visited(1 To 19, 1 To 19) As Boolean
Dim Liberties As Integer
Dim TargetColor As Integer
Sub CheckAndRemove(row As Integer, col As Integer)
TargetColor = Board(row, col)
If TargetColor = 0 Then Exit Sub
' 探索初期化
Dim i As Integer, j As Integer
For i = 1 To 19: For j = 1 To 19: Visited(i, j) = False: Next: Next
Liberties = 0
' 探索開始
SearchGroup row, col
' 呼吸点が0なら石を除去
If Liberties = 0 Then
RemoveGroup row, col
End If
End Sub
Sub SearchGroup(r As Integer, c As Integer)
If r < 1 Or r > 19 Or c < 1 Or c > 19 Then Exit Sub
If Visited(r, c) Then Exit Sub
If Board(r, c) = 0 Then
Liberties = Liberties + 1
Exit Sub
End If
If Board(r, c) = TargetColor Then
Visited(r, c) = True
SearchGroup r + 1, c
SearchGroup r - 1, c
SearchGroup r, c + 1
SearchGroup r, c - 1
End If
End Sub
Sub RemoveGroup(r As Integer, c As Integer)
' ターゲットの色を再帰的に0(空)にする
If r < 1 Or r > 19 Or c < 1 Or c > 19 Then Exit Sub
If Board(r, c) <> TargetColor Then Exit Sub
Board(r, c) = 0
Cells(r, c).Value = "" ' セル表示もクリア
RemoveGroup r + 1, c
RemoveGroup r - 1, c
RemoveGroup r, c + 1
RemoveGroup r, c - 1
End Sub
実務アドバイス
実務におけるVBA開発では、上記のアルゴリズムを「高速化」することが鍵となります。特に、毎回の石の配置ごとに盤面全体をスキャンするのは非効率です。
1. 差分更新の活用: 最後に置いた石の周囲4方向のみをチェックし、もし相手の色があればそのグループの呼吸点だけを計算する、というアプローチをとれば計算量は劇的に減ります。
2. 配列とセルの分離: セル(Cells)へのアクセスはVBAで最も重い処理の一つです。ロジックの計算はすべてメモリ上の二次元配列(Array)で行い、結果を最後に一度だけセルへ反映させる手法を徹底してください。これにより、実行速度が100倍以上向上することもあります。
3. デバッグの可視化: 探索中のグループを強調表示するデバッグ用サブルーチンを作っておくと、Twitterで出題された難問の「なぜこの石が取れるのか」というロジック検証に非常に役立ちます。
また、実務的なVBAプロジェクトであれば、クラスモジュールを使って「Stoneクラス」や「Groupクラス」を定義し、オブジェクト指向で設計することをお勧めします。これにより、「石が取られた時の連鎖反応」といった複雑なイベント処理も、コードの可読性を損なわずに記述可能です。
まとめ
Excel VBAで囲碁の石取りアルゴリズムを実装することは、単なるプログラミングの練習を超えた、アルゴリズム的思考の訓練になります。再帰関数を正しく使い、盤面というグラフ構造を論理的に解釈する力は、他の業務自動化ツール開発にも間違いなく活かされます。
今回紹介した「探索→判定→除去」という一連の流れは、囲碁だけでなく、パズルゲームの連鎖判定や、複雑な業務フローにおける依存関係の解析など、ビジネスの現場でも応用可能な汎用的な設計思想です。まずは19路盤の広大な盤面を恐れず、3×3の小さな盤面からロジックを組んでみてください。そして、Twitterの詰碁問題を自分の書いたプログラムが「正解」と判定した時の達成感は、エンジニアとしての確かな成長を実感させてくれるはずです。VBAの限界は、あなたのアルゴリズムの限界でしかありません。今日からぜひ、この挑戦を楽しんでください。
