この記事は Wano Group Advent Calendar 2025 の18日目の記事となります。
昨日の Windowsの電源トラブル調査:powercfg /systempowerreport 入門 によってPCのバッテリー消耗が著しいときにも対応できそうな気がします。これでまたひとつ強くなれました。自分も自分や自分以外を強くできる記事が書けるようガンバります!
ネタバレ
- 麻雀をはじめたよ
- 待ち牌がわかるしくみをざっくりめに考えるよ
- 今回は用語の整理だよ
- いずれ待ち牌判定用のスクリプトを載せるよ
はじめに
こんにちは!@shibe_ です。TuneCore Japanでバックエンドエンジニアをしています。
2022年の3月にTuneCore Japanに入り(採用に至るまでの経緯などはこちら)、ついに麻雀を始めました。
エピソードトーク
ある日、ワタシが意気揚々と とある麻雀ゲーム をプレイしていたとき。
大量の待ち牌が眼の前に現れ、なにがなんだかわからなくなってしまいました。
※以下は 雀魂 のゲーム画面の一部を引用しています
出典:雀魂 -じゃんたま-( https://mahjongsoul.com )
いまは待ち牌のわかるゲームだからよいものの、リアル麻雀でこのような状態になったときに頭がおぼつかないぞ。
そう思ったワタシは「待ち牌のしくみ」を整理し、スクリプトなどにして書いてみようと思ったのです。
(同様の機能はご覧頂いているとおり、雀魂 には当然実装されています。完全に車輪の再発明です)
まずは待ち牌のロジック以前に「そもそも何を前提として考えるのか」を整理することにしました。
ということで、早速用語を整理していきましょう。
用語の整理
この記事では、
「13枚の手牌から、どの牌を引けばアガリになるか」
を理解することだけを目的にしています。
そのため、麻雀の用語も
必要最小限・今回の仕様に関係あるものだけ説明します。
麻雀
麻雀は、牌を集めて決められた形を作るゲームです。
本記事では
- 対戦
- 勝ち負け
- 点数
- 役
は扱わず、
「手牌の形が成立しているかどうか」 だけを考えます。
なんだその無味乾燥な一人回しは。それが良いんだよ……
手牌
プレイヤーが現在持っている牌の集合のことです。
今回の記事では、
手牌は常に13枚であるものとして扱います(なんかいろいろあって多くなったり少なくなったりします。なんで?)。
この13枚に あと1枚を引いたら和了れるか? を判定するのが目的です。
和了
手牌がルール上「完成した形」になっている状態です。
この記事では、
和了の形として
- 4つの 面子
- 1つの 雀頭
からなる一般的な形のみを対象とします。
つまり七対子(チートイツ)や国士無双(コクシムソウ)などの特殊な形は扱いません。
名前はとても格好がいいですが、一度忘れてください。
数牌と字牌
牌は大きく2種類に分けて考えます。
数牌
1〜9の数字を持つ牌です。
数牌には柄が以下の3種類存在します。
ちょうど、トランプのスート(ハート/クラブ/ダイヤ/スペード)のようなものだと思ってください。
- 萬子(マンズ):漢数字の書かれた柄
- 筒子(ピンズ):丸が書かれた柄
- 索子(ソーズ):竹が書かれた柄
字牌
その名の通り、字で構成された牌のことです。
東・南・西・北・白・發・中 の7種類で、
数字を持たないため順子は作れません。
そのため、字牌は 雀頭または刻子としてのみ扱います。
面子
面子とは、3枚1組で成立する牌のまとまり のことです。
面子には以下の2種類が存在します。
順子(シュンツ)
同一の柄の数牌を、連続した数字 で3枚集めた形です。
例:
- 3筒子-4筒子-5筒子
- 1索子-2索子-3索子
✕ 連続した数字でも柄が異なれば順子にはなりません
- 1索子-2萬子-3萬子
刻子(コーツ)
同じ牌を3枚集めた形を指します。
例:
- 7索子-7索子-7索子
- 西-西-西
✕ 同一の数字でも柄が異なれば刻子にはなりません
- 1索子-1萬子-1萬子
雀頭(ジャントウ)とは?
雀頭とは、同一の牌を2枚集めたペアのことです。
和了の形には、
面子4つとは別に、雀頭が1つ必ず必要になります。
待ち牌
待ち牌とは、
13枚の手牌に1枚加えたとき、和了できる牌のことです。
待ち牌の考え方(具体例)
例えば手牌が以下の13枚だった場合、
雀頭:
- 1索子-1索子
面子:
- 西-西-西
- 1萬子-2萬子-3萬子
- 3筒子-4筒子-5筒子
- 5索子-7索子
6索子 を引けば 4面子1雀頭 が揃いますね。
このときは 6索子 が 待ち牌 であるといえます。
さらに、以下の場合を考えてみましょう。
雀頭:
- 東-東
面子:
- 西-西-西
- 7索子-7索子-7索子
- 3筒子-4筒子-5筒子
- 發-發
この場合、 發 を引けば和了になりますね。
しかし、それだけではありません。
東 を引いた場合は以下のような形になります。
雀頭:
- 發-發
面子:
- 西-西-西
- 7索子-7索子-7索子
- 3筒子-4筒子-5筒子
- 東-東-東
つまり、この場合は 發 と 東 が待ち牌である、というわけです。
さらに、以下のようなパターンはどうでしょう。
雀頭:
- 西-西
面子:
- 東-東-東
- 1索子-2索子-3索子
- 4筒子-5筒子-6筒子
- 7萬子-8萬子
この場合、まず 9萬子 を引けば 7萬子-8萬子-9萬子 の順子ができあがるので和了になることがわかるかと思います。
しかし、同様に 6萬子 を引いても 6萬子-7萬子-8萬子 の順子ができるため、
今回は 6萬子 9萬子 が待ち牌となるわけです。
最後の例です。
雀頭:
- 西-西
面子:
- 東-東-東
- 1筒子-2筒子-3筒子
- 4筒子-5筒子-6筒子
- 7筒子-8筒子
この場合、先程と同様に 6筒子 9筒子 は待ち牌になります。
しかし、今回の例では 6筒子 はすでにお手元にあります。
それを使うと以下のように考えることもできますね。
雀頭:
- 西-西
面子:
- 東-東-東
- 1筒子-2筒子-3筒子
- 4筒子-5筒子
- 6筒子-7筒子-8筒子
これにより 3筒子 6筒子 が待ち牌であるとわかります。
(さらに同様に、1筒子-2筒子/ 3筒子-4筒子-5筒子/ 6筒子-7筒子-8筒子 で 3筒子 が待ち牌だ!と考えることもできます。が、すでに3筒子は待ち牌であることがわかっているので省略します)
ということでこの手牌の待ち牌は 3筒子 6筒子 9筒子 である、とわかります。
まとめ
いかがでしたか?
自分は前提条件が非常に多く、麻雀に取り組むハードルがいかに高いかを思い知りました。
さらに、手牌の組み合わせ方がかなり自由度が高いため、すべてを洗い出すと莫大な計算量になりそうです。
そのため、「待ち牌を探し出す、アルゴリズムを考えたら自分にも応用できる上にアルゴリズム選定の実践にもなるぞ」と思い至りました。
次回以降は以下のような進行で、待ち牌を待たせぬように進めていこうと思います。
- 要件の整理: 待ち牌にはどのようなパターンがあるか、を整理(おそらくそれだけで1記事のボリュームになってしまう)
- 設計: 待ち牌を導き出す解法を複数パターン考え、どちらが計算量が少ないかを検討
- 実装: 設計をもとに、実際に待ち牌をはじき出すスクリプトを作成
お楽しみに!
この記事で、より多くの魂が救われることをここで祈り続けています。
TuneCore Japan では 一緒に働くメンバーを募集しています。
エンジニアだけでなく、Director等の各種ポジションをオープンしているので興味がわいた方はぜひご覧ください!
