上一篇文章对玩家手中的牌进行分析归类,下面就该实现电脑玩家出牌与跟牌的策略了。首先我们来看看出牌的策略,代码如下:

void GameScene::update(float delta){switch (m_iState){case 0:SendPk();break;case 1:schedule(schedule_selector(GameScene::Call),1);break;case 2:scheduleOnce(schedule_selector(GameScene::OutCard),0.5);break;case 3:IsShengLi();break;default:break;}
}

首先解释下该函数,本函数为一个循环,每帧被调用一次。我们看一下头文件里m_iState的注释:

int m_iState;//当前状态 ,0:发牌状态 1:叫地主状态 2:出牌状态 3:结果状态

很明显,出牌和跟牌策略就在状态2,该函数延时0.5秒出牌。我们接下来看下OutCard函数的策略:

void GameScene::OutCard(float delta){switch (m_iOutCard%3){case 0:m_chuPaiMenu->setVisible(true);//显示出牌菜单,包括”不出“,”出牌“m_typeTem = PaiDuanPaiXing();//获得玩家出的牌的牌型,这个函数在cocos2dx《单机斗地主》源码解剖之六 玩家(人)的出牌中有解释。if(!m_npcOne->getIsOutPk() && !m_npcTwo->getIsOutPk())//如果两个电脑玩家没出过牌,设”不出“按钮不可点,反应则然。((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(0))->setEnabled(false);else((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(0))->setEnabled(true);//出牌if(!m_npcOne->getIsOutPk() && !m_npcTwo->getIsOutPk()){//清除所有出的牌ClearOutPk();//下面贴代码if (m_typeTem != ERROR_CARD)//ERROR_CARD为错误的牌型((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(1))->setEnabled(true);else((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(1))->setEnabled(false);}else //跟牌{if(m_arrPlayerOut->count() != 0){Poker* pk = (Poker*)m_arrGenPk->objectAtIndex(0);//要跟的牌Poker* pk1 = (Poker*)m_arrPlayerOut->objectAtIndex(0);//玩家出的牌if(m_typeTem == m_type && pk1->getNum()>pk->getNum() || (m_typeTem==BOMB_CARD && m_type!=BOMB_CARD))//m_type为跟的牌的牌型((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(1))->setEnabled(true);else((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(1))->setEnabled(false);}else((CCMenuItemFont *)m_chuPaiMenu->getChildByTag(1))->setEnabled(false);}break;case 1:m_chuPaiMenu->setVisible(false);if(!m_player->getIsOutPk() && !m_npcOne->getIsOutPk()){//清除所有出的牌ClearOutPk();NpcOutPoker(m_npcTwo,m_arrGenPk,m_npcTwoOut);//电脑出牌策略,函数下面解释。}elseNpcGenPoker(m_npcTwo,m_arrGenPk ,m_npcTwoOut);//电脑跟牌策略,函数下面解释。PlayerOutPaiXu(m_arrGenPk);//对要跟的牌进行排序,该函数在cocos2dx《单机斗地主》源码解剖之六 玩家(人)的出牌有解释。PlayerOutPaiXu(m_npcTwoOut->getArrPk());//对电脑玩家出的牌进行排序m_npcTwoOut->updatePkWeiZhi();//更新位置m_npcTwo->updatePkWeiZhi();//同上++m_iOutCard;if(IsOutPkFinish())//判断游戏是否结束,下面解释。m_iState = 3;break;case 2:if(!m_player->getIsOutPk() && !m_npcTwo->getIsOutPk()){//清除所有出的牌ClearOutPk();NpcOutPoker(m_npcOne,m_arrGenPk,m_npcOneOut);}elseNpcGenPoker(m_npcOne,m_arrGenPk,m_npcOneOut);PlayerOutPaiXu(m_arrGenPk);PlayerOutPaiXu(m_npcTwoOut->getArrPk());m_npcOneOut->updatePkWeiZhi();m_npcOne->updatePkWeiZhi();++m_iOutCard;if(IsOutPkFinish())m_iState = 3;break;default:break;}
}

首先介绍一下这个状态机,我们看头文件对m_iOutCard变量的定义:int m_iOutCard;//论到谁出牌,0为玩家出牌与跟牌的策略,1和2为电脑玩家出牌与跟牌的策略。他们的意义已在代码里添加注释。

在上面代码中你一定发现了有些令人费解的函数(ClearOutPk(),NpcOutPoker(m_npcTwo,m_arrGenPk,m_npcTwoOut),NpcGenPoker(m_npcTwo,m_arrGenPk ,m_npcTwoOut),IsOutPkFinish()),下面一一解释:

ClearOutPk()的代码:

void GameScene::ClearOutPk()
{CCObject* object;
//清除玩家出的牌
    CCARRAY_FOREACH(m_playerOut->getArrPk(),object){Poker* pk = (Poker*)object;pk->setVisible(false);}m_playerOut->getArrPk()->removeAllObjects();
//清除电脑玩家出的牌CCARRAY_FOREACH(m_npcTwoOut->getArrPk(),object){Poker* pk = (Poker*)object;pk->setVisible(false);}m_npcTwoOut->getArrPk()->removeAllObjects();
//同上CCARRAY_FOREACH(m_npcOneOut->getArrPk(),object){Poker* pk = (Poker*)object;pk->setVisible(false);}m_npcOneOut->getArrPk()->removeAllObjects();this->getChildByTag(NpcOneBuChu)->setVisible(false);this->getChildByTag(NpcTwoBuChu)->setVisible(false);
}

NpcOutPoker(m_npcTwo,m_arrGenPk,m_npcTwoOut) 电脑出牌策略:

电脑出牌策略我这里只是简单的判断,打出排在第一位置牌值最小的牌型。

void GameScene::NpcOutPoker(Player* npc,CCArray* out,Player* out1){//隐藏上一次出的牌CCObject* object;CCARRAY_FOREACH(out1->getArrPk(),object){ //out1为上一次出的牌Poker* pk = (Poker*)object;pk->setVisible(false);}out1->getArrPk()->removeAllObjects();//打出牌值最小的一个牌型,也就是排在第一位置的牌型PaiXing px = npc->m_vecPX.front();out->removeAllObjects();//三条出牌原则if(px.type == THREE_CARD){stable_sort(npc->m_vecPX.begin(),npc->m_vecPX.end(),isShorter1);m_type = THREE_CARD;//带单for(std::vector<PaiXing>::iterator iter=npc->m_vecPX.begin();iter!=npc->m_vecPX.end();++iter){//除非只剩两手牌,否则不能带王和2Poker* pk = iter->vec.front();if(pk->getNum() >= Er && npc->m_vecPX.size() != 1)break;if(iter->type == SINGLE_CARD){out1->getArrPk()->addObject(iter->vec.front());out->addObject(iter->vec.front());npc->getArrPk()->removeObject(iter->vec.front());npc->m_vecPX.erase(iter);m_type = THREE_ONE_CARD;break;}}//带双if(out1->getArrPk()->count() == 0){for(std::vector<PaiXing>::iterator iter=npc->m_vecPX.begin();iter!=npc->m_vecPX.end();++iter){//除非只剩两手牌,否则不能带王和2Poker* pk = iter->vec.front();if(pk->getNum() >= Er && npc->m_vecPX.size() != 1)break;if(iter->type == DOUBLE_CARD){for(std::vector<Poker*>::iterator it=iter->vec.begin();it!=iter->vec.end();++it){out1->getArrPk()->addObject(*it);out->addObject(*it);npc->getArrPk()->removeObject(*it);}npc->m_vecPX.erase(iter);m_type = THREE_TWO_CARD;break;}}}}//三顺出牌原则if(px.type == AIRCRAFT_CARD){//有足够的单就带单stable_sort(npc->m_vecPX.begin(),npc->m_vecPX.end(),isShorter1);m_type = AIRCRAFT_CARD;if(GetNpcPxNum(npc,SINGLE_CARD) >= px.vec.size()/3){int num=0;for (std::vector<PaiXing>::iterator it=npc->m_vecPX.begin(); it!=npc->m_vecPX.end()&&num<px.vec.size()/3;){if(it->type == SINGLE_CARD){++num;out1->getArrPk()->addObject(it->vec.front());out->addObject(it->vec.front());npc->getArrPk()->removeObject(it->vec.front());it = npc->m_vecPX.erase(it);m_type = AIRCRAFT_SINGLE_CARD;}else++it;}}//有足够的双就带双if(GetNpcPxNum(npc,DOUBLE_CARD) >= px.vec.size()/3 && out1->getArrPk()->count() == 0){int num=0;for (std::vector<PaiXing>::iterator it=npc->m_vecPX.begin(); it!=npc->m_vecPX.end()&&num<px.vec.size()/3;){if(it->type == DOUBLE_CARD){++num;for(std::vector<Poker*>::iterator ite=it->vec.begin(); ite!=it->vec.end(); ++ite){out1->getArrPk()->addObject(*ite);out->addObject(*ite);npc->getArrPk()->removeObject(*ite);m_type = AIRCRAFT_DOBULE_CARD;}it = npc->m_vecPX.erase(it);}else++it;}}}//连牌出牌原则,直接出,不做处理if(px.type == CONNECT_CARD){m_type = CONNECT_CARD;}//双顺出牌原则,直接出,不做处理if(px.type == COMPANY_CARD){m_type = COMPANY_CARD;}//对子和单子出牌原则if(px.type == DOUBLE_CARD || px.type == SINGLE_CARD){int threeNum = GetNpcPxNum(npc,THREE_CARD)+GetNpcPxNum(npc,AIRCRAFT_CARD);int chiBangNum = GetNpcPxNum(npc,DOUBLE_CARD)+GetNpcPxNum(npc,SINGLE_CARD);//所有三条<=所有对子+所有单牌-2,出对子,否则出三带对if(threeNum <= chiBangNum-2 || threeNum == 0){if(px.type == DOUBLE_CARD)m_type = DOUBLE_CARD;if(px.type == SINGLE_CARD)m_type = SINGLE_CARD;}else{PaiXing px = npc->m_vecPX.front();std::vector<PaiXing>::iterator dle = npc->m_vecPX.begin();npc->m_vecPX.erase(dle);npc->m_vecPX.push_back(px);NpcOutPoker(npc,out,out1);return;}}for(std::vector<Poker*>::iterator iter=px.vec.begin(); iter!=px.vec.end(); ++iter){out1->getArrPk()->addObject(*iter);out->addObject(*iter);npc->getArrPk()->removeObject(*iter);npc->setIsOutPk(true);}m_lastOut = npc;//从npc->m_vecPX中移除pxfor(std::vector<PaiXing>::iterator it=npc->m_vecPX.begin();it!=npc->m_vecPX.end();++it){if(it->type == px.type && it->vec.front()->getNum() == px.vec.front()->getNum()){npc->m_vecPX.erase(it);break;}}
}

NpcGenPoker(m_npcTwo,m_arrGenPk ,m_npcTwoOut),IsOutPkFinish())跟牌策略:

