yuanfengyun / q_algorithm Goto Github PK
View Code? Open in Web Editor NEW棋牌的胡牌算法,包括麻将、跑胡子、扑克。实现 lua 、c++ 、c# 、golang 、js 、java 、python 版本。( Mahjong algorithm )
棋牌的胡牌算法,包括麻将、跑胡子、扑克。实现 lua 、c++ 、c# 、golang 、js 、java 、python 版本。( Mahjong algorithm )
请问代码clone下来后,怎么编译运行(新手勿喷,谢谢)?
在mac上能编译运行吗?没找到工程文件啊。
以测试用例来说明。
func test_one_success_1() {
cards := []int{
1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 3, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
}
fmt.Println("测试1种能胡的牌型")
print_cards(cards)
if mjlib.MHuLib.GetHuInfo(cards, 34, 0, 34) {
fmt.Println("测试通过:胡牌")
} else {
fmt.Println("测试失败:能胡的牌型判断为不能胡牌")
}
fmt.Println("-----------")
}
func test_one_success_2() {
cards := []int{
1, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
}
fmt.Println("测试1种能胡的牌型")
print_cards(cards)
if mjlib.MHuLib.GetHuInfo(cards, 34, 0, 34) {
fmt.Println("测试通过:胡牌")
} else {
fmt.Println("测试失败:能胡的牌型判断为不能胡牌")
}
fmt.Println("-----------")
}
test_one_success_1 是正常的。
test_one_success_2 中,cards 将第三行第四列的3个牌去掉,测试结果是胡不了。
那么,碰、杠了的牌,不能从 cards 中移除吗?
如果不能移除,那么碰、杠的牌规则上是不能跟手上的牌重新组合的,结果会不会出错?
如果能移除,请问应该怎么调用?
var cards=[
1,0,0,4,0,0,0,4,0,
0,0,1,0,0,0,0,1,0,
1,0,0,0,0,1,0,0,0,
1,0,0,0,0,0,0,
]
// 筒 万 条
// 混儿 1张 2筒
console.log("测试能胡的牌型");
// print_cards(cards)
if (mjlib.MHulib.get_hu_info(cards, 34, 3, 7) ){
console.log("测试通过:胡牌")
} else {
console.log("测试失败:能胡的牌型判断为不能胡牌")
}
可能出问题的地方
function _init()
{
//需要初始化多个对象
ProbabilityItemTable = { array_num : 0, m_num : [ 0, 0, 0, 0 ], m : [] };
for( let i = 0; i < 4; i ++ )
{
ProbabilityItemTable.m[ i ] = [];
for( let j = 0; j < 5; j ++ )
{
var ProbabilityItem = { eye : false, gui_num : 0 };
ProbabilityItemTable.m[ i ].push( ProbabilityItem );
}
}
}
//初始化牌型
_init();
上面的意思是 4种花色 * 5种癞子分配可能?
假设手上有8张癞子,不是0-8共9种分配可能吗?
c++版本的split和split2拆分法有问题.我试过查表版和HuPaiMj3.h,HuPaiMj2.h,还有拆分法,并且把我自己用的胡牌算法代进去,900万次,发现拆分法的结果不对,总会比其他的算法得出的少一些,并且拆分法的性能不是最好的
可以胡牌的牌组还是很多的,所有都需要对手牌进行二次编码,请问您的编码方式可以提供一下嘛?
local t = {
0,0,0, 0,0,0, 0,0,0,
0,2,0, 0,0,0, 0,0,2,
0,0,0, 1,1,3, 0,0,2,
0,0,0, 0,0,0, 0,
}
if hulib.get_hu_info(t) then
print("胡")
else
print("不能胡")
end
结果是胡
int[] cards = new int[]{
0, 0, 4, 1, 0, 0, 0, 0, 0, /* 万 */
0, 0, 0, 1, 0, 0, 0, 0, 0, /* 筒 */
0, 0, 0, 1, 0, 0, 0, 0, 0, /* 条 */
0, 0, 0, 1, 0, 0, 0 };//字
这个牌,字牌只能要一个癞子做将,然后其他的牌型,每个都需要2个癞才能成顺子,但除了check_probability里有减去万字需要的癞子外check_probability_sub里面每次循环找下一个牌型时,没有把当前可能需要的癞子扣除,所以导致这个牌型的结果是可胡牌
char cards[] = {
4,0,2,0,2,0,2,2,2,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0
};
bool isHu = split2::get_hu_info(cards,34, 33);
没有用到鬼牌,这个牌应该是龙7对,该判胡才对。
请教下。gen_eye_table 函数中,
local function gen_eye_table()
local t = {0,0,0,0,0,0,0,0,0}
for i=1,18 do
t[i] = 2
print("将",i)
add_to_table(t)
gen_table_sub(t, 1)
t[i] = 0
end
end
这个18 如何理解?不是应该只有9就行了么
利用拆分法,您的代码目前好像无法判定 我上述的情况,请问应该在哪一步修改,谢谢
这个太厉害了, 很好很强大, 6666
为什么找不到utils文件
请问258做将怎么改
从规则上来说,只有一对将牌的情况也是符合3x0+2的公式,应该也能够在auto_table_with_eye中查到才对。
函数:
two(int n, int need_gui, int max_gui)
{
...
if (choose_ke) need_gui = need_gui + 1;
else{
if (c1 < 2){
need_gui = need_gui + (2 - c1);
n = n - c1;
}
else{
n = n - 2;
}
if (c2 < 2){
need_gui = need_gui + (2 - c2);
n = n - c2; //应为c2*10?
}
else
{
n = n - 20;
}
}
...
}
n = n - c2; //应为c2*10?
看了很多麻将的胡牌算法,这个应该是比较高效而且文档代码清晰的一个,感谢分享。
java版本的table里面的src的org/yungege/mj/Hulib.java里面的判断组合里面的check_probability_sub函数里面的最后
if (!eye && !item.eye && !item.eye && item.gui_num + 2 > gui_num) 写的有问题呀,没不要取非,而且判断了2次item.eye
在windows下跑test_split2时调用到
hu += split2::get_hu_info(&source[n * 34], 34, gui_index);
时 当n=1时,在函数
split2::one(char* cards, int& index, int& need_gui, int max_gui, int used_gui)
时会出现index=9,而cards数组的长度为9,此时要执行访问了cards[9],cards[10]
int c1 = cards[index];
int c2 = cards[index+1];
并执行了操作
cards[index]--; //cards[9]--;
,访问越界。
vs2013运行了mjlib_c++的代码,发现数组越界了,153行,chars数组长度只有9,加个断点发现index+1为9了
char cards[] = {
0,2,1,2,2,2,1,1,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0
};
使用split2,这种牌型无法判断胡牌
java版本split不能判7对
feng_eye_table_2第762行
feng_eye_table_5第2409行
feng_eye_table_8第187行
feng_table_3第318行
feng_table_6第736行
清一色好判断,去除鬼牌,剩下的为同一种花色既为清一色。
七小对也好判断,去除鬼牌,去掉对子,剩余单牌数量等于鬼牌数量,即为清一色。
碰碰胡还没想到算法,求指点。
请问支持广东麻将100只 (条子,筒子,翻子) 吗。
为什么python算法里面
if cur_card != 34:
cards[cur_card] = cards[cur_card] + 1
这个是有什么作用
我在你的代码中,好像没有找到生成的算法
java版生成表的方式,代码中基本没有注释,看起来有点费劲。要是加点注释会更好理解。
{0,0,0,0,0,0,0,0,2,0,0,1,1,1,0,0,2,0,2,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,}
9万9万3筒4筒5筒8筒8筒1条1条5条6条7条8条9条
这个验证胡了
bool HuLib::check_7dui(char* const cards){
int c = 0;
for(int i=0;i<34;++i)
{
if(cards[i] % 2 != 0) return false;
c += cards[i];
}
if(c != 34) return false; // 此处应为 c!= 14
return true;
}
7 7 7 8 9 万 判断出来是不胡的...大哥能帮忙看下吗?哈哈
我看到python版只有一个split模块,并且我进行了测试,胡牌结果是正确的且非常快,请问这是什么思路,没有用到您说的生成table方法
首先非常感谢作者这么无私的奉献,保守估计帮我省去了1周的时间。
暂时使用的是c++的split2实现版本,未来再考虑用lua。
我想问下,这个c++版本应该是靠谱的吧?
把每个癞子可能的花色,替换上去,再用分拆法吗?
这样就有 27 * 27 * 27 * 27种可能?(不考虑风的情况)
你说的我实在是看不太懂。
比如:“不同花色分开处理,分别校验是否能满足 将、顺子、刻子”。
上面这句我就不太明白,满足后怎么办?不满足又怎么办?、
还有和3n或3n+2匹配时我也看不太懂。
表的产生我也不懂。
源码中tbl的表为什么要分这么多种?
eye_table_0.tbl
feng_eye_table_0
table_0
这三种又是什么意思?
牌型数组如下,鬼牌为 cards[14]
char cards[34] = { 0,0,1, 1,1,0, 0,0,0, 0,2,1, 2,0,1, 0,0,0, 1,1,1, 0,0,0, 0,2,0, 0,0,0, 0,0,0, 0 };
使用的算法为
qipai/mjlib_c++/split/
另外当牌型为如下时是可以通过的
char cards[34] = { 0,0,0, 1,1,0, 0,0,0, 0,2,2, 2,0,1, 0,0,0, 1,1,1, 0,0,0, 0,2,0, 0,0,0, 0,0,0, 0 };
c++版本的拆牌算法无法识别下面的牌:
char cards[] = {
3,0,0,0,0,0,0,0,1,
0,1,0,1,0,0,0,0,0,
1,0,1,0,0,1,0,1,0,
0,0,0,0,0,0,4
};
这种情况下出现内存访问错误。
然后我看了下splite2::one(...)函数的实现,发现处理只是想把只有一张的牌连成一个刻子(3张连续的牌)。
而上面这个第一个最后的9,应该要组成将(一对9),就可以和牌。
其他语言的版本没有看。
不知道上面的理解是否有偏差,如果没有的话,我改好了的话提交一个pr。
另外,查表的方法用于判定是否可以和牌很好用。
我编译了一下发现一些错误 比如 TableMgr::get_instance() 但TableMgr 并无此声明和定义?
字牌如果是4,2,0,0,0,0,0的情况是有将的,为什么拆分法看到4直接return false是不是有问题?
在GetHuInfo里,var tmp_cards = cards并非深拷贝,因为cards不是数组,而是切片,所以这边只是引用,然后这样导致每次循环cards已经被改变了,在list_probability里的ptbl.m_num[anum] <= 0每次都成立,都没走到最耗时的鬼牌组合的函数里check_probability,如此计算最终耗时是5秒没错,go test下测试。
但是,经过把上面的引用改为正确的深拷贝后(比较耗时的操作
var tmp_cards = make([]int, len(cards))
copy(tmp_cards , cards)
),鬼牌2张,总麻将数17张,结果是35秒。
a步骤 312应该是取到300 而不是330吧
我使用qipai/mjlib_lua/gui_table麻将算法遇到了问题:
local t = {
0,0,0, 0,0,3, 0,0,0,
0,0,0, 3,0,0, 1,1,1,
0,0,0, 1,1,1, 0,0,2,
0,0,0,0, 0,0,0}
hulib.get_hu_info(t, 0)
这样的结果居然是失败的,真奇怪
local t = {
0,0,0, 0,0,3, 0,0,0,
0,0,0, 3,0,0, 1,1,1,
0,0,0, 1,1,1, 0,0,0,
0,0,0,0, 2,0,0}
hulib.get_hu_info(t, 32)
这样是成功的
local t = {
0,0,0, 0,0,3, 0,0,0,
0,0,0, 3,0,0, 1,1,1,
0,0,0, 1,1,1, 0,0,1,
0,0,0,0, 1,0,0}
hulib.get_hu_info(t, 32)
这样也是失败的
func test_one_success_4() {
cards := []int{
0, 0, 0, 0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 3, 2, 1,
0, 0, 0, 0, 0, 0, 0,
}
fmt.Println("测试1种能胡的牌型4")
print_cards(cards)
if mjlib.MHuLib.GetHuInfo(cards, 34, 18, 34) {
fmt.Println("测试通过:胡牌")
} else {
fmt.Println("测试失败:能胡的牌型判断为不能胡牌 xxxxxxxxxx")
}
fmt.Println("-----------")
}
func test_one_success_5() {
cards := []int{
0, 0, 0, 0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 2, 1, 0,
0, 0, 0, 0, 0, 0, 0,
}
fmt.Println("测试1种能胡的牌型5")
print_cards(cards)
if mjlib.MHuLib.GetHuInfo(cards, 34, 18, 34) {
fmt.Println("测试通过:胡牌")
} else {
fmt.Println("测试失败:能胡的牌型判断为不能胡牌 xxxxxxxxxx")
}
fmt.Println("-----------")
}
要不我提交一份单元测试的 pull request?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.