koba::blog

小林聡: プログラマです

向聴数を求めるプログラム(一般手編(再))

4面子1雀頭形の向聴数(シャンテン数)計算は 向聴数を求めるプログラム - koba::blog で取り上げているけれど、もう一度おさらい。

基本は

  • 向聴数 = 8 ー 面子の数 × 2 ー 搭子の数

でよいのだが、考慮すべきことがいくつかある。

雀頭がない場合

一萬二萬三萬八萬九萬四筒五筒六筒一索二索七索八索九索東

この牌姿は3面子2搭子なので公式に当てはめると聴牌なのだが、雀頭がないので実際には 1搭子が使えず1向聴となる。

搭子過多の場合

一萬二萬三萬八萬九萬四筒五筒六筒一索二索八索九索東東

この牌姿は6ブロック形の搭子過多*1のケース。2面子4搭子あるので公式に当てはめるとこれも聴牌なのだが、実際には雀頭をのぞくと面子+搭子は4つまでしか使えないため、この分を補正して1向聴とする必要がある。

搭子不足の場合

一萬三萬三萬三萬四萬五萬五萬六萬八萬南西發中中

以前も出した例。この牌姿の場合、中中雀頭としてのぞいて 三萬三萬三萬四萬五萬六萬 の2面子(搭子なし)とすれば3向聴だが、実際には 三萬四萬五萬 の1面子だけとって 一萬三萬三萬五萬六萬八萬 の3搭子を残せば2向聴と計算できる。つまり、面子をとれるだけとってはダメで、場合によっては搭子を多く残す必要もあるということ。

面子のとり方

面子のとり方もいろいろとややこしい。

二筒二筒二筒三筒四筒五筒 の場合、二筒二筒二筒三筒四筒五筒 の2面子に分けるのが正解だが、二筒三筒四筒 の順子を先にとってしまうと 二筒二筒五筒 が残ってしまう。

刻子を先にとればいいかというと、そういう訳でもなく 二筒三筒四筒四筒四筒五筒六筒 から 四筒四筒四筒 を先にとると 二筒三筒五筒六筒 の2搭子が残るが、この場合は 二筒三筒四筒四筒五筒六筒 の2面子をとって 四筒 を孤立牌として残すのが正解。

では先頭から貪欲にとれるものをとっていけばいいのかというとそれも違い、一筒二筒二筒二筒三筒四筒五筒 の先頭から 一筒二筒三筒 をとると 二筒二筒四筒五筒 が残るが、もちろんこの場合は 二筒二筒二筒三筒四筒五筒 の2面子をとって 一筒 を残さなければならない。

結局バックトラックを用いないうまい方法はなく、正直に

  1. 面子を(敢えて)とらない
  2. 順子として面子をとる
  3. 刻子として面子をとる

の3パターンについてバックトラックを使ってすべて試し、最適なものを選ぶしかない。

考慮すべきことはこんなところだけれど、長くなってしまったので実際のプログラムは次回に。

*1:一般的には面子オーバーと言うかな