DFS+DP搜索斗地主玩家手牌最少出牌次数

最近在做一个炸弹斗地主的项目,需要搭建一个离线牌库,筛牌就成为了重点。其实别的部门有这块的功能代码,但是时间充裕,自己做做,效率不行的话,再想办法拿人家的代码吧。。。

与普通斗地主的出牌规则一致:

牌型
火箭(双王)
炸弹
四带2单
四带一对
四带两对
三带1
三带一对
单顺(5张及以上)
双顺(3对及以上)
三顺(2组及以上)
飞机带翅膀(33344456,或者3334445566)
对子
单牌

分析:
在各种牌型中,只有顺子和飞机与牌的点数有关,其他的与牌的点数均无关,也就是说,其他的牌只要每种牌的张数固定了,最少出牌手数就是固定的。
因此用DP数组存储每种情况的出牌次数,然后对顺子和飞机进行深搜即可。算法实际运行挺快的。代码下周整理好再放。

分割线-------------------------------------------------------------------
talk is cheap, show me the code
最近一直在忙,没来的及更新,手数搜索的代码测试过了,已经放到线上使用了,下面讲解下dp的思路以及主要代码:

1.dp状态的定义

一共有五种状态:
(1)当前手中的牌的数量
(2)炸弹的数量, 比如33334444,状态值就是2
(3)三张的数量,比如剩余手牌33367,状态值就是1
(4)对子的数量
(5)单牌的数量
状态有了,dp数组自然就定义出来了:
dp[17][25][25][25][25]: 稍微定义的大了一些,服务端,内存充足,哈哈哈,不影响,可以根据自己项目的需求修改。

2.dp数组的初始化

直接上代码,dp中的拆带牌规则,可以根据需求进行调整,比如现在的代码中是允许将一个炸弹当作两个对子的,也就是可以允许这种出牌: 3333 55 55

void InitAllDPArr()
{
   
    for(int i = 0; i< 17; i ++)
    {
   
        InitDPArr(i + 1, m_dp[i]);// i + 1 代表手牌张数
    }
}

void InitDPArr(int nDPIndex,int (&dp)[25][25][25][25])
{
   
    dp[0][0][0][0] = 0; // base case
    for(int i = 0; i <= nDPIndex; i ++) //四张
    {
   
        for(int j = 0; j <= nDPIndex; j ++) //三张
        {
   
            for(int k = 0; k <= nDPIndex; k ++) //对子 
            {
   
                for(int l = 0;l <= nDPIndex; l ++) //单张 
 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值