在《斗地主ai-拆牌篇01》中介绍了拆牌相关的术语和基本逻辑。
玩乐儿童编程:斗地主AI-拆牌篇01在《斗地主ai-拆牌篇02》中介绍了利用递归思想,将手牌拆分为除可带牌型外的所有可能套牌的逻辑。
玩乐儿童编程:斗地主AI-拆牌篇02本篇就来阐述一下拆牌逻辑的第三步,根据上一步拆分的结果,对每种结果进行带牌处理,生成所有可带牌组合的逻辑,第三步结束后,拆牌的工作就算完成了。
- 计算带牌逻辑输入:除可带牌型外的所有可能套牌
- 计算带牌逻辑输出:所有可能的拆牌组合构成的套牌
继续上一篇中使用的手牌:3344555。
经过递归拆牌后输入为:
[5,554433]
[555,44,33]
[555,44,3,3]
[555,4,4,33]
[5,55,44,33]
[555,4,4,3,3]
[5,5,5,44,33]
[55,5,44,3,3]
[5,55,4,4,33]
[5,55,4,4,3,3]
[5,5,5,44,3,3]
[5,5,5,4,4,33]
[5,5,5,4,4,3,3]
计算带牌带牌逻辑,遍历每一种拆牌结果
1、查看拆牌结果中套牌是否包括:三张、炸弹和飞机,并且有可以被带的套牌:单张和对子。如果没有可带牌或被带牌直接返回。否则,进行下一步。
2、计算可带牌套牌的数量为(dpNum),从1遍历到dpNum,求出每种可带牌数量下的所有带牌组合。意思是如果有3个套牌可以带牌,那么带牌的结果可能是有1个套牌带牌(三选一),有2个套牌带牌(三选2),有3个套牌带牌(三选三)。这也对应了真实对局中,即使多手可带套牌,但是不一定全部按照带牌的方式走出去。
举例,[555,777,J,QQ]中有dpNum为2(555、777为可带牌套牌),在真实对局中,不一定是按照555J、777QQ这样出牌;也有可能是跟牌出了QQ,最后出555J和777。所以在计算可带牌的第一步,就是每种可带牌数量下的带牌组合。
以[555,777,J,QQ]为例,有1个可带牌套牌进行带牌的可能包括:
- [555J,777,QQ]
- [555QQ,777,J]
- [555,777J,QQ]
- [555,777QQ,J]
以[555,777,J,QQ]为例,有2个可带牌套牌进行带牌的可能包括:
- [555J,777QQ]
- [555QQ,777J]
搞清楚了,为什么要计算每种可带牌数量后,进入下一步看如何确保每种情况都被考虑到。
3、为可带牌套牌选择被带牌
3.1 首先,是从备选可带牌中进行Cnm的选择,其中C代表组合公式,n是bpNum,m是要选出来进行带牌的数量。以上面[555,777,J,QQ]为例,就是C21等于2
3.2 对上面的组合计算出需要的带牌数,如果被带牌不能满足则返回;如果能满足,则按照需要的被带牌数量对可带牌套牌进行排序后,进入带牌递归逻辑
3.3 带牌递归逻辑,是带牌的核心逻辑,明确递归的几个要素:
- 递归结束逻辑:所有可带牌套牌都已匹配到被带牌
- 递归范围减少:每匹配好一组可带牌+被带牌,就其从待匹配可带牌套牌和待匹配被带牌的列表中删除,并生成匹配好的新套牌
- 递归返回结果:在递归过程中记录,在递归结束时返回所有匹配好的新套牌。
以[555,777,J,QQ]为例,首先选择1套可带牌出来匹配,可选列表为[555,777],被带列表为[J,QQ],进入递归
555可选的被带牌列表为[J,QQ],555匹配J,记录新套牌555J,更新可选列表[777],被带列表为[QQ],进入递归
777可选的被带牌列表为[QQ],777匹配QQ,记录新套牌777QQ,更新可选列表[],被带列表为[],结束递归,返回记录到的新套牌[555J,777QQ]。
以上只是种一个递归分支,下面用示意图的方式来表现递归。
![v2-0ad81a2c199fae67da592b326f66ab2f_b.jpg](https://img-blog.csdnimg.cn/img_convert/5180e886b54528ba5986a8d8583c8a3f.png)
最后,以文章开头的输入计算可带牌的输出(可粗部分为可带牌的拆法):
- [5,554433]
- [555,44,33]
- [55544,33]
- [55533,44]
- [555,44,3,3]
- [55544,3,3]
- [5553,44,3]
- [555,4,4,33]
- [5554,4,33]
- [55533,4,4]
- [5,55,44,33]
- [555,4,4,3,3]
- [5554,4,3,3]
- [5553,4,4,3]
- [5,5,5,44,33]
- [55,5,44,3,3]
- [5,55,4,4,33]
- [5,55,4,4,3,3]
- [5,5,5,44,3,3]
- [5,5,5,4,4,33]
- [5,5,5,4,4,3,3]
到这里AI的拆牌逻辑就告一段落了,如果有兴趣了解完整的拆牌逻辑可以给我留言。