void GameScene::NpcGenPoker(Player* npc,CCArray* out ,Player* out1){//隐藏上一次出的牌if(m_isChiBang){CCObject* object;CCARRAY_FOREACH(out1->getArrPk(),object){Poker* pk = (Poker*)object;pk->setVisible(false);}out1->getArrPk()->removeAllObjects();}/************************************************************************//*找出对应牌型出牌                                                      *//************************************************************************/for (std::vector<PaiXing>::iterator iter=npc->m_vecPX.begin(); iter!=npc->m_vecPX.end(); ++iter){if(m_type == iter->type){//对飞机、连牌进行判断if(m_type == AIRCRAFT_CARD || m_type == CONNECT_CARD || m_type == COMPANY_CARD)if(out->count() != iter->vec.size())continue;Poker* pk = (Poker*)out->objectAtIndex(out->count()-1);Poker* pk1 = iter->vec.front();//如果对方是自己人大于2的牌不出if(!npc->getIsDiZhu() && !m_lastOut->getIsDiZhu()){if(pk1->getNum()>=Er || m_type == BOMB_CARD){//passif(npc == m_npcOne)this->getChildByTag(NpcOneBuChu)->setVisible(true);if(npc == m_npcTwo)this->getChildByTag(NpcTwoBuChu)->setVisible(true);npc->setIsOutPk(false);return;}}if(pk1->getNum() > pk->getNum()){out->removeAllObjects();for(std::vector<Poker*>::iterator it = iter->vec.begin(); it!=iter->vec.end(); ++it){out1->getArrPk()->addObject(*it);npc->getArrPk()->removeObject(*it);out->addObject(*it);}npc->m_vecPX.erase(iter);npc->setIsOutPk(true);m_lastOut = npc;return;}}}//三带一或三带二if(SanDaiYiOrEr(npc,out,out1))return;//四带单或四带双//飞机带单或带双if(FeiJiDaiChiBang(npc,out,out1))return;/************************************************************************//*如果除炸弹还剩一手牌                                                  *//************************************************************************/if(npc->m_vecPX.size() == 2){for (std::vector<PaiXing>::iterator iter=npc->m_vecPX.begin(); iter!=npc->m_vecPX.end(); ++iter){if(iter->type == BOMB_CARD && m_type != BOMB_CARD){out->removeAllObjects();for(std::vector<Poker*>::iterator it = iter->vec.begin(); it!=iter->vec.end(); ++it){out1->getArrPk()->addObject(*it);npc->getArrPk()->removeObject(*it);out->addObject(*it);}npc->m_vecPX.erase(iter);m_lastOut = npc;return;}}}/************************************************************************//* 如果出牌方是自己人不拆牌跟                                        *//************************************************************************/if(!npc->getIsDiZhu() && !m_lastOut->getIsDiZhu()){//passif(npc == m_npcOne)this->getChildByTag(NpcOneBuChu)->setVisible(true);if(npc == m_npcTwo)this->getChildByTag(NpcTwoBuChu)->setVisible(true);npc->setIsOutPk(false);return;}/************************************************************************//*拆单张牌跟之                                                        *//************************************************************************/if(NpcChaiDan(npc,out,out1))return;/************************************************************************//*拆双牌跟之                                                        *//************************************************************************/if(NpcChaiDui(npc,out,out1))return;/************************************************************************//*拆三张牌跟之                                                        *//************************************************************************/if(NpcChaiSan(npc,out,out1))return;/************************************************************************//*拆飞机牌跟之                                                        *//************************************************************************/if(NpcChaiFeiJi(npc,out,out1))return;/************************************************************************//*拆连牌跟之                                                        *//************************************************************************/if(NpcChaiLianPai(npc,out,out1))return;/************************************************************************//*拆双顺跟之                                                        *//************************************************************************/if(NpcChaiShuangShun(npc,out,out1))return;//炸之for (std::vector<PaiXing>::iterator iter=npc->m_vecPX.begin(); iter!=npc->m_vecPX.end(); ++iter){if(iter->type == BOMB_CARD){//如果出牌方出的不是炸弹就炸之,否则比较大小炸之if(m_type != BOMB_CARD){out->removeAllObjects();for(std::vector<Poker*>::iterator it = iter->vec.begin(); it!=iter->vec.end(); ++it){out1->getArrPk()->addObject(*it);npc->getArrPk()->removeObject(*it);out->addObject(*it);}npc->m_vecPX.erase(iter);m_type = BOMB_CARD;npc->setIsOutPk(true);m_lastOut = npc;return;}else{Poker* pk = (Poker*)out->objectAtIndex(0);Poker* pk1 = iter->vec.front();if(pk1->getNum()>pk->getNum()){out->removeAllObjects();for(std::vector<Poker*>::iterator it = iter->vec.begin(); it!=iter->vec.end(); ++it){out1->getArrPk()->addObject(*it);npc->getArrPk()->removeObject(*it);out->addObject(*it);}npc->m_vecPX.erase(iter);m_type = BOMB_CARD;npc->setIsOutPk(true);m_lastOut = npc;return;}}}}//passif(npc == m_npcOne){this->getChildByTag(NpcOneBuChu)->setVisible(true);}if(npc == m_npcTwo){this->getChildByTag(NpcTwoBuChu)->setVisible(true);}npc->setIsOutPk(false);
}

