麻将普通胡牌算法JS版(含癞子,非轮训)
记录一下麻将的通用胡牌算法实现,只要满足X*ABC + Y*DDD + EE 即可胡牌。
在这里先分析一下最简单的胡牌思路:先找出所有可能的将牌,若除去两张将牌之外的所有牌都能成刻或顺,则可胡牌。
将牌就是公式里唯一的对子即是EE、顺子ABC或者刻子DDD。
将牌的查找:遍历每张手牌,若有两张以上相同牌就能作将,或者用一张癞子凑也可。
接下来就只要判断一副牌是否成扑,伪码如下:
function isShunKe=(牌){ // 这里约定传入的牌是有序的、张数是3的倍数 if(没牌){ return true; } if(若第一张是顺子中的一张){ if(isShunKe(去掉该顺子剩下的牌)){ return true; } } if(若第一张是刻子中的一张){ if(isShunKe(去掉该刻子剩下的牌)){ return true; } } return false;
}
只要思路清晰了算法就很简单,为什么只考虑第一张牌?其实函数内部递归调用了每张牌都会计算到的,除非没牌了。下面给出详细代码:
function isShunKe(cards, laiziCount){ if (cards.length === 0){ return true; } // 若第一张是顺子中的一张 for (var first = cards[0] - 2; first <= cards[0]; first++) { if(first % 10 > 7 || (laiziCount === 0 && first < cards[0])) { // 顺子第一张牌不会大于7点、无赖子情况下顺子第一张只能用手上的牌 continue; } var shunCount = 0; for (var i=0;i<3;i++) { if (cards.indexOf(first + i) >= 0) { shunCount++; } } if (shunCount === 3 || shunCount + laiziCount >= 3) { // 找到包含第一张牌的顺子 var puCards = cards.slice(); var puLaizi = laiziCount; for (var i=0; i<3; i++) { var deletePos = puCards.indexOf(first + i); if (deletePos >= 0) { puCards.splice(deletePos, 1); } else { puLaizi--; } } if (isShunKe(puCards, puLaizi)) { // 剩下的牌成扑 return true; } } } // 若第一张是刻子中的一张 var keziCount = 1; var keziCard = cards[0]; if (cards[1] === keziCard) { keziCount++; } if (cards[2] === keziCard) { keziCount++; } if (keziCount === 3 || keziCount + laiziCount >= 3) { var puCards = cards.slice(); var puLaizi = laiziCount; for (var i = 0; i < 3; i++) { var deletePos = puCards.indexOf(keziCard); if (deletePos >= 0) { puCards.splice(deletePos, 1); } else { puLaizi--; } } if (isShunKe(puCards, puLaizi)) { return true; } } return false;
}
下面是判断胡牌的函数:
function canHuLaizi(cards, laiziCount) { if ((cards.length + laiziCount + 1) % 3 != 0) { // 若牌张数不是2、5、8、11、14则不能胡 return false; } // 排序方便胡牌判断 cards.sort(function(a, b) { return a - b; }) // 依次删除一对牌做将,其余牌全部成扑则可胡 for (var i = 0; i < cards.length; i++) { if (i > 0 && cards[i] == cards[i - 1]){ // 和上一次是同样的牌,避免重复计算 continue; } if ((i + 1 < cards.length && cards[i] == cards[i + 1]) || laiziCount > 0) { // 找到对子、或是用一张癞子拼出的对子 var puCards = cards.slice(); var puLaizi = laiziCount; puCards.splice(i, 1); if (puCards[i] == cards[i]) { puCards.splice(i, 1); } else { puLaizi--; } // 删去对子判断剩下的牌是否成扑 if (isShunKe(puCards, puLaizi)) { return true; } } } if (laiziCount >= 2 && isShunKe(cards, laiziCount - 2)) { // 两个癞子做将牌特殊判定处理 return true; } return false;
}
这里做一下两个输入参数的说明:
- cards:手牌数组,不超过14张牌,每张牌由整数表示如下
数字 {01 ~ 09} 表示 {1 ~ 9} 筒
数字 {11 ~ 19} 表示 {1 ~ 9} 条
数字 {21 ~ 29} 表示 {1 ~ 9} 万
数字 {31 33 35 37 } 表示风 { 东 南 西 北 } // 为什么间隔两个数字记录一个,就是为了防止将自拍在自己算过程中组成顺子
数字 {41 43 45} 表示箭 {中 發 白}
- laiziCount:癞子数量,用整数表示
有关算法代码重构,这里有个小技巧:
使用随机生成的牌型数据,将新版本代码与老版本代码对比,当运算结果不一样时候可以快速的找出bug,也可以循环大量输入统计耗时比较效率。
通过这个手段解决了一些小问题,最终跑1000万次牌型输出结果一致,就可以安心的替换了。
麻将普通胡牌算法JS版(含癞子,非轮训)相关推荐
- 跑胡子c语言算法,跑胡子胡牌算法Java版(带赖子、基于回溯算法)
跑胡子规则 跑胡子,小写"一"到"十"各4张共40张,大写"壹"到"拾"各4张共40张. 砌牌:跑胡子为3人同玩,庄家砌 ...
- 麻将胡牌算法lua 不支持癞子
--[[ file:game\lualib\mahjongHelper.lua desc:麻将辅助 + 胡牌 + 听牌 算法 auto:Carol Luo ]] local ipairs = ipai ...
- 麻将通用胡牌算法详解(拆解法)
1.背景 前几天刚好有项目需要胡牌算法,查阅资料后,大部分胡牌算法的博客都是只讲原理,实现太过简单,且没有给出测试用例.然后就有了下面的这个胡牌算法,我将从算法原理和算法实现两部分展开,想直接用的,直 ...
- 麻将 胡牌 算法(任意癞子)
分享一个麻将胡牌算法,支持多癞子,自己对麻将胡牌的理解写的一套快速识别胡牌逻辑,核心逻辑500行代码,仅对同条万进行处理,字花牌不包含在内,易理解,1M次随机胡牌牌型大概3秒左右.原创分享,我的算法也 ...
- erlang实现麻将胡牌以及癞子胡牌算法
判断胡牌 麻将胡牌其实是按照nAAA + mABC + DD的套路,算法判断也很好实现,找出DD,然后剩下的牌都能形成AAA或者ABC即可胡牌.本文只介绍麻将普通胡牌的算法,该算法经过验证可判断除特殊 ...
- 麻将胡牌算法的一种设计及其分析
马勇波 陈欣庆 (解放军理工大学工程兵工程学院研究生二队,南京 210007) 摘 要 文章通过一个二维数组定义麻将的数据结构,并在此基础上设计了一种判断麻将是否胡牌的算法,该算法主 ...
- 麻将胡牌算法带癞子 python实现
姐姐:你去帮我和闺蜜打麻将? 学霸哥哥:可是我不会打麻将呀! 姐姐:你不是学霸吗?我教你一个麻将公式,我闺蜜可是单身哟! 学霸哥哥:什么公式? 姐姐:麻将胡牌公式: AAA*M+ABC*N+BB,WM ...
- node.js——麻将算法(五)胡牌算法的一些优化处理方案(有赖子版)
以前有赖子判胡算法 http://blog.csdn.net/sm9sun/article/details/65632646 以前的帖子说明了处理赖子的两种方案:枚举代替及插空补缺,并最终选择了枚举遍 ...
- 麻将高效鬼牌胡牌算法(C++版)
最近做的一个麻将里面有双鬼牌的玩法,即为8张鬼牌,第一反应是采用N重循环把鬼牌变成一张张牌去遍历是否能胡牌,实际测试在5张牌鬼牌的情况得出结果就需要差不多5,6分钟. 因此自己做了一套用凑牌的方式去判 ...
最新文章
- urllib.parse包学习
- flask貌似html文件里只能用flask指定的路径格式,css文件里则可用相对路径
- openssl https 单向认证连接成功示例
- kafka架构、亿级数据如何优化GC
- K8S+Docker理论与实践深度集成
- Win7系统打开摄像头提示“请检查装置连接状况”怎么办
- combobox异步加载 easyui_如何解决多条数据加载easyui-combobox样式反应慢的问题
- 【Java】《Java面向对象编程的三大特性》阅读笔记
- centos用php上传文件,WBB - Centos下PHP无法Curl模拟Post上传文件的问题
- PDE2 three fundamental examples
- java生成一条唯一的邀请码_根据用户id生成一个唯一邀请码
- 什么原数据更容易平稳_判定数据序列平稳与否的方法都有哪些,什么是平稳序列...
- Android中的Apk的加固(加壳)原理解析和实现
- springboot实现条形码_java生成条形码(多种条码类型生成)
- IDEA如何设置author头注解
- 在Xubuntu上安装中文输入法
- 用户行为分析zhi应用分析模型
- 牛逼!java只能输入数字的正则
- 《深入理解计算机系统》
- vue中warning_使用vue的i18n 出现很多warning提示