搞一星期仍未果 跪求高手赐一道胡牌算法

threeperson 2018-04-20 12:30:57
棋牌(跑胡子)项目中的一道胡牌算法,折磨了一星期,还是没写出来。前后切换各种姿势,最终都无济于事,快崩溃了 技术太菜,实在折腾不出来,特来求救。
跑胡子游戏介绍,百科。这里就不浪费大家时间看游戏规则了,我直接把胡牌规则简化出来:

1)数字 1、2、3、4、5、6、7、8、9、10 代表小牌,共10张;
2)数字11、12、13、14、15、16、17、18、19 、20 代表大牌,共10张;
3)玩家手牌是以上20个数字的随机组合,每个数字最多出现3次(实际是4张,因为我项目里已过滤,这里只需求3张),最少0次,总数量2~21张(在这个范围内 且 %3要么等于2,要么等于0,这个是跑胡子规则,不用纠结哈);
4)3个相邻数字 或 2 7 10(特殊) 或 12 17 20(特殊)可以组成 1组(俗称:吃),如1 2 3,4 5 6,2 7 10。小牌不能跟大牌组合(即需区分范围判断,要么属于1~10,要么属于11~20),像 9 10 11这种组合是不允许的;
5) 3个相同数字可以组成1组(俗称:碰),如1 1 1,3 3 3,12 12 12;
6) 3个相同点数的小牌跟大牌可以组成1组(俗称:绞),即组成 a a+10 a+10或 a a a+10 或 a a-10 a-10 或 a a 1-10形式,例如2 12 12或12 2 2。
7) 玩家卡牌数量%3等于0时,刚好3张一组,需全部拆尽;
8) 玩家卡牌数量%3等于2时,有且只有”一对"牌单独出来(即2张相同的牌作对),其他牌需按3张一组全部拆尽;
9) 玩家卡牌如果能按以上规则拆尽,则代表能胡牌,否则不能胡牌。

麻将的胡牌算法是满足 nAAA+mXYZ+DD 公式,但跑胡子更特殊一点,它有大小牌之分,还有2 7 10这种特殊组合,且DD(作对的牌) 不一定有。
示例卡牌1:
List<int> cardList = new List<int>(){ 1, 7, 8, 9, 4, 4, 15, 1, 2, 3, 11, 11, 13, 14, 15, 16, 17, 18, 19, 20 };

拆分完后运行结果:

示例卡牌2:
List<int> cardList = new List<int>(){ 8, 8, 9, 9, 10, 10, 1, 2, 3, 11, 12, 13, 17, 17, 15, 15, 7 };

拆分完后运行结果:


以上结果是我本地运行,虽然是正确结果,但代码兼容性差,只能胡特定格式的牌,代码我就不贴出来了(主要是不敢贴,写到自己都无法控制了)。

网上有一份前辈写的胡牌算法,是C写的,看不大懂,它里面还有算胡息,这个暂可忽略。大家可参考:https://github.com/yuanfengyun/qipai/blob/master/phzlib_c/hulib.c

先谢过,感激不尽!
...全文
1257 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
threeperson 2018-04-25
  • 打赏
  • 举报
回复
当一个组合的所有路径都走完了,还是走不通。需要把已剔除牌放回,并从第一张牌的下一个组合继续。如果第一张牌的所有组合都找完了,就判定不能胡。
threeperson 2018-04-25
  • 打赏
  • 举报
回复
思路是先把所有卡牌的可能组合列出来。首先把手牌排序,拿出第一张牌,从它的可能组合中先找第一个,然后去手牌列表中查找对应的组合。若能找到,标记剔除,继续下一张。若不能找到,标记已找过的组合(不要重复找),尝试这张牌的下一个组合。通过递归调用,穷举所有组合。目前就是这样解决的,效率不是很高,单副牌验证需要60ms左右,先用着吧。
threeperson 2018-04-24
  • 打赏
  • 举报
回复
又经过4天的奋战,这个算法总算被我写出来了。明天测试下,没问题再分享吧。熬到快吐血了
xuzuning 2018-04-20
  • 打赏
  • 举报
回复
所以说嘛,并不是一定能拆尽的
极客诗人 2018-04-20
  • 打赏
  • 举报
回复
长这么打 棋牌类接触蛮多 就这个跑胡子 不会算息
threeperson 2018-04-20
  • 打赏
  • 举报
回复
cardList 就是玩家当前手牌,每次发牌后生成。能拆尽就代表当前玩家可胡牌,不能拆尽就不能胡。
引用 5 楼 xuzuning 的回复:
但 cardList 中的数字是随机产生的,不可能都做到 拆尽 否则,把把都是胡牌,有什么玩头?
xuzuning 2018-04-20
  • 打赏
  • 举报
回复
但 cardList 中的数字是随机产生的,不可能都做到 拆尽 否则,把把都是胡牌,有什么玩头?
threeperson 2018-04-20
  • 打赏
  • 举报
回复
这样不行,整副牌需要拆尽,即所有数字都要找到对应的组合。
引用 3 楼 xuzuning 的回复:
还有一个问题 比如 { 8, 8, 9, 9, 10, 10, 1, 2, 3, 11, 12, 13, 17, 17, 15, 15, 7 } 你是里的结果是 1 2 3 7 17 17 8 9 10 8 9 10 11 12 13 15 15 但也可以是 1,2,3 7,8,9 8,9,10 11,12,13 剩余 10,15,15,17,17 未分配 这里有什么讲究吗?
threeperson 2018-04-20
  • 打赏
  • 举报
回复
不允许重复,是我的算法有问题。已组合过的数字需剔除。
引用 1 楼 xuzuning 的回复:
太专业了点! 组合过的数字允许重复使用吗? 比如 { 1, 7, 8, 9, 4, 4, 15, 1, 2, 3, 11, 11, 13, 14, 15, 16, 17, 18, 19, 20 } 中只有一个 14 而你示例的结果中,含有 14 的组合有两个 4 4 14 13 14 15
xuzuning 2018-04-20
  • 打赏
  • 举报
回复
还有一个问题 比如 { 8, 8, 9, 9, 10, 10, 1, 2, 3, 11, 12, 13, 17, 17, 15, 15, 7 } 你是里的结果是 1 2 3 7 17 17 8 9 10 8 9 10 11 12 13 15 15 但也可以是 1,2,3 7,8,9 8,9,10 11,12,13 剩余 10,15,15,17,17 未分配 这里有什么讲究吗?
xuzuning 2018-04-20
  • 打赏
  • 举报
回复
太专业了点! 组合过的数字允许重复使用吗? 比如 { 1, 7, 8, 9, 4, 4, 15, 1, 2, 3, 11, 11, 13, 14, 15, 16, 17, 18, 19, 20 } 中只有一个 14 而你示例的结果中,含有 14 的组合有两个 4 4 14 13 14 15
sunny7862632 2018-04-20
  • 打赏
  • 举报
回复
首先你要学会玩这个,而不是看看规则。而且有代码可参考,会玩的前提下应该还是很容易做的。
threeperson 2018-04-20
  • 打赏
  • 举报
回复
胡息有固定规则,多记就好了。跑胡子规则是牌类中比较复杂的。
引用 7 楼 weixin_38925245 的回复:
长这么打 棋牌类接触蛮多 就这个跑胡子 不会算息
引用 7 楼 weixin_38925245 的回复:
长这么打 棋牌类接触蛮多 就这个跑胡子 不会算息

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