当游戏玩家选择好要出的牌以后,首先需要判断该牌型是否符合游戏规则,即合法。如果合法就高亮显示出“出牌”按钮,否则显示灰色“出牌”按钮,表示不可出。怎样判断玩家所选择的牌型是否合法呢?请看下面的代码:
int GameScene::PaiDuanPaiXing(){
//对出的牌进行排序
PlayerOutPaiXu(m_arrPlayerOut);
//牌型判断
int lengh = m_arrPlayerOut->count();
PaiXing px;
//牌的张数少于5张类型判断 单,对,三张,四张
if(lengh0){
Poker* pk = (Poker *)m_arrPlayerOut->objectAtIndex(0);
Poker* pk1 = (Poker *)m_arrPlayerOut->objectAtIndex(lengh-1);
if(pk->getNum() == pk1->getNum())
return lengh;
//三带一
pk1 = (Poker *)m_arrPlayerOut->objectAtIndex(lengh-2);
if(pk->getNum() == pk1->getNum() && lengh == 4)
return THREE_ONE_CARD;
//双鬼
if(pk->getHuaSe()==Gui && pk1->getHuaSe()==Gui)
return BOMB_CARD;
}
//牌的张数大于等于5张的类型判断
if(lengh>=5)
{
//是否为连牌牌型(单)
if(IsLianPai())
return CONNECT_CARD;
if(IsLianDui()) //判断连对
return COMPANY_CARD;
//判断飞机类型
return IsFeiJi();
}
return ERROR_CARD;
}
你一定注意到上面的PlayerOutPaiXu(m_arrPlayerOut);这个函数了,它的作用正是注释所说对出的牌进行排序,以方便分析它的牌型,m_arrPlayerOut是玩家选出的牌。先看以下代码:
void GameScene::PlayerOutPaiXu(CCArray* m_arrPlayerOut){
//对出的牌进行分离
std::vector vec;//JiShu是一个结构体,下面显示代码
while(m_arrPlayerOut->count() > 0)
{
JiShu js;
js.arr = CCArray::create();
//取出第一个
Poker* pk = (Poker*)m_arrPlayerOut->objectAtIndex(0);
m_arrPlayerOut->removeObjectAtIndex(0);
js.num = 1;
js.pkZhi = pk->getNum();
js.arr->addObject(pk);
//找出与第一个相同的牌
int i=0;
while (icount())
{
Poker* pk1 = (Poker*)m_arrPlayerOut->objectAtIndex(i++);
if(pk1->getNum() == pk->getNum())
{
++js.num;
js.arr->addObject(pk1);
m_arrPlayerOut->removeObject(pk1);
--i;
}
}
//把js存储起来用于排序
vec.push_back(js);
}
//对vec进行排序,按牌值从小到大排序
for(int i=0; iaddObjectsFromArray(it->arr);
}
}
//记数 排序出的牌用
struct JiShu
{
int pkZhi;//牌值
int num; //牌数量
CCArray* arr; //集合牌
};
上面综合思想是:判断出的牌“m_arrPlayerOut”里有几个相同的牌并通过JiShu结构体记录下来并保存在std::vector vec中,然后按他们牌值和相同牌的数量进行一次排序,然后再把排序好的牌一个一个放回m_arrPlayerOut中去,这样就会方便以后用来分析牌型了。打个比方:比如出的牌 66633,经过排序会变成33666, 665543经过排序变成345566.
那么上面代码中return BOMB_CARD; return THREE_ONE_CARD;是指什么呢,他们是一个枚举变量,分别代表一个牌型,请看下面代码:
//斗地主共有13种牌型
enum CARD_TYPE
{
SINGLE_CARD = 1, //单牌-
DOUBLE_CARD, //对子-
THREE_CARD, //3不带-
BOMB_CARD, //炸弹
THREE_ONE_CARD, //3带1-
THREE_TWO_CARD, //3带2-
BOMB_TWO_CARD, //四个带2张单牌
BOMB_TWOOO_CARD, //四个带2对
CONNECT_CARD, //连牌-
COMPANY_CARD, //连队-
AIRCRAFT_CARD, //飞机不带-
AIRCRAFT_SINGLE_CARD, //飞机带单牌-
AIRCRAFT_DOBULE_CARD, //飞机带对子-
ERROR_CARD //错误的牌型
} ;
下面分析//牌的张数大于等于5张的类型判断,原代码如下:
int GameScene::PaiDuanPaiXing(){
//对出的牌进行排序
PlayerOutPaiXu(m_arrPlayerOut);
//牌型判断
int lengh = m_arrPlayerOut->count();
PaiXing px;
//牌的张数少于5张类型判断 单,对,三张,四张
if(lengh0){
Poker* pk = (Poker *)m_arrPlayerOut->objectAtIndex(0);
Poker* pk1 = (Poker *)m_arrPlayerOut->objectAtIndex(lengh-1);
if(pk->getNum() == pk1->getNum())
return lengh;
//三带一
pk1 = (Poker *)m_arrPlayerOut->objectAtIndex(lengh-2);
if(pk->getNum() == pk1->getNum() && lengh == 4)
return THREE_ONE_CARD;
//双鬼
if(pk->getHuaSe()==Gui && pk1->getHuaSe()==Gui)
return BOMB_CARD;
}
//牌的张数大于等于5张的类型判断
if(lengh>=5)
{
//是否为连牌牌型(单)
if(IsLianPai())
return CONNECT_CARD;
if(IsLianDui()) //判断连对
return COMPANY_CARD;
//判断飞机类型
return IsFeiJi();
}
return ERROR_CARD;
}
首先看一下IsLianPai()这个代码,这个是判断是否为连牌,比如34567.下面贴上代码:
bool GameScene::IsLianPai(){
int lengh = m_arrPlayerOut->count();
CCArray * arr = m_arrPlayerOut;
//所有牌值必须小于2
CCObject* object;
CCARRAY_FOREACH(arr,object){
if (((Poker *)object)->getNum() >= 12)//12代表牌值2,下面解释为什么
return false;
}
//必须是连续的(前一张牌值加1是否等于后一张牌值)
for(int i=0; iobjectAtIndex(i);
Poker* pk1 = (Poker *)arr->objectAtIndex(i+1);
if(pk->getNum()+1 != pk1->getNum())
return false;
}
return true;
}
大家一定会对上面的12数值感到疑惑,下面截个图来解释:
牌值我是从0开始设置的,比如3的牌值为0,4为1。
接下来放上判断是否是连对 IsLianDui() 代码:
bool GameScene::IsLianDui(){
int lengh = m_arrPlayerOut->count();
CCArray * arr = m_arrPlayerOut;
//所有牌值必须小于2
CCObject* object;
CCARRAY_FOREACH(arr,object){
if (((Poker *)object)->getNum() >= 12)
return false;
}
//大于等于6张牌并且数量为偶数
if(lengh objectAtIndex(i+2);
if(pk->getNum()+1 != pk1->getNum())
return false;
}
return true;
}
判断飞机类型 IsFeiJi()代码,函数名取的有点不合适,它返回的是一种飞机的类型,而不是bool值,所以很抱歉:
int GameScene::IsFeiJi(){
int lengh = m_arrPlayerOut->count();
CRAD_INDEX card_index = FenXiFeiJi();//分析牌是否是飞机,下面解释
//判断三带二
if(card_index.three_index.size()*3+card_index.duble_index.size()*2==lengh && card_index.three_index.size()==1 && card_index.duble_index.size()==1)
return THREE_TWO_CARD;
//判断飞机
if(card_index.three_index.size()>1 && card_index.four_index.empty() && IsFeiJiLian(card_index.three_index)){
//飞机不带
if(card_index.three_index.size()*3 == lengh && card_index.duble_index.size()+card_index.single_index.size() == 0)
return AIRCRAFT_CARD;
//飞机带单
if(card_index.three_index.size()*3+card_index.single_index.size() == lengh && card_index.duble_index.size() == 0)
return AIRCRAFT_SINGLE_CARD;
//飞机带双
if(card_index.three_index.size()*3+card_index.duble_index.size()*2 == lengh && card_index.single_index.size() == 0)
return AIRCRAFT_DOBULE_CARD;
}
//判断四带
if(card_index.three_index.empty() && !card_index.four_index.empty() && lengh%2 == 0)
{
//四带单
if(card_index.four_index.size()*4+card_index.single_index.size() == lengh && card_index.four_index.size()==1 && card_index.single_index.size()==2)
return BOMB_TWO_CARD;
//四带对
if(card_index.four_index.size()*4+card_index.duble_index.size()*2 == lengh && card_index.four_index.size()==1 && card_index.duble_index.size()==1)
return BOMB_TWOOO_CARD;
}
return ERROR_CARD;
}
这里注意CRAD_INDEX card_index = FenXiFeiJi(); 这句代码。
CRAD_INDEX为一种结构体:
struct CRAD_INDEX//分析飞机
{
std::vector single_index;//单张
std::vector duble_index;//双张
std::vector three_index;//三张
std::vector four_index;//四张
};
以上的结构体是为了对出的牌进行分类用,下面看看是如何对牌分类的,下面是FenXiFeiJi()的代码:
CRAD_INDEX GameScene::FenXiFeiJi(){
//分析牌型结构
CCArray* arr = m_arrPlayerOut;
//飞机的类型
CRAD_INDEX m_cardIndex;
for(int i=0; icount();)
{
int time = 0;//相同牌的个数
Poker* pk = (Poker *)arr->objectAtIndex(i);
//找出相同牌
for(int j=i; jcount(); ++j)
{
Poker* pk1 = (Poker *)arr->objectAtIndex(j);
if(pk->getNum() == pk1->getNum()){
++time;
++i;
}
}
//单张
if(time == 1)
nbsp; m_cardIndex.single_index.push_back(pk->getNum());
else if(time == 2)
m_cardIndex.duble_index.push_back(pk->getNum());
else if(time == 3)
m_cardIndex.three_index.push_back(pk->getNum());
else if(time == 4)
m_cardIndex.four_index.push_back(pk->getNum());
}
return m_cardIndex;
}
本章至此结束,下面我们就可以判断玩家(人)出的牌是否合法了
