七並べ(しちならべ、七ならべとも書く)は古典的なトランプゲームの一種。 ババを使ったりの変種も多い。 最近はオンラインで無料で遊べるサービスも多い。
ここでは、七並べ for Palmに対抗するアルゴリズムを考えてみる。意外に奥が深い (人間が「遊べる」ゲームだから奥が深いのは当り前か)。
七並べ や 7並べ や Fantan domino (英語名) で探してみたが、 具体的なアルゴリズムに触れたサイトは無かった。
7並べ(FANTAN DOMINO) (JavaScriptで遊ぶカードゲーム#4)のページによると「アルゴリズムを調べていて、基本ルールだけでは手札が配られた時点で既に決着が付いていることが分かりました。」と書かれているが、具体的なアルゴリズムが書かれていないので検証できない。
(このページ、移転していて、この文章があったページが見つかりません...)
私見では、相手が複数人の場合、こちらの置き方によりゲームの結果が変わることが有り得るので必ずしも決着が付くとは言えないと思う。
なぜ、あなたはJavaでオブジェクト指向開発ができないのかが7並べを題材にしている。
七並べにはさまざまな派生ルールがある。 Wikipedia:7並べが詳しいので、 ここではルールの詳細については割愛する。
ここでは、「七並べ for Palm」のルールに従って考えることにする。 ルールの概要は以下の通り。
勝ち人数 | 1位 | 2位 | 3位 | 4位 |
---|---|---|---|---|
1人勝ち | +5 | 0 | -2 | -3 |
2人勝ち | +3 | +2 | -2 | -3 |
3,4人勝ちは何点なのかわかりません... |
「七並べ for Palm」の表示が簡潔でわかりやすいのでそれを採用する。
S .*...*789*..* H ...*567....*. D ...*.67.....* C ....*.78..*..
自分の手札はS2,S6,ST,SKなど。
なお、アルゴリズムは札の種類に依存しないし、場は左右対象であるため、 7->K方向の列が8つあると考えて構わない。以下、それで記述する。
1. 自分が札を置ける場所の数を減らさず、相手が札を置ける場所が増えない札を置く。
78***..
上記のように、札が連続している場所に置く。
自分が札を置ける場所の数が減らないのは連続している場合のみである。
2. 相手が札を置ける場所が増えない札を置く。
789TJ*K
上記のように、自分の札がその列の最後の札である場所に置く。
自分の札が最後の札でない場合は、札の右に空きがある。
3. 相手が札を置ける場所がなるべく増えない札を置く。 その札を置くことで、自分の札が置きやすくなる場合はそこを優先する。
S 78*..*K H 789*..K D 7*...*K C 78*...K
上記の場合は、S9 -> HJ -> D8 -> C9 の順に置く。 (HJとD8の順序はこれでいいのだろうか?)
S 7*.**QK H 7*.*.*K D 7*.*JQK C 7*.*.QK
この場合はS8 -> H8 -> D8 -> C8 ではないか。 (本当? H8とD8はどっちが有利なんでしょう...)
以上で、次にどの札を置くべきかの順位付けは終りである。
パスについてはよくわからないのだが、経験則を書く。
前述の順序で、1,2の場合はそこに置けば良い。 したがって問題になるのは3の場合だけである。
本当に空き数だけでパスする/しないを決めていいのかは謎。
S 789*... H 789T*..
上記の場合、HJにまず置く。その後、パスが2以下でSTしか置けない状況であれば パスする。
各列は89TJQKの6箇所しかなく、それぞれの箇所は「既に札が置かれている」 「自分が札を置ける」「相手が札を置ける」の3通りの可能性しかない。 したがって、各列ごとに3^6(=729通り)の場面しかない。 それぞれに評価点を与え、遺伝的アルゴリズムを応用すれば解けてしまうのでは ないだろうか。zuのアルゴリズムの自明な場合(1,2)を省けばもっと場合は 少ないし。
パスに付いては、空き数と互いのパス数をパラメータにすればなんとかなるような。
上記のアルゴリズムでPalm相手にはそこそこの戦いができるが、 これでは人間様の面子が立たない。「パスをするタイミング」と 「相手がどこに置いたかを把握」することが必要であろう。