1. 程式人生 > >帶賴子的超高效麻將、跑鬍子胡牌演算法

帶賴子的超高效麻將、跑鬍子胡牌演算法

騰訊課堂視訊講解:https://ke.qq.com/course/305608?tuin=104cb0e2

文件 github地址 https://github.com/yuanfengyun/qipai/tree/master/doc

lua版 https://github.com/yuanfengyun/qipai/tree/master/mjlib_lua

c++版 https://github.com/yuanfengyun/qipai/tree/master/mjlib_c%2B%2B

golang版 https://github.com/yuanfengyun/qipai/tree/master/mjlib_go

js版 https://github.com/yuanfengyun/qipai/tree/master/mjlib_js

c#版 https://github.com/yuanfengyun/qipai/tree/master/mjlib_c%23

java版 https://github.com/yuanfengyun/qipai/tree/master/mjlib_java

速度: 

    每秒處理100萬次四個賴子判胡

    每秒處理1000萬次八個賴子判胡


QQ: 273461474

核心思想:
1、名詞解釋:eye(將),字牌(feng、東南西北中發白),花色(萬、筒、條、字牌)
2、分而治之:檢查手牌是否能胡是依次檢查萬、筒、條、字牌四種花色是否能組成胡牌的一部分。
3、單一花色要能滿足胡牌的部分,則要麼是3*n(不帶將),要麼是3*n+2(帶將)。3*n中的3帶表三張牌一樣的刻子,或三張連續的牌如1筒2筒3筒。
4、判斷是否滿足胡牌的單一花色部分,需要根據是否有將,有幾個賴子,查詢不同的表。表內容表示表裡的元素加上對應的賴子數量能組成3*n 或3*n+2。
賴子數是表名最後的數字,帶有eye的表表示滿足3*n+2,沒有的表示滿足3*n。
5、查表的key值,是直接根據1-9有幾張牌就填幾(賴子不算),如1-9萬各一張,則key為111111111。如1萬3張,9萬2張,則key為300000002。
6、組合多種花色,判斷是否能胡牌。將賴子分配給不同的花色,有若干種分配方式,只要有一種分配能讓所有花色滿足單一花色胡牌部分,則手牌能胡。
如:手上有3個賴子,可以分配萬、筒、條各一張,也可以萬、同、字牌各一張
7、根據是否有將、是否字牌分為4種表,每種表又根據賴子個數0-8分別建表,共36張表,具體如下:
 
賴子個數                   帶將表                          不帶將的表                              字牌帶將表                        字牌不帶將表
0                           eye_table_0                          table_0                          feng_eye_table_0                 feng_table_0
1                           eye_table_1                          table_1                          feng_eye_table_0                 feng_table_1
2                           eye_table_2                          table_2                          feng_eye_table_0                 feng_table_2
3                           eye_table_3                          table_3                          feng_eye_table_0                  feng_table_3
4                           eye_table_4                          table_4                          feng_eye_table_0                 feng_table_4
5                           eye_table_5                          table_5                          feng_eye_table_0                  feng_table_5
6                            eye_table_6                         table_6                          feng_eye_table_0                  feng_table_6
7                            eye_table_7                         table_7                          feng_eye_table_0                  feng_table_7
8                            eye_table_8                          table_8                         feng_eye_table_0                  feng_table_8
 
步驟:
1、統計手牌中鬼牌個數 nGui,將鬼牌從牌資料中去除.
2、不同花色分開處理,分別校驗是否能滿足 將、順子、刻子
3、分析東南西北風中發白時,不需要分析順子的情況,簡單很多
4、分析單一花色時,直接根據1-9點對應數字得出一個9位的整數,每位上為0-4代表該點數上有幾張牌
比如:1筒2筒3筒3筒3筒3筒6筒7筒8筒2萬3萬3萬3萬4萬
數字:筒: 1,1,4,0,0,1,1,1,0 得出的數字為114001110
萬 0,1,3,1,0,0,0,0,0 得出的數字為13100000
5、組合多種花色,判斷是否能胡牌。將賴子分配給不同的花色,有若干種分配方式,只要有一種分配能讓所有花色滿足單一花色胡牌部分,則手牌能胡。
如:手上有3個賴子,可以分配萬、筒、條各一張,也可以萬、同、字牌各一張
每種花色與賴子組合,如果所有花色都能配型成功則可胡牌
檢查配型時,每種花色的牌數量必需是3*n 或者 3*n + 2
根據賴子個數、帶不帶將,查詢對應表,看能否滿足3*n 或 3*n+2的牌型
 
非字牌表的產生:
1、窮舉萬字牌所有滿足胡牌胡可能,將對應的牌型記錄為數字,根據是否有將、放入eye_table_0或table_0中。
具體是每次加入一個刻子,順子或是將(將只能加入一對),最多加入四組外帶將牌。
2、將table_0中牌去掉一張,放入table_1中,表示去掉的牌用1張賴子代替。eye_table_0中牌去掉一張,放入到eye_table_1中。
3、將table_1中牌去掉一張,放入table_2中,表示去掉的牌用1張賴子代替。eye_table_1中牌去掉一張,放入到eye_table_2中。
4、將table_2中牌去掉一張,放入table_3中,表示去掉的牌用1張賴子代替。eye_table_2中牌去掉一張,放入到eye_table_3中。
5、將table_3中牌去掉一張,放入table_4中,表示去掉的牌用1張賴子代替。eye_table_3中牌去掉一張,放入到eye_table_4中。
6、將table_4中牌去掉一張,放入table_5中,表示去掉的牌用1張賴子代替。eye_table_4中牌去掉一張,放入到eye_table_5中。
7、將table_5中牌去掉一張,放入table_6中,表示去掉的牌用1張賴子代替。eye_table_5中牌去掉一張,放入到eye_table_6中。
8、將table_6中牌去掉一張,放入table_7中,表示去掉的牌用1張賴子代替。eye_table_6中牌去掉一張,放入到eye_table_7中。
9、將table_7中牌去掉一張,放入table_8中,表示去掉的牌用1張賴子代替。eye_table_7中牌去掉一張,放入到eye_table_8中。
 
字牌表的產生:

與非字牌表的產生方法相同,只是第一步中,不能加入順子(除非麻將玩法字牌是能組成順子的)


表的大小:總量在2M左右

表生成耗時:2-3S