麻雀ネタその2。
Rubyで麻雀のアガリを判定するスクリプトを書きました。
途中まで自力で書いてたんですけど、効率的な書き方ができそうになかったので、以下の記事を参考にしました。
というか、ほとんどRubyでリライトしただけです。
意外とややこしいんですよねー…。
詳細は割愛しますが、ざっくり言うとまず雀頭の2枚を固定して、残りの12枚が3枚セット×4の形になってるかどうか判定するんですが…。
① 刻子(同じ牌の3枚セット)のチェック(消去)→順子(連続する3枚の牌のセット)のチェック (消去)
② 順子(3連続)のチェック→刻子(3枚セット)のチェック
③ 刻子(3枚セット)を1組だけ消去→順子のチェック
の3とおりのチェックをしてやる必要があります。
たとえば雀頭を除いた残りの12枚が「111123567999」だった場合、
①のチェックに従ってやると、
1と9に3枚のセットがあるので消去します。(この時点で残りは「123567」)
続いて、123と567が3連続になっているので消去します。
これですべての数字が消去できたのでアガリの形になっていると判定します。
大抵の場合はこのチェックだけで正しく判定できるんですが、まれにこれだけでは正しく判定できない場合があります。
たとえば、雀頭を除いた残りの12枚が「122233344777」だった場合、
①のチェックに従ってやると、
2と3と7に3枚のセットがあるので消去します。(この時点で残りは[144])
残りの3枚には3連続の形はありませんので、これ以上消去できません。
これだと[144]が残ってしまうので、アガリではないと判定されてしまいます。
この場合は、②のように先に順子(3連続)をチェックしてやらないとうまくいきません。
「122233344777」から3連続の形を探すと「123」「234」「234」が存在することがわかります。
これらを消去すると残りは「777」になります。
「777」は3枚同じ数字のセットになっているので消去できます。
これですべての数字が消去できたので、今度はアガリの形になっていると正しく判定できました。
さらに複雑なパターンもあります。
リンク先にも示されていますが「222334455567」のようなパターンです。
まず①の方法でチェックしてみます。
「222334455567」から3枚セットを探してみると2と5が3枚セットになっているので消去します。
すると「334467」が残ります。
これには3連続の形がありませんので、アガリではないと判定されます。
続いて②の方法を試してみます。
「222334455567」から3連続となっている形を探してみると「234」「234」「567」が3連続の形になっているので消去します。
すると「255」が残ります。
これには3枚セットの形がありませんので、やはりアガリではないと判定されます。
①の方法でも②の方法でもうまくいかなかったので、新しい方法を考えてやる必要がありますが、それが③の方法です。
3枚セットをすべて消去するのではなく1組だけ消去してやる方法です。
「222334455567」から最初に見つかる3枚セットは2の3枚セットなので、それを消去します。
すると「334455567」が残ります。
ここから3連続の形を探すと「345」「345」「567」が見つかるので、それらを消去します。
これですべての数字を消去することができたので、めでたくアガリ形であると判定されました。
…というのが、リンク先のアルゴリズム(の一部)なんですが、このやり方で本当に網羅できているのかはよくわかりません。(-_-;;; )
まー私よりはるかに自頭のいい方が書いてるブログなので、きっと網羅されているのでしょう。(権威主義)
久しぶりにしっかり頭を使った気がします。
図とか入れたほうがいいんでしょうけど、そこまでやる気力がないです。
カロリーメイトください。