其中代码就不一一分析了,请自行到前三章下载源码阅读。本文章到此结束了!感谢大家的支持!!!

cocos2dx《单机斗地主》源码解剖之八 电脑玩家出牌与跟牌(结束)相关推荐

  1. 单机斗地主源码 android 安卓

    https://download.csdn.net/download/smwhotjay/9456078

  2. 解决天堂2单机/JAVAL2J源码CMD后台乱码

    解决天堂2单机/JAVAL2J源码CMD后台乱码## 解决天堂2单机/JAVAL2J源码CMD后台乱码 ​前言:我们知道现在大部分L2J开源都是国外的,所以很多天堂2源码/开源项目组我们在使用的时候, ...

  3. spark 源码分析之八--Spark RPC剖析之TransportContext和TransportClientFactory剖析

    spark 源码分析之八--Spark RPC剖析之TransportContext和TransportClientFactory剖析 TransportContext 首先官方文档对Transpor ...

  4. Android斗地主源码实现

    2019独角兽企业重金招聘Python工程师标准>>> 用android实现斗地主的源码 斗地主源码: 转载:http://www.adobex.com/android/source ...

  5. C# 网络斗地主源码开源

    C# 网络斗地主源码开源多线程 讨论交流及  下载地址 可以发送聊天消息 转载于:https://www.cnblogs.com/endv/p/7253327.html

  6. PHP实现单人多人聊天源码免费分享 | 电脑报修系统

    源码清单 1. 简易版登陆式聊天源码. 2. 电脑报修轻系统源码. 3. 关注下面公众号回复"聊天",免费获取. 聊天系统 虽然微信,QQ是即时通讯的元老.但是他们限制很多,所以很 ...

  7. 成品app直播源码,iOS键盘弹出遮挡输入框

    成品app直播源码,iOS键盘弹出遮挡输入框解决的相关代码 self.phoneInput = [UITextField new];self.phoneInput.placeholder = @&qu ...

  8. [置顶]       cocos2d-x 手游源码站

    尊重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/37829061 1.魔幻方块 链接:魔幻方块源码 关键 ...

  9. 棋牌微信小游戏之多人在线斗地主源码分享

    游戏说明: 这是一款多人在线的斗地主棋牌游戏,拥有随机匹配功能,有三人同时匹配即可开始游戏.游戏支持微信约战,玩家通过在微信上发送邀请信息给微信好友,好友点击信息即可进入游戏. (PS:需要自己配置自 ...

最新文章

  1. C++知识点42——下标运算符[]的重载及string类的实现
  2. jFreeChary初探
  3. python3 多进程 multiprocessing 报错 AttributeError: ‘ForkAwareLocal‘ object has no attribute ‘connection‘
  4. 皮卡丘为什么不进化_皮卡丘为啥不进化成雷丘?小智都暗示得这么明显皮卡丘还是拒绝了...
  5. mysql算法函数_十个实用MySQL函数
  6. windows局域网文件共享的使用
  7. [Golang]Go语言学习资源集合
  8. Java自动化测试框架-11 - TestNG之annotation与并发测试篇 (详细教程)
  9. c语言编程创意表白,C语言和图形界面编程打造——浪漫的表白程序
  10. 冰蝎2流量分析,解密以及其防守姿势
  11. 网页开发(三)——实现网页前端和数据库的数据交换
  12. 滴滴的大数据可视化效果
  13. python一笔画五角星_五角星怎么画标准(一笔画五角星的顺序)
  14. CSICTF2020随缘Writeup
  15. 树莓派GPIO控制/使用的教程
  16. 【赚钱应跟Apple,做大不忘Google】移动开发时代的开发者选择
  17. AngularJS的$destory用法
  18. c++报错:常量中有换行符(中文编码问题)
  19. android 关闭jack_编译Android时禁用Jack Server
  20. 跨考不容易,各专业跨考建议注意事项!

热门文章

  1. 视频传输解决方案,让视频会议更高效
  2. 从分歧走向融合:图神经网络历经了怎样的演化之路?
  3. gkui服务器下发消息超时,gkui服务器下发消息超时
  4. springboot宴会预定平台毕业设计-附源码231718
  5. macbook 备份系统
  6. Windows 8/8.1下 PL2303 HXA 驱动安装
  7. 【笔记】多因素条件下注意力分配建模
  8. 使用基于注意力的编码器-解码器实现医学图像描述
  9. 大疆Tello UDP控制协议接口
  10. 美团校招php笔试题,【美团点评】2020校招数据分析方向笔试题