自分が遊んだゲームのことなどを中心に、適当に書いています。
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
大分前にやりかけていた自分用の麻雀のプログラムを作るのを最近ちょっと再開したのですが、麻雀は聴牌・待ちを判断するのが大変だよなあと改めて思ったので、ちょっと参考になるものがないか、インターネットを検索していました。
そうしたら面白そうな記事を見つけました。
makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ
makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (2/2) - ITmedia エンタープライズ
これの記事の2の方で使用する麻雀牌は萬子だけで門前で槓子は無し、
という条件で1~9の13文字の文字列を受け取って
全ての待ちを出力するプログラムを書けという問題が出ていました。
記事によると、中学生・高校生・大学生の人に解かせて全員3時間以内に回答できて
最短の人は40分程度で解いたそうです、すごいですね。
こういう簡単な場合のプログラムが書けないようでは、
麻雀牌全体での待ちを調べるプログラムなんか書けっこないですし、
自分も毎日仕事でプログラムを書いたり読んだりしているので、
とりあえず考えてみることにします。
プログラム作成や調査の遅さや、根本的な不具合をだしてよく注意されるので
自分のコーディング能力じゃ駄目そうだなあ、と思うし
自分の能力の無さを痛感して絶望するのも怖いので
とりあえずプログラムは書かずに方針を考えるだけ。
以下考えたことをだらだら書いています。
そうしたら面白そうな記事を見つけました。
makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ
makeplex salon:あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (2/2) - ITmedia エンタープライズ
これの記事の2の方で使用する麻雀牌は萬子だけで門前で槓子は無し、
という条件で1~9の13文字の文字列を受け取って
全ての待ちを出力するプログラムを書けという問題が出ていました。
記事によると、中学生・高校生・大学生の人に解かせて全員3時間以内に回答できて
最短の人は40分程度で解いたそうです、すごいですね。
こういう簡単な場合のプログラムが書けないようでは、
麻雀牌全体での待ちを調べるプログラムなんか書けっこないですし、
自分も毎日仕事でプログラムを書いたり読んだりしているので、
とりあえず考えてみることにします。
プログラム作成や調査の遅さや、根本的な不具合をだしてよく注意されるので
自分のコーディング能力じゃ駄目そうだなあ、と思うし
自分の能力の無さを痛感して絶望するのも怖いので
とりあえずプログラムは書かずに方針を考えるだけ。
以下考えたことをだらだら書いています。
■まずセットになる組み合わせは下記の通りになる ・刻子:111,222,333,444,555,666,777,888,999 ・順子:123,234,345,456,567,678,789 ・雀頭:11,22,33,44,55,66,77,88,99 ・待ち シャボ :11,22,33,44,55,66,77,88,99 両面・嵌張・辺張:12,13,23,24,34,35,45,46,56,57,67,68,78,79,89 単騎 :1,2,3,4,5,6,7,8,9 ■探索の無駄を省くことを考えずに全部調べようとすれば、 待ちの探索プログラムの動きはこんな感じだろうか。 例.入力:"1112345678999"が来たときの調べ方 刻子を探す→(111)、残り"2345678999" 刻子を探す→(999)、残り"2345678" 順子を探す→(234)、残り"5678" 順子を探す→(567)、残り[8]→(111)(999)(234)(567)[8] 順子を探す→(678)、残り[5]→(111)(999)(234)(678)[5] 順子を探す→(345)、残り"2678" 順子を探す→(678)、残り[2]→(111)(999)(345)(678)[2] 順子を探す→(456)、残り"2378" 順子・刻子・雀頭が無いので待ちが無い 順子を探す→(567)、残り"2348" ※順子を探す→(234)、残り[8]→(111)(999)(567)(234)[8] 順子を探す→(678)、残り"2345" ※順子を探す→(234)、残り[5]→(111)(999)(678)(234)[5] ※順子を探す→(345)、残り[2]→(111)(999)(678)(345)[2] 順子を探す→(234)、残り"5678999" ※刻子を探す→(999)、残り"5678" 順子を探す→(567)、残り[8]→(111)(234)(999)(567)[8] 順子を探す→(678)、残り[5]→(111)(234)(999)(678)[5] 順子を探す→(567)、残り"8999" ※刻子を探す→(999)、残り[8]→(111)(234)(567)(999)[8] 雀頭を探す→(99)、残り[89]→(111)(234)(567)(99)[89] 順子を探す→(678)、残り"5999" ※刻子を探す→(999)、残り[5]→(111)(234)(678)(999)[5] 雀頭を探す→(99)、残り"59" 待ちになっていない 順子を探す→(789)、残り"5699" 雀頭を探す→(99)、残り[56]→(111)(234)(789)(99)[56] 順子を探す→(345)、残り"2678999" ・ ・ ・ 雀頭を探す→(99)、残り"11123456789" ※刻子を探す→(111)、残り"23456789" ・ ・ ・ 見つかった待ちのそれぞれについてセットの組み合わせを数字順に並び替える 重複するものを除く ■待ちになっているかどうか ※問題では特に指定がないけど、普通の麻雀だと同じ牌は4枚しか無いので、 その前提で考えてみる。 1.待ちの牌が1枚の場合、 残りの手牌で同じ牌を3枚使っていなければ単騎待ちになっている 2.待ちの牌が2枚の場合、 (1)2枚めの牌-1枚めの牌=0(2枚が同じ牌)の場合、 残りの手牌で同じ牌を2枚使っていなければシャボ待ちになっている (2)2枚めの牌-1枚めの牌=1の場合、下記のアとイを調べる。 ア.(1枚めの牌-1)の牌が1~9の範囲にあるかどうかを調べる、 牌が存在する場合、残りの手牌でその牌を4枚使っていなければ 両面待ちか辺張待ちになっている イ.(2枚めの牌+1)の牌が1~9の範囲にあるかどうかを調べる、 牌が存在する場合、残りの手牌でその牌を4枚使っていなければ 両面待ちか辺張待ちになっている (3)2枚めの牌-1枚めの牌=2の場合、 (1枚めの牌+1)の牌が1~9の範囲にあるかどうかを調べる、 牌が存在する場合、残りの手牌でその牌を4枚使っていなければ 嵌張待ちになっている 3.待ちの牌が1枚か2枚になっていなければ待ちになっていない ■無駄な探索をしないためにはどうするか 探す順番は 1.刻子((111)~(999)) →2.順子((123)~(789)) →3.雀頭((11)~(99)) の順で数字が小さい方から探すことにする 現在探索中の組み合わせよりも優先順位が高いものが入っている組み合わせは、 既に調べてあるので考えなくて良くなるはず また、雀頭は1個しかないので、雀頭が見つかった後、残りをみて待ちになっていなければ 待ちになっていないのでは・・・ あ、良く考えたら七対子があるからそれだけは別に調べないとダメか。 七対子の聴牌かどうか調べるには雀頭だけ6つあるか調べれば良い ※日本式の麻雀だと同じ牌の雀頭((11)(11)とか)だと七対子にならないから、 (11)→(22)→(33)→(44)→(55)→(66)→(77)→(88)→(99)まで 順番に調べれば良さそう。 あと萬子しかないから国士無双の聴牌は考えなくて大丈夫だ。 ■上記を踏まえて考えると、探索の動きはこんな感じだろうか。 例.入力:"1112345678999"が来たときの調べ方 ・普通の和了り形((xxx)(xxx)(xxx)(xxx)(xx))の聴牌かどうか調べる 刻子を探す→(111)、残り"2345678999" 刻子を探す→(999)、残り"2345678" 順子を探す→(234)、残り"5678" 順子を探す→(567)、残り[8]→(111)(999)(234)(567)[8] 順子を探す→(678)、残り[5]→(111)(999)(234)(678)[5] 順子を探す→(345)、残り"2678" 順子を探す→(678)、残り[2]→(111)(999)(345)(678)[2] 順子を探す→(456)、残り"2378" 順子・刻子・雀頭が無いので待ちが無い 順子を探す→(567)、残り"2348" 優先順位が同じ(567)かそれ以下のセットが見つからないのでこれ以上探索しない 順子を探す→(678)、残り"2345" 優先順位が同じ(678)かそれ以下のセットが見つからないのでこれ以上探索しない 順子を探す→(234)、残り"5678999" 順子を探す→(567)、残り"8999" 雀頭を探す→(99)、残り[89]→(111)(234)(567)(99)[89] 順子を探す→(678)、残り"5999" 雀頭を探す→(99)、残り"59" 待ちになっていない 順子を探す→(789)、残り"5699" 雀頭を探す→(99)、残り[56]→(111)(234)(789)(99)[56] 順子を探す→(345)、残り"2678999" ・ ・ ・ 雀頭を探す→(99)、残り"11123456789" 待ちになっていない ・七対子の和了り形((xx)(xx)(xx)(xx)(xx)(xx)(xx))の聴牌かどうか調べる 雀頭を探す→(11)、残り"12345678999" 雀頭を探す→(22)、無い 雀頭を探す→(33)、無い 雀頭を探す→(44)、無い 雀頭を探す→(55)、無い 雀頭を探す→(66)、無い 雀頭を探す→(77)、無い 雀頭を探す→(88)、無い 雀頭を探す→(99)、残り"123456789" 待ちになっていない 見つかった待ちのそれぞれについてセットの組み合わせを数字順に並び替えるこんな感じかなあ。 多分書かないと思いますが気が向いたらプログラムを書いてみようかなと思います。
PR
この記事にコメントする