Skip to content

Commit

Permalink
增加网友24431188,重构的js版
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanfengyun committed Oct 29, 2018
1 parent 7376597 commit a936908
Show file tree
Hide file tree
Showing 11 changed files with 1,814 additions and 0 deletions.
62 changes: 62 additions & 0 deletions mjlib_js2/Algorithm.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
由网友QQ 24431188 重写版本

一)查表法核心思想:
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 Table0 Table_Feng0
1 Table1 Table_Feng1
2 Table2 Table_Feng2
3 Table3 Table_Feng3
4 Table4 Table_Feng4
5 Table5 Table_Feng5
6 Table6 Table_Feng6
7 Table7 Table_Feng7
8 Table8 Table_Feng8

要单独分开字牌表是因为字牌是不能形成顺子的,东南西不是顺子。(但是有些地方的玩法,例如南昌,它是可是东南西组成顺子的。)

步骤:
1、统计手牌中鬼牌个数 ghostCount,将鬼牌从牌数据中去除.
2、把手上的牌编码成一串数字比如: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
3、查表检查单一种花色能否胡牌先查Table0; 如果不能胡,再根据手上鬼牌的个数查其它表。
4、当所有牌型都能胡,并且有且仅有一种牌型是3*n+2, 其它牌型为3*n.


二) 表的产生

非字牌表的产生:
1、穷举万字牌所有满足胡牌胡可能,将对应的牌型记录为数字,放入Table0中。
具体是每次加入一个刻子,顺子或是将(将只能加入一对),最多加入四组外带将牌。
2、将Table0中牌去掉一张,放入Table1中,表示去掉的牌用1张赖子代替。
3、将Table1中牌去掉一张,放入Table2中,表示去掉的牌用1张赖子代替。
4、将Table2中牌去掉一张,放入Table3中,表示去掉的牌用1张赖子代替。
5、将Table3中牌去掉一张,放入Table4中,表示去掉的牌用1张赖子代替。
6、将Table4中牌去掉一张,放入Table5中,表示去掉的牌用1张赖子代替。
7、将Table5中牌去掉一张,放入Table6中,表示去掉的牌用1张赖子代替。
8、将Table6中牌去掉一张,放入Table7中,表示去掉的牌用1张赖子代替。
9、将Table7中牌去掉一张,放入Table8中,表示去掉的牌用1张赖子代替。

只计算到8张牌,如果手上有超过8张牌,无论是什么牌都是胡牌的。

字牌表的产生:
与非字牌表的产生方法相同,只是第一步中,不能加入顺子(除非麻将玩法字牌是能组成顺子的)。

三) 代码实现
1) 只有在没有表的情况下,才会生成每一张表。
2) 每张表生成以后,将会加载下来,并存放在内存中。
3) GenTable是个单例,这样可以节约内存。

使用方法:
1) let hulogic = new HuLogic();
2) hulogic.checkHu(cardList,ongoingCard);
57 changes: 57 additions & 0 deletions mjlib_js2/App/Mocha_Test/testHu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@


const Card = require('../Models/Card');
const HuLogic = require('../Models/HuAlgorithm/HuLogic')
const assert = require('assert');


describe('胡牌测试', function () {

it('检查胡牌', function () {
var testPaiList =
[
["1万", "3万", "5万", "6万", "7万", "8筒", "8筒", "6筒", "6筒", "4筒", "4筒", "中", "中", "5筒"],
["5万", "6万", "4万", "9筒", "9筒", "8筒", "1条", "6筒", "2条", "3条", "南", "南", "中", "7筒",],//7筒
["1万", "3万", "4万", "5万", "6万", "2筒", "3筒", "4筒", "5筒", "7筒", "南", "中", "中", "南"],//南
["1万", "3万", "4万", "5万", "6万", "2筒", "3筒", "4筒", "5筒", "7筒", "中", "中", "中", "8万"],//8万
["2筒", "4筒", "5筒", "6筒", "7筒", "2万", "4万", "5万", "7万", "8万", "8万", "中", "白", "3万"],//3万

["6筒", "6筒", "1条", "3条", "4条", "5条", "6条", "7条", "9条", "7万", "9万", "中", "白", "中"],//中
["3筒", "4筒", "5筒", "5筒", "6筒", "7筒", "3条", "4条", "8条", "8条", "3万", "5万", "白", "4万"],//4万
["9筒", "9筒", "6条", "7条", "8条", "3万", "3万", "4万", "6万", "7万", "7万", "7万", "白", "3万"],//3万
["1筒", "2筒", "3筒", "4筒", "5筒", "6筒", "2万", "5万", "7万", "8万", "中", "中", "白", "4万"],//4万
["2筒", "3筒", "4筒", "7筒", "8筒", "5条", "6条", "7条", "9条", "9条", "7万", "7万", "白", "中"],//中

["5筒", "1条", "2条", "3条", "6条", "7条", "8条", "6万", "7万", "7万", "8万", "9万", "白", "5万"],//5万

["白", "中", "中", "8条", "7条", "7条", "5条", "4条", "3条", "2条", "5万", "3万", "2万", "1万"],//1万
["中", "1条", "3条", "4条", "5条", "6条", "1万", "1万", "2万", "3万", "4万", "5万", "7万", "白"],//白
["白", "9条", "8条", "8条", "7条", "7条", "4条", "3条", "5筒", "4筒", "3筒", "2筒", "2筒", "4条"],//4条

["7万", "8万", "9万", "9条", "9条", "8条", "8条", "4筒", "3筒", "2筒", "1筒", "白", "白", "中"],//"中"
["9万", "8万", "7万", "6万", "4万", "3万", "2万", "1万", "3条", "1条", "1条", "白", "白", "1条"],//

["7万", "7万", "3万", "3万", "9条", "8条", "7条", "8筒", "7筒", "6筒", "5筒", "4筒", "中", "7万"],//"7万"
["8万", "7万", "4万", "4万", "9条", "8条", "7条", "7筒", "5筒", "2筒", "2筒", "白", "中", "2筒"],//"2筒"

["8万", "7万", "6万", "4万", "3万", "2万", "1万", "7筒", "6筒", "5筒", "3条", "3条", "中", "9万"],//"9万"


["中", "中", "9条", "8条", "8条", "7条", "6条", "5条", "4条", "3条", "9筒", "7筒", "2筒", "8筒"],//"8筒"
["白", "中", "9条", "8条", "7条", "6条", "9筒", "9筒", "7筒", "5筒", "4筒", "2筒", "3筒", "4条"]//"4条"
];

var testHuResult = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1];
for (let i = 0; i < testPaiList.length; i++) {
let cardDisplayNameList = testPaiList[i];

let cardList = Card.CreateCardWithNameList(cardDisplayNameList, [31, 32, 33]);
let huLogic = new HuLogic();
let isHu = huLogic.checkHu(cardList);
assert(isHu == testHuResult[i]);

}


})
})
Loading

0 comments on commit a936908

Please sign in to comment.