基础知识
本文涉及的所有名词均在博文中有说明: http://blog.csdn.net/kunyus/article/details/78644517
核心思想
- 去除杂念: 由于字牌中只只允许出现 对子 和 刻子, 所以单独处理字牌.
- 返璞归真: 万/筒/条牌等 序数牌 处理除了花色不同其他规则一致, 所以忽略 序数牌 花色进行处理.
- 分而治之: 序数牌中存在关系的牌必须是连续的, 不连续的牌之间不会存在关系, 所以对连续牌进行分片.
- 各司其职: 单一分片能满足胡牌的部分,要么是 {3*n}(不带将), 要么是 {3*n+2}(带将), {3*n} 中的的牌不是三张牌一样的刻子,就是三张连续牌的顺子, 如: 1筒2筒3筒 1万1万1万, 通过此规则对分片进行归类.
- 各行其政: 针对{3*n} 和 {3*n+2} 分片单独处理
完整处理流程
处理字牌
统计手牌中所有字牌的牌个数, 牌个数必须为 2 或者 3, 出现其他则无法胡牌.
所有字牌都不是连续牌, 不能出现顺子, 只允许出现 对子 和 刻子 .
移除字牌中牌个数为 2 和 3 的牌并统计相应的 对子 和 刻子.
处理序数牌
将手牌中序数牌按花色以及牌个数进行归表并记录表中牌的总个数. (注意: 下文中出现的 牌表 一词均指此表.)
此处用万举例, 其他花色结果一样:
- 手牌 万: 1-9 各一张, 此时表内容应为: 111111111(9)
- 手牌 万: 11 22 333 4 5 6 77 88, 此时表内容应为: 2231112200(14)
遍历所有 牌表, 并对牌表中牌个数为 4 的牌移除一个刻子, 牌个数更改为 1.
对 牌表 进行分类, 牌个数满足 {3*n} 的归一组, 满足 {3*n+2} 的归一组. 出现不属于两组内的则无法胡牌.
单一花色能满足胡牌的部分,要么是 {3*n}(不带将), 要么是 {3*n+2}(带将), {3*n} 中的的牌不是三张牌一样的刻子,就是三张连续牌的顺子, 如: 1筒2筒3筒 1万1万1万
注意: 若字牌中不存在对子(将), 一副牌中 {3*n+2} 只能并且必须存在一个, 所以 {3*n+2} == 1, 否则 {3*n+2} == 0)
处理牌表
对 {3*n} 表按零元素进行分片并统计分片牌个数, 对满足 {3*n} 的计入 {3*n}, 出现不满足的则无法胡牌.
如表: 112110114(12) 最终切分为两个分片, 分别是 11211(6) 和 114(6)
对 {3*n}+2 表按零元素进行分片并统计分片牌个数, 分别计入 {3*n} 和 {3*n+2}, 出现不满足的则无法胡牌.
如表: 1221001142(14) 最终切分为两个分片, 分别是 1221(6) 和 1142(8)
处理 {3*n} 分片
遍历所有 {3*n} 分片, 去除所有牌个数为 3 的元素, 移除所有的刻子.
遍历所有 {3*n} 分片, 判断开头结尾是否为 2, 为 2 则连续个数必须被 3 整除, 不能整除则无法胡牌.
遍历所有 {3*n} 分片, 判断开头结尾是否为 1, 若为 1 则尝试在此处移除一个顺子, 移除失败则无法胡牌.
若上面 2 步任一执行成功, 则重新执行上面 2 步, 若上面 2 步全都没有执行成功而且还有余牌则当前牌无法胡牌.
处理 {3*n+2} 分片
遍历所有 {3*n+2} 分片, 移除分片中牌个数全部为 3 的分片.
遍历所有 {3*n+2} 分片, 移除所有开头结尾的 2, 如果为连续的 2 则移除所有连续 2.
遍历所有 {3*n+2} 分片, 判断开头结尾是否为 1, 若为 1 则尝试在此处移除一个顺子, 移除失败则无法胡牌.
遍历所有 {3*n+2} 分片, 判断开头结尾是否为 3, 若为 3 则尝试在此处 硬解 , 解牌失败则无法胡牌.
若上面 3 步任一执行成功, 则重新执行上面 3 步, 若上面 3 步全都没有执行成功而且还有余牌则当前牌无法胡牌.
硬解
从开始出依次处理当前牌, 出现 2 跳过, 出现其他牌则认为此处为起点.
从起点处尝试移除一个顺子, 移除成功向后跳到牌个数大于 1 的位置重新执行步骤 1.
若步骤 2 失败, 判断起点处是否为 1, 为 1 则无法胡牌. 不为 1 则起点向下移动一位重新执行步骤 2.