11号,硬着头皮吃水饺,不知道馅是什么肉做的,应该没有三会火腿肠好吧.....

这是移植自网上搜索到的两个扑克类游戏,原游戏是MFC做的,移植到了OpenGL中。两者的渲染方式不同,架构有所改变。总共没花几天时间,如果自己从头写估计至少要用几个月。

扑克类游戏主要是数据结构要列好,算法都是初级的入门算法,繁琐但是并不困难。

继续给游戏添加了联机和自动出牌功能,出牌智商有点弱。

抽象出一些基类PokerGame,PokerPlayer方便派生出多种类型的游戏。斗地主游戏PokerDouDiZhu或其它的出牌类游戏比如‘’红心大战‘’都可以继承自PokerGame类。斗地主玩家基类DouDizhuPlayer也继承自PokerPlayer。

还是原先的小游戏架构分三种类型的玩家: (Player、Robot、Role)

DouDizhuPlayer             继承自PokerPlayer是斗地主玩家基类,只有被动出牌功能(只响应出牌消息,不主动发送出牌消息给主机和其它玩家)。

DouDizhuPlayerRobot   继承自DouDizhuPlayer是AI玩家类,具有自动出牌功能(主动发送出牌消息)。

DouDizhuPlayerRole     继承自DouDizhuPlayerRobot是实体玩家类,具有自动出牌功能的同时也可以手选出牌。

对于蜘蛛纸牌游戏,结构上和斗地主类出牌的游戏应该算是两种不同的类型了。这个蜘蛛纸牌游戏只加了提示出牌功能,没有做联机和自动出牌。

定义纸牌ID:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerGame.h
//  @Brief:     PokerGame
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#if !defined(PokerCard_h__)
#define PokerCard_h__//扑克牌ID
enum CardID
{MEIH2=0,MEIH3,MEIH4,MEIH5,MEIH6,MEIH7,MEIH8,MEIH9,MEIH10,MEIHJ,MEIHQ,MEIHK,MEIHA,FANGK2,  FANGK3,  FANGK4,  FANGK5,  FANGK6,  FANGK7,  FANGK8,  FANGK9,  FANGK10, FANGKJ,  FANGKQ,  FANGKK,  FANGKA,  HEIT2,HEIT3,HEIT4,HEIT5,HEIT6,HEIT7,HEIT8,HEIT9,HEIT10,  HEITJ,HEITQ,HEITK,HEITA,HONGT2,  HONGT3,  HONGT4,  HONGT5,  HONGT6,  HONGT7,  HONGT8,  HONGT9,  HONGT10, HONGTJ,  HONGTQ,  HONGTK,  HONGTA,  JokerSmall,      JokerBig,CardNum
};//单张牌
class Card
{
public: Card();int  Color();           //牌的花色bool   bClicked;       //是否被左键选中待出牌int    cardValue;       //牌面值CardID cardID;
};#endif

出牌型游戏基类:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerGame.h
//  @Brief:     PokerGame
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#if !defined(PokerGame_h__)
#define PokerGame_h__#include "Render/Texture.h"
#include "Poker/PokerCard.h"
#include "Rpg/MiniGame.h"#define MaxPlayerCard        20  //玩家最多持牌数
#define RenderShiftX        20  //牌之间距离
#define RenderShiftY        20#define RenderLeftRightSpace  10  //牌距离屏幕左右留空
#define RenderUpDownSpace       10   //牌距离屏幕上下留空
#define RenderUpDownDistance    25   //上下第二排牌距离第一排留空
#define RenderClickedAddDistance    20 //点选后牌高出的长度#define Board2DCen (G_PokerGame->BoardRect2D.GetCen())//显示座位:不同的客户端看到的不一样(不是每个客户端都是坐北朝南)
enum ChairPostion
{SP_Down,SP_Right,SP_Up,SP_Left,
};//网络消息
enum MiniPokerCmd
{CMD_ShuffleCard,  //洗牌CMD_BeLord     ,  //叫地主CMD_NotBeLord  ,  //不叫地主CMD_OutCard    ,  //出牌CMD_Pass       ,  //过CMD_GameOver   ,  //结束CMD_Restart    ,  //重新开始
};
const char* PokerCmdToString(int enumeration);class SoundChannel;
class GuiMovieCtrl;
class PokerGame;
//玩家的数据结构
class PokerPlayer:public MiniPlayer
{
public:PokerPlayer();virtual~PokerPlayer();virtual bool Start();virtual bool Stop();virtual void Update();virtual void Render();virtual void RecvCard(CardID cardID);virtual void SortCard();   //整牌//出牌virtual void OutCard(); //张数int CountCard(int value);//int MinCard(int temp[], int num);//分析牌 各value值的张数void AnalyseCard();bool ClickCards(int cardValue[],int num);        //改变牌状态,标记待出bool ClickCardsID(int cardID[],int num);        //改变牌状态,标记待出int  ClickCard(const vec2& pos);ChairPostion  m_screenPos;          //显示座位:上下左右bool m_workingWithAI;     Card m_cards[MaxPlayerCard];    int  m_cardNum;             int  m_turn;                        //统一座位:东西南北int  m_outNum;                //出到桌面的牌数bool m_notOut;             //不出牌的标记int  ValueCount[18];        //各value值的张数int  m_totalScore;          //记录总分int  m_turnScore;         //记录这回合得分int CardY;                 //south myplayer第一张牌左上角 xyint CardX;                     int m_clickedNum;          //点击待出的牌数bool  m_bBaoPai;PokerGame*  m_game;SoundChannel*  m_sound;GuiMovieCtrl*  m_movieCtrl;
};//准备要出的牌
class ToOutCards
{
public:ToOutCards();Card m_cards[MaxPlayerCard];    int  m_cardNum; //张数int CountCard(int value);//最小的牌int MinCard();
};//游戏状态
enum PokerGameStatus
{Waiting,  //准备Dealing,  //发牌Preparing,//叫地主中Playing,  //进行中Resulting,//显示结果
};//牌的状态
enum CardFlag
{NotDeal = 0,//未发的牌InHand,     //已发牌未出的牌BeOut,      //已出的牌
};class PacketBase;
class PokerGame
{
public:PokerGame();virtual ~PokerGame();virtual bool Start();virtual bool Stop();virtual bool Render();virtual bool Update();virtual bool Free();virtual bool CheckRoundEnd();              //回合结束判断virtual void FirstOut();                    //游戏开始首次出牌  virtual void StateDealCard();               //发牌virtual void SignCard(Card *card);      //标记牌分值virtual void NextTurn();void ShuffleCard();        //洗牌virtual void OutCard(PokerPlayer*player); //出牌PokerPlayer* GetTurnPlayer();       //处理游戏网络命令包virtual int  ProcessPacketCmd(PacketBase* packet);//virtual const char* CmdToString(const char* stream,int len);PokerGameStatus m_gameStatus;CardFlag m_cardFlag[CardNum];       //出牌标记/*CardID*/char   m_cardShuffle[CardNum];    //洗牌结果PokerPlayer*  m_players[4];         PokerPlayer*  m_myPlayer;int  m_playerNum;              int  m_turn;                //出牌位置int  m_lastOutTurn;           //上次出牌位置float m_turnTime;           //换手时间int   m_dealCardNum;float m_dealAccumTime;int CardHeight;             //牌长int CardWidth;              //牌宽bool m_openPoker;bool m_bHost;TexturePtr m_texBack;TexturePtr m_cardTexture[CardNum];TexturePtr m_cardBackTexture;TexturePtr m_thinkTexture[4];TexturePtr m_passTexture[4];TexturePtr m_passButtonTexture;
};#endif //========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerGame.cpp
//  @Brief:     PokerGame
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#include "General/Pch.h"
#include "General/Window.h"
#include "General/Timer.h"
#include "Poker/PokerGame.h"
#include "Render/RendDriver.h"
#include "Render/Texture.h"
#include "Render/Font.h"
#include "Packet/PacketMiniGame.h"
#include "Sound/ChannelSound.h"
#include "Rpg/MiniGame.h"
#include <stdlib.h>
#include "General/Pce.h"
#include "MiniGamePoker.h"
#include "Rpg/SyncGameInfo.h"PokerGame::PokerGame()
{m_gameStatus = Dealing;m_openPoker = false;for (int i=0;i<4;i++){m_players[i] = NULL;}
}PokerGame::~PokerGame()
{Free();
}void PokerGame::StateDealCard()
{
}void PokerGame::OutCard(PokerPlayer*player)
{G_PokerGame->PlaySound__("data/sound/step_foot.wav");for(int i = 0; i < player->m_cardNum; i++){if(player->m_cards[i].bClicked == true){m_cardFlag[player->m_cards[i].cardID] = BeOut;}}player->OutCard();
}void PokerGame::FirstOut()
{
}bool PokerGame::CheckRoundEnd()
{return false;
}bool PokerGame::Render()
{G_RendDriver->Color4f(1,1,1,1);G_RendDriver->SetRenderStateEnable(RS_BLEND,true);G_RendDriver->BlendFunc(Blend_Filter);//if(m_gameStatus == Playing){for(int i = 0; i < m_playerNum; i++){m_players[i]->Render();}}return true;
}bool PokerGame::Start()
{  m_gameStatus = Dealing;m_dealCardNum = 0;m_dealAccumTime = 0;m_turn = 0;m_lastOutTurn = -1;for(int i = 0; i < CardNum; i++)m_cardFlag[i] = NotDeal;G_TextureMgr->AddTexture(m_texBack, "data/minigame/poker/back.png");const char* cardTexName[] = {"data/minigame/poker/mei2.png","data/minigame/poker/mei3.png","data/minigame/poker/mei4.png","data/minigame/poker/mei5.png","data/minigame/poker/mei6.png","data/minigame/poker/mei7.png","data/minigame/poker/mei8.png","data/minigame/poker/mei9.png","data/minigame/poker/mei10.png","data/minigame/poker/meiJ.png","data/minigame/poker/meiQ.png","data/minigame/poker/meiK.png","data/minigame/poker/meiA.png","data/minigame/poker/fang2.png","data/minigame/poker/fang3.png","data/minigame/poker/fang4.png","data/minigame/poker/fang5.png","data/minigame/poker/fang6.png","data/minigame/poker/fang7.png","data/minigame/poker/fang8.png","data/minigame/poker/fang9.png","data/minigame/poker/fang10.png","data/minigame/poker/fangJ.png","data/minigame/poker/fangQ.png","data/minigame/poker/fangK.png","data/minigame/poker/fangA.png","data/minigame/poker/hei2.png","data/minigame/poker/hei3.png","data/minigame/poker/hei4.png","data/minigame/poker/hei5.png","data/minigame/poker/hei6.png","data/minigame/poker/hei7.png","data/minigame/poker/hei8.png","data/minigame/poker/hei9.png","data/minigame/poker/hei10.png","data/minigame/poker/heiJ.png","data/minigame/poker/heiQ.png","data/minigame/poker/heiK.png","data/minigame/poker/heiA.png","data/minigame/poker/hong2.png","data/minigame/poker/hong3.png","data/minigame/poker/hong4.png","data/minigame/poker/hong5.png","data/minigame/poker/hong6.png","data/minigame/poker/hong7.png","data/minigame/poker/hong8.png","data/minigame/poker/hong9.png","data/minigame/poker/hong10.png","data/minigame/poker/hongJ.png","data/minigame/poker/hongQ.png","data/minigame/poker/hongK.png","data/minigame/poker/hongA.png","data/minigame/poker/xiaowang.png","data/minigame/poker/dawang.png",};for (int i=0;i<CardNum;i++){G_TextureMgr->AddTexture(m_cardTexture[i],cardTexName[i]);}G_TextureMgr->AddTexture(m_cardBackTexture,"data/minigame/poker/cardback01.png");G_TextureMgr->AddTexture(m_passTexture[0],"data/minigame/poker/donotout00.png");G_TextureMgr->AddTexture(m_passTexture[1],"data/minigame/poker/donotout01.png");G_TextureMgr->AddTexture(m_passTexture[2],"data/minigame/poker/donotout02.png");G_TextureMgr->AddTexture(m_passTexture[3],"data/minigame/poker/donotout03.png");G_TextureMgr->AddTexture(m_thinkTexture[0],"data/minigame/poker/think00.png");G_TextureMgr->AddTexture(m_thinkTexture[1],"data/minigame/poker/think01.png");G_TextureMgr->AddTexture(m_thinkTexture[2],"data/minigame/poker/think02.png");G_TextureMgr->AddTexture(m_thinkTexture[3],"data/minigame/poker/think03.png");G_TextureMgr->AddTexture(m_passButtonTexture,"data/minigame/poker/donotoutbutton.png");CardHeight = 96;CardWidth = 71;if (m_bHost){ShuffleCard();C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_ShuffleCard);  //todo每个人只发各自的牌,地主牌叫过另发。防止外挂作弊。packet.WriteValue(m_cardShuffle);    //seed即可G_MiniGame->SendPacketToOther(&packet);}else{for (int i = 0; i < CardNum; i++){m_cardShuffle[i] = -1;}}return true;
}
bool PokerGame::Stop()
{  Free();return true;
}
PokerPlayer* PokerGame::GetTurnPlayer()
{return m_players[m_turn];
}void PokerGame::SignCard(Card *card)
{}bool PokerGame::Update()
{m_turnTime += G_Timer->GetStepTimeLimited();if (m_gameStatus == Preparing||m_gameStatus == Playing){GetTurnPlayer()->Update();}return true;
}bool PokerGame::Free()
{for (int i=0;i<4;i++){SafeDelete(m_players[i]);}return true;
}void PokerGame::NextTurn()
{int nextTurn = (++m_turn) % m_playerNum;m_turn = nextTurn;m_players[nextTurn]->m_outNum = 0;m_players[nextTurn]->m_notOut = 0;//m_players[(1+m_turn) % m_playerNum]->m_notOut = 0;m_turnTime = 0;
}void PokerGame::ShuffleCard() //洗牌
{for (int i = 0; i < CardNum; i++){m_cardShuffle[i] = (CardID)i;}// 随机i-1中的任意一个数与i交换for (int i = 2; i < CardNum; i++){int ran = Rand()%i;char temp = m_cardShuffle[ran];m_cardShuffle[ran] = m_cardShuffle[i];m_cardShuffle[i] = temp;}
}int  PokerGame::ProcessPacketCmd(PacketBase* packet)
{int cmd;packet->ReadValue(cmd);switch(cmd){case CMD_ShuffleCard:{//todo 只发自己的牌packet->ReadValue(m_cardShuffle);}return 1;}return 0;
}Card::Card()
{bClicked = false;
}int Card::Color()
{if(cardID == JokerSmall){return 4; //小王 黑桃&&梅花}else if(cardID == JokerBig){return 5;}else if(cardID >= 0 && cardID < JokerSmall){return cardID / 13;}return 0;
}PokerPlayer::PokerPlayer()
:m_workingWithAI(false)
,m_clickedNum(0)
,m_movieCtrl(NULL)
{m_sound = new SoundChannel;
}PokerPlayer::~PokerPlayer()
{SafeDelete(m_sound);
}void PokerPlayer::AnalyseCard()
{for(int i = 0; i < 18; i++){ValueCount[i] = CountCard(i);}
}int  PokerPlayer::MinCard(int temp[], int num)
{int i, min = temp[0];for(i = 1; i < num; i++){if(temp[i] < min){min = temp[i];}}return min;
}int  PokerPlayer::CountCard(int value)
{int n = 0; for(int i = 0 ; i < m_cardNum ; i++){if(m_cards[i].cardValue == value)n++;}return n;
}void PokerPlayer::RecvCard(CardID cardID)
{m_cards[m_cardNum].cardID = cardID;m_cards[m_cardNum].bClicked = false;m_game->SignCard(&m_cards[m_cardNum]);m_cardNum++;m_sound->PlaySound__("data/sound/chess_duk.wav");
}bool PokerPlayer::Start()
{for(int j = 0; j < MaxPlayerCard; j++){m_cards[j].cardID = (CardID)0;m_cards[j].cardValue = -1;m_cards[j].bClicked = false;}m_cardNum = 0;m_outNum = 0;m_screenPos = SP_Up;m_totalScore = 0;m_turnScore = 0;m_bBaoPai = false;return true;
}bool PokerPlayer::Stop()
{Free();return true;
}void PokerPlayer::OutCard()
{Card card;int outNum = 0;int i = 0;while(i < m_cardNum){if(m_cards[i].bClicked == true){card = m_cards[i];//把被选中的牌挪到最后(显示出牌用),后面依次前移for(int j = i; j < MaxPlayerCard; j++)m_cards[j] = m_cards[j+1];card.bClicked = false;m_cards[MaxPlayerCard - 1] = card;m_cardNum--;outNum++;}elsei++;}m_outNum = outNum;m_clickedNum = 0;
}void PokerPlayer::SortCard()
{}void PokerPlayer::Update()
{}void PokerPlayer::Render()
{int CardHeight=m_game->CardHeight;             int CardWidth=m_game->CardWidth;    ///显示名字if (GetPlayerInfo()){if(m_screenPos == SP_Down){G_FontMgr->TextAtPos(vec2(Board2DCen.x - 33,  G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace), GetPlayerInfo()->playerName);}else if(m_screenPos == SP_Up){G_FontMgr->TextAtPos(vec2(Board2DCen.x - 33,  G_PokerGame->BoardRect2D.y+RenderUpDownSpace), GetPlayerInfo()->playerName);}else if(m_screenPos == SP_Right){G_FontMgr->TextAtPos(vec2(G_Window->m_iWidth - 66 - 5, Board2DCen.y), GetPlayerInfo()->playerName);}else if(m_screenPos == SP_Left){G_FontMgr->TextAtPos(vec2(5, Board2DCen.y), GetPlayerInfo()->playerName);}}G_RendDriver->Color3f(1,1,1);///显示未出的牌bool canSee = m_game->m_openPoker;//明牌switch(m_screenPos){case SP_Down:{CardX = Board2DCen.x - ((m_cardNum - 1) * RenderShiftX + CardWidth)/2;CardY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace - CardHeight;for(int i = 0; i < m_cardNum; i++){if(m_cards[i].bClicked == false){m_game->m_cardTexture[m_cards[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF(CardX+i* RenderShiftX, CardY, CardWidth, CardHeight));}else{m_game->m_cardTexture[m_cards[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF(CardX+i * RenderShiftX, CardY -RenderClickedAddDistance, CardWidth, CardHeight));}}}break;case SP_Right:{int x = G_PokerGame->BoardRect2D.GetRight() - RenderLeftRightSpace- CardWidth;int y = Board2DCen.y - (m_cardNum * RenderShiftY + CardHeight)/2;for(int i = 0; i < m_cardNum; i++){if (canSee) m_game->m_cardTexture[m_cards[i].cardID]->Bind();elsem_game->m_cardBackTexture->Bind();G_RendDriver->DrawTextureRect(RectF(x, y + i * RenderShiftY, CardWidth, CardHeight));}}break;case SP_Up:{int x = Board2DCen.x - ((m_cardNum - 1) * RenderShiftX + CardWidth)/2; int y = G_PokerGame->BoardRect2D.y + RenderUpDownSpace;for(int i = 0; i < m_cardNum; i++){if (canSee) m_game->m_cardTexture[m_cards[i].cardID]->Bind();elsem_game->m_cardBackTexture->Bind();G_RendDriver->DrawTextureRect(RectF(x + i * RenderShiftX, y, CardWidth, CardHeight));}}break;case SP_Left:{int x = G_PokerGame->BoardRect2D.x + RenderLeftRightSpace;int y = Board2DCen.y - (m_cardNum * RenderShiftY + CardHeight)/2;for(int i = 0; i < m_cardNum; i++){if (canSee) m_game->m_cardTexture[m_cards[i].cardID]->Bind();elsem_game->m_cardBackTexture->Bind();G_RendDriver->DrawTextureRect(RectF(x, y + i * RenderShiftY, CardWidth, CardHeight));}}break;}显示所出的牌{int outX, outY;int i, j;if(m_screenPos == SP_Down){outX = Board2DCen.x - m_outNum * RenderShiftX/2 - RenderShiftX;outY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace - CardHeight * 2 - RenderUpDownDistance;for(i = MaxPlayerCard - m_outNum, j=0; i < MaxPlayerCard; i++, j++){m_game->m_cardTexture[m_cards[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF( outX+j * RenderShiftX, outY, CardWidth,CardHeight));}}if(m_screenPos == SP_Right){outX = G_PokerGame->BoardRect2D.GetRight() - RenderLeftRightSpace - CardWidth*2.8f; outY = Board2DCen.y - ((m_outNum - 1) * RenderShiftY + CardHeight)/2;for(i = MaxPlayerCard - m_outNum, j = 0; i < MaxPlayerCard; i++, j++){m_game->m_cardTexture[m_cards[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF(outX, outY+j * RenderShiftY, CardWidth,CardHeight ));}}if(m_screenPos == SP_Up){outX = Board2DCen.x - ((m_outNum - 1) * RenderShiftX + CardWidth)/2;outY = G_PokerGame->BoardRect2D.y + RenderUpDownSpace + CardHeight + RenderUpDownDistance;for(i = MaxPlayerCard - m_outNum, j=0; i < MaxPlayerCard; i++, j++){m_game->m_cardTexture[m_cards[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF( outX+j * RenderShiftX, outY , CardWidth,CardHeight ));}}if(m_screenPos == SP_Left){outX = G_PokerGame->BoardRect2D.x + RenderLeftRightSpace + CardWidth*1.8f; outY = Board2DCen.y - ((m_outNum - 1) * RenderShiftY + CardHeight)/2;for(i = MaxPlayerCard - m_outNum, j = 0; i < MaxPlayerCard; i++, j++){m_game->m_cardTexture[m_cards[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF(outX, outY+j * RenderShiftY, CardWidth,CardHeight));}}}
}
//标记要出牌
bool PokerPlayer::ClickCards(int cardValue[],int num)
{int find = 0;for(int i = 0; i < num; i++){for(int j = 0; j < m_cardNum; j++){if(m_cards[j].cardValue == cardValue[i] && m_cards[j].bClicked == false //有可能两张相同value){find++;m_cards[j].bClicked = true;break;}}}assert(find == num);return (find == num);
}
//标记要出牌
bool PokerPlayer::ClickCardsID(int cardID[],int num)
{int find = 0;for(int i = 0; i < num; i++){for(int j = 0; j < m_cardNum; j++){if(m_cards[j].cardID == cardID[i] && m_cards[j].bClicked == false //有可能两张相同value){find++;m_cards[j].bClicked = true;break;}}}assert(find == num);return (find == num);
}int  PokerPlayer::ClickCard(const vec2& mousePos)
{int x1, y1, x2, y2;x1 = CardX;y1 = CardY - RenderClickedAddDistance;x2 = (m_cardNum - 1) * RenderShiftX + m_game->CardWidth + CardX;y2 = CardY + m_game->CardHeight;if((mousePos.x < x2) && (mousePos.x > x1) && (mousePos.y > y1) && (mousePos.y < y2)){if(m_cardNum != 0){ int n;n = (mousePos.x - CardX) / RenderShiftX;if(n >= m_cardNum)n = m_cardNum - 1;if(m_cards[n].bClicked == false){m_cards[n].bClicked = true;m_clickedNum++;}else if(m_cards[n].bClicked == true){m_cards[n].bClicked = false;m_clickedNum--;}m_sound->PlaySound__("data/sound/chess_duk.wav");}}return 0;
}ToOutCards::ToOutCards()
{for(int i = 0; i < MaxPlayerCard; i++){m_cards[i].cardID = (CardID)0;m_cards[i].cardValue = -1;}m_cardNum = 0;
}int  ToOutCards::MinCard()
{int min = m_cards[0].cardValue;for(int i = 1; i < m_cardNum; i++){if(m_cards[i].cardValue < min){min = m_cards[i].cardValue;}}return min;
}int  ToOutCards::CountCard(int value)
{int n = 0; for(int i = 0 ; i < m_cardNum ; i++)if(m_cards[i].cardValue == value)n++;return n;
}const char* PokerCmdToString(int enumeration)
{switch(enumeration){case CMD_ShuffleCard:return "CMD_ShuffleCard";       case CMD_BeLord     :return "CMD_BeLord     ";        case CMD_NotBeLord  :return "CMD_NotBeLord  ";        case CMD_OutCard    :return "CMD_OutCard    ";        case CMD_Pass       :return "CMD_Pass       ";    case CMD_GameOver   :return "CMD_GameOver   ";        case CMD_Restart    :return "CMD_Restart    ";        default             :return "CMD_unknow";}return "CMD_unknow";
}

斗地主游戏派生类:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerDouDiZhu.h
//  @Brief:     PokerDouDiZhu
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#if !defined(DouDiZhu_h__)
#define DouDiZhu_h__#include "PokerGame.h"//准备要出的牌
class ToOutCardsDouDizhu:public ToOutCards
{
public:};enum OutType
{None = -1,GZ = 0, //单张DZ    , //对子SZ    , //顺子SGBD  , //三张不带SD1   , //三带一SD2   , //三带二SD2G  , //四带二SD2D  , //四带二对LD3   , //三连对LD4   ,LD5   ,LD6   ,LD7   ,FJBD  , //飞机不带FJD2G , //飞机带二个FJD2D , //飞机带两对SFJBD , //三飞机不带SFJDSG, //三飞机带三个SFJDSD, //三飞机带三对ZD    , //炸弹SW    , //双王
};
struct CurOutCards
{int  value;OutType type;//char type[10];int  num;int  min;
};
class DouDizhuPlayerRobot;
class DouDizhuPlayerRole;class PokerDouDiZhu:public PokerGame
{
public:enum CardValue{Value3 = 3,Value4,Value5,Value6,Value7,Value8,Value9,Value10,ValueJ,ValueQ,ValueK,ValueA = 14,Value2 = 15,ValueJokerSmall = 16,      ValueJokerBig = 17,};PokerDouDiZhu();virtual ~PokerDouDiZhu();virtual bool Start();virtual bool Stop();virtual bool Render();virtual bool Update();virtual bool CheckRoundEnd();                //结束判断virtual void StateDealCard();             //发牌void StateDecideLord();                     //选地主//注意:不要循环发送,比如主机发过来,调用了几层函数又发回去void SendDecideLord(int turn);                  //void DecideLord(int turn);                  //选出地主virtual void SignCard(Card *card);         //标记牌分值virtual void FirstOut();                 //首次出牌      //没出的最大单牌int MaxCard();                         void OnRButtonDown();bool Button_NotBeLord();bool Button_BeLord();bool Button_Pass();//处理游戏网络命令包virtual int  ProcessPacketCmd(PacketBase* packet);//virtual const char* CmdToString(const char* stream,int len);int  m_winnerTurn;              //标记哪个是赢家int  m_lordTurn;               //地主位置Card m_lordCard[3];               //三张地主牌CurOutCards         m_curOutCards;ToOutCardsDouDizhu  m_toOutCards;      //准备要出的牌DouDizhuPlayerRole* m_myRolePlayer; TexturePtr m_lordTexture;TexturePtr m_notbeLordTexture;TexturePtr m_notbeLordButtonTexture;TexturePtr m_sanfenButtonTexture;TexturePtr m_winTexture;TexturePtr m_loseTexture;//炸弹倍数int m_zhadanNum;};
extern PokerDouDiZhu* G_PokerDouDiZhu;#endif//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerDouDiZhu.cpp
//  @Brief:     PokerDouDiZhu
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#include "General/Pch.h"
#include "General/Timer.h"
#include "General/Window.h"
#include "Input/InputMgr.h"
#include "Poker/PokerDoudizhu.h"
#include "Poker/PokerGame.h"
#include "Poker/DouDiZhuPlayer.h"
#include "Poker/MiniGamePoker.h"
#include "Poker/MiPoker_PlayGui.h"
#include "Net/PacketList.h"
#include "Gui/MiniGuis.h"
#include "Gui/GuiMgr.h"
#include "Gui/GuiControlMisc.h"
#include "Rpg/MiniGame.h"
#include "Rpg/SyncGameInfo.h"
#include "Packet/PacketMiniGame.h"
#include "Render/RendDriver.h"
#include "Render/Texture.h"
#include "Sound/ChannelSound.h"
#include "General/Pce.h"PokerDouDiZhu* G_PokerDouDiZhu = NULL;PokerDouDiZhu::PokerDouDiZhu()
{m_lastOutTurn = -1;m_lordTurn = -1;m_winnerTurn = -1;G_PokerDouDiZhu = this;}PokerDouDiZhu::~PokerDouDiZhu()
{}bool PokerDouDiZhu::Start()
{m_myRolePlayer = NULL;//?PokerGame::Start();G_TextureMgr->AddTexture(m_notbeLordTexture,"data/minigame/poker/bujiao.png");G_TextureMgr->AddTexture(m_notbeLordButtonTexture,"data/minigame/poker/bujiaobutton.png");G_TextureMgr->AddTexture(m_lordTexture,"data/minigame/poker/islord.png");G_TextureMgr->AddTexture(m_sanfenButtonTexture,"data/minigame/poker/sanfen.png");G_TextureMgr->AddTexture(m_winTexture,"data/minigame/poker/win.png");G_TextureMgr->AddTexture(m_loseTexture,"data/minigame/poker/lose.png");m_turnTime = 0;m_lordTurn = -1;m_myPlayer = NULL;//m_playerNum = 3;for(int i = 0; i < m_playerNum; i++){MyRoomPlayerInfo* playerInfo = G_SyncMyRoomInfo->GetPlayerFromIndex(i);if (playerInfo){//roomSlot 不一定连续,但已经排序if (playerInfo->roomSlot == G_SyncMyRoomInfo->m_myRoomSlot){m_players[i] = m_myRolePlayer = new DouDizhuPlayerRole;m_myPlayer = m_myRolePlayer;}else{if (G_PokerGame->IsHost()==false ||playerInfo->isAI==false){//非主机上ai表现同实体玩家m_players[i] = new DouDizhuPlayer;}else{//主机负责ai玩家的模拟m_players[i] = new DouDizhuPlayerRobot;}}m_players[i]->SetPlayerInfo(playerInfo);}else{return false;}}//if (m_myRolePlayer){m_myRolePlayer->m_toOutCard = &m_toOutCards;}else{return false;}for(int i = 0; i < m_playerNum; i++){dynamic_cast<DouDizhuPlayer*>(m_players[i])->g_curOutCards = &m_curOutCards;m_players[i]->m_turn = i;m_players[i]->m_game = this;m_players[i]->Start();}//MiPoker_PlayGui* playGui = G_GuiMgr->GetGui<MiPoker_PlayGui>();if (playGui && playGui->IsAwake()){//自动出牌if(m_myPlayer)m_myPlayer->m_workingWithAI = playGui->m_textButtonOption[2]->GetState()==GCS_CLICK;//明牌m_openPoker = playGui->m_textButtonOption[3]->GetState()==GCS_CLICK;}//int myTurn = m_myRolePlayer?m_myRolePlayer->m_turn:0;m_players[myTurn]->m_screenPos = SP_Down;m_players[++myTurn%m_playerNum]->m_screenPos = SP_Right;m_players[++myTurn%m_playerNum]->m_screenPos = SP_Left;//进入miniplaygui,(选人、选关卡都已在房间里进行完毕)。//if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);return true;
}
bool PokerDouDiZhu::Stop()
{Free();return true;
}
bool PokerDouDiZhu::Update()
{PokerGame::Update();switch(m_gameStatus){case Dealing:StateDealCard();break;case Preparing:{//call backif (G_Mouse->IsButtonDowning(MOUSE_LEFT)){if(Button_BeLord()) return true;if(Button_NotBeLord()) return true;}}break;case Playing:{CheckRoundEnd();if (G_Mouse->IsButtonDowning(MOUSE_LEFT)){//todo set ui visible  + call backif(Button_Pass()) return true;}//call backif (G_Mouse->IsButtonDowning(MOUSE_RIGHT)){OnRButtonDown();}}break;case Resulting:{if (m_turnTime > 5){if (m_bHost){C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_Restart);  G_MiniGame->SendPacketToOther(&packet);}Free();Start(); //send shuffle}}break;}return true;
}
bool PokerDouDiZhu::Render()
{PokerGame::Render();//if(m_gameStatus == Playing || m_gameStatus == Preparing){//显示地主牌{int x, y;x =   Board2DCen.x - CardWidth * 5/2;y = G_PokerGame->BoardRect2D.y + RenderUpDownDistance;if(m_gameStatus == Playing){for(int i = 0; i < 3; i++){m_cardTexture[m_lordCard[i].cardID]->Bind();G_RendDriver->DrawTextureRect(RectF( x+i * 2 * CardWidth, y, CardWidth,CardHeight));}}else{//未叫显示背面for(int i = 0; i < 3; i++){m_cardBackTexture->Bind();G_RendDriver->DrawTextureRect(RectF(x + i * 2 * CardWidth, y, CardWidth, CardHeight));}}}}if (m_gameStatus == Resulting){if (m_myRolePlayer==NULL|| m_winnerTurn == m_myRolePlayer->m_turn|| (m_winnerTurn!=m_lordTurn && m_myRolePlayer->IsLord()==false) ){m_winTexture->Bind();G_RendDriver->DrawTextureRect(vec2(Board2DCen.x-m_winTexture->GetWidth()/2, Board2DCen.y-m_winTexture->GetHeight()/2));}else{m_loseTexture->Bind();G_RendDriver->DrawTextureRect(vec2(Board2DCen.x-m_loseTexture->GetWidth()/2, Board2DCen.y-m_loseTexture->GetHeight()/2));}}return true;
}bool PokerDouDiZhu::CheckRoundEnd()
{//if(m_players[m_turn]->m_cardNum == 0)//{//  m_winnerTurn = m_turn;//   GameOver();//   return true;//}bool gameOver = false;for(int i = 0; i < m_playerNum; i++){if(m_players[i]->m_cardNum == 0){m_winnerTurn = i;gameOver = true;}}if(gameOver&&m_bHost){int fen = 3;if(m_winnerTurn == m_lordTurn)fen = -3;//fen *= zhadan;for(int i = 0; i < m_playerNum; i++){if(i!=m_lordTurn)m_players[i]->m_totalScore += fen ;elsem_players[i]->m_totalScore -= fen*2;}char sound[256];if (m_winnerTurn == m_lordTurn){sprintf(sound,"data/sound/poker/play_lord_win");}else{sprintf(sound,"data/sound/poker/play_farmer_win");}if (m_winnerTurn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_players[m_winnerTurn]->m_sound->PlaySound__(sound);C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_GameOver);  packet.WriteValue(m_winnerTurn); G_MiniGame->SendPacketToOther(&packet);m_gameStatus = Resulting;m_turnTime = 0;}return gameOver;
}//标记牌值
void PokerDouDiZhu::SignCard(Card *card)
{int id = card->cardID;if(id == JokerSmall){card->cardValue = 16;}else if(id == JokerBig){card->cardValue =  17;}else if(id >= 0 && id < JokerSmall){card->cardValue = (id + 12) %13 + 3;}
}void PokerDouDiZhu::StateDealCard()
{//另外三张决定地主后再发if (m_dealCardNum>=51){for(int i = 0; i < m_playerNum; i++)m_players[i]->SortCard();m_gameStatus = Preparing;return;}m_dealAccumTime += G_Timer->GetStepTime();//0.1秒发一张if (m_dealAccumTime > m_dealCardNum*0.1f){CardID cardID = (CardID)m_cardShuffle[m_dealCardNum];if (cardID>=0){m_cardFlag[cardID] = InHand;int playerIndex = m_dealCardNum % m_playerNum;m_players[playerIndex]->RecvCard(cardID);m_dealCardNum++;}else{//host洗牌还没发下来}}
}void PokerDouDiZhu::SendDecideLord(int turn)
{C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_BeLord);  packet.WriteValue(m_turn); //todo给lord发三张地主牌,目前是洗牌时已经发送G_MiniGame->SendPacketToOther(&packet);
}
void PokerDouDiZhu::DecideLord(int turn)
{m_lordTurn = turn;m_lastOutTurn = turn;m_turn = turn;m_turnTime = 0;m_gameStatus = Playing;for(int i = 0; i < 3; i++){m_lordCard[i].cardID = (CardID)m_cardShuffle[i+CardNum-3];}//给地主发三张牌for(int i = 0; i < 3; i++)m_players[m_lordTurn]->RecvCard(m_lordCard[i].cardID);m_players[m_lordTurn]->SortCard();char sound[256];sprintf(sound,"data/sound/poker/call_jiaofeng_3");if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");if(m_myRolePlayer)m_myRolePlayer->m_sound->PlaySound__(sound);}
//决定地主
void PokerDouDiZhu::StateDecideLord()
{
}void PokerDouDiZhu::FirstOut()
{}//现存最大单牌
int  PokerDouDiZhu::MaxCard()
{if(m_cardFlag[JokerBig] != BeOut)return 17;if(m_cardFlag[JokerSmall] != BeOut)return 16;int max = 0;for(int i = 0; i < JokerSmall; i++){if(m_cardFlag[i] != BeOut && max < (i +12) % 13)max = (i + 12) % 13 + 3;}return max;
}void PokerDouDiZhu::OnRButtonDown()
{if(m_myRolePlayer==NULL||m_turn != m_myRolePlayer->m_turn)return;if(m_gameStatus != Playing)return;m_myRolePlayer->m_notOut = 0;//?if(m_gameStatus == Playing && m_myRolePlayer->TryOutCard()){OutCard(m_myRolePlayer);//if (CheckRoundEnd()==false){C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_OutCard);  packet.WriteValue(m_myRolePlayer->m_turn); packet.WriteValue(m_curOutCards); //packet.WriteValue(m_myRolePlayer->m_outNum); for(int i = MaxPlayerCard - m_myRolePlayer->m_outNum; i < MaxPlayerCard; i++){packet.WriteValue(m_myRolePlayer->m_cards[i].cardID);}G_MiniGame->SendPacketToOther(&packet);m_lastOutTurn = m_myRolePlayer->m_turn;NextTurn();}}
}//人当地主
bool PokerDouDiZhu::Button_BeLord()
{if(m_myRolePlayer==NULL||m_turn != m_myRolePlayer->m_turn)return false;if(m_gameStatus != Preparing)return false;int ClickX = G_PokerGame->GetMousePos().x;int ClickY = G_PokerGame->GetMousePos().y;int buttonX = Board2DCen.x - 80;int buttonY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-32;if(ClickX>buttonX  && ClickX<buttonX+m_sanfenButtonTexture->GetWidth() && ClickY>buttonY && ClickY < buttonY+m_sanfenButtonTexture->GetHeight()){G_PokerDouDiZhu->SendDecideLord(m_turn);DecideLord(m_myRolePlayer->m_turn);return true;}return false;
}//人不当地主
bool PokerDouDiZhu::Button_NotBeLord()
{if(m_myRolePlayer==NULL||m_turn != m_myRolePlayer->m_turn)return false;if(m_gameStatus != Preparing)return false;int ClickX = G_PokerGame->GetMousePos().x;int ClickY = G_PokerGame->GetMousePos().y;int buttonX = G_Window->m_iWidth/2 + 20;int buttonY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-32;if(ClickX>buttonX  && ClickX<buttonX+m_notbeLordButtonTexture->GetWidth() && ClickY>buttonY && ClickY < buttonY+m_notbeLordButtonTexture->GetHeight()){C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_NotBeLord);  packet.WriteValue(m_myRolePlayer->m_turn); G_MiniGame->SendPacketToOther(&packet);m_turn = (m_myRolePlayer->m_turn+1) % m_playerNum;m_turnTime = 0;//NextTurn()char sound[256];sprintf(sound,"data/sound/poker/call_bujiao");if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_myRolePlayer->m_sound->PlaySound__(sound);return true;}return false;
}
bool PokerDouDiZhu::Button_Pass()
{if(m_myRolePlayer==NULL||m_lastOutTurn == m_myRolePlayer->m_turn)return false;if(m_turn != m_myRolePlayer->m_turn)return false;if(m_gameStatus != Playing)return false;int ClickX = G_PokerGame->GetMousePos().x;int ClickY = G_PokerGame->GetMousePos().y;int buttonX = Board2DCen.x - 30;int buttonY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-32;if(ClickX>buttonX  && ClickX<buttonX+m_passButtonTexture->GetWidth() && ClickY>buttonY && ClickY < buttonY+m_passButtonTexture->GetHeight()){C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_Pass);  packet.WriteValue(m_myRolePlayer->m_turn); G_MiniGame->SendPacketToOther(&packet);m_myRolePlayer->m_notOut = 1;NextTurn();char sound[256];sprintf(sound,"data/sound/poker/play_guo_%d",Rand()%2);if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_myRolePlayer->m_sound->PlaySound__(sound);return true;}return false;
}int  PokerDouDiZhu::ProcessPacketCmd(PacketBase* packet)
{PokerGame::ProcessPacketCmd(packet);packet->SeekPos(PacketBase::HeadSize);int cmd;packet->ReadValue(cmd);switch(cmd){case CMD_BeLord:{int turn = 0;packet->ReadValue(turn);DecideLord(turn);}break;case CMD_NotBeLord:{int turn = 0;packet->ReadValue(turn);m_turn = turn;NextTurn();char sound[256];sprintf(sound,"data/sound/poker/call_bujiao");if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_myRolePlayer->m_sound->PlaySound__(sound);}break;case CMD_Pass:{int turn = 0;packet->ReadValue(turn);m_turn = turn;m_players[m_turn]->m_notOut = true;NextTurn();char sound[256];sprintf(sound,"data/sound/poker/play_guo_%d",Rand()%2);if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_players[m_turn]->m_sound->PlaySound__(sound);}break;case CMD_OutCard:{int turn = 0;packet->ReadValue(turn);packet->ReadValue(m_curOutCards); //int outNum;int cardID[MaxPlayerCard];packet->ReadValue(outNum); for(int i = 0; i < outNum; i++){packet->ReadValue(cardID[i]);}dynamic_cast<DouDizhuPlayer*>(m_players[turn])->ClickCardsID(cardID,outNum);m_turn = turn;m_lastOutTurn = turn;m_players[turn]->m_notOut = false;OutCard(m_players[turn]);NextTurn();}break;case CMD_GameOver:{int turn = 0;packet->ReadValue(turn);m_winnerTurn = turn;m_turnTime = 0;m_gameStatus = Resulting;char sound[256];if (m_winnerTurn == m_lordTurn){sprintf(sound,"data/sound/poker/play_lord_win");}else{sprintf(sound,"data/sound/poker/play_farmer_win");}if (m_winnerTurn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_players[m_winnerTurn]->m_sound->PlaySound__(sound);}break;case CMD_Restart:Free();Start();break;}return 0;
}

斗地主玩家派生类:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerDouDiZhu.h
//  @Brief:     PokerDouDiZhu
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#if !defined(DouDizhuPlayer_h__)
#define DouDizhuPlayer_h__#include "PokerGame.h"class DouDizhuPlayer:public PokerPlayer
{
public:DouDizhuPlayer();virtual bool Start();//virtual void Update();virtual void Render();virtual void SortCard();         //整牌virtual void OutCard(); bool IsLord();                      //是否地主bool IsMyTurn();                    //是否轮到CurOutCards* g_curOutCards;
};class DouDizhuPlayerRobot:public DouDizhuPlayer
{
public:virtual bool Start();virtual void Update();virtual void Render();bool ThinkOutCard();                //出牌void OutFirst();                    //先出bool OutFollow();                   //跟牌void FirstLianZi();                 //出串void FirstSanZhang();               //出三张,含三带一void FirstDuiZi();                 //出对子void FirstDanZhang();              //出单牌void FirstZhaDan();                    //出炸弹void FirstDanJoker();              //出单大王void FirstJoker();                    //出双王bool searchDanJoker();             //查找是否有单王,且为大王bool searchJoker();                    //查找是否有双王bool searchZhaDan();               //查找有无炸弹bool searchSanZhang();              //查找有无三张bool searchDuiZi();                 //查找有无对子bool searchDanZhang();              //查找有无单张bool searchLianZi();                //查找有无连子bool FollowLianZi();                //跟连子bool FollowSanZhang();             //跟三张bool FollowSiDai2();               //出四带二bool FollowSanDaiYi();                //出三带一bool FollowDuiZi();                   //跟对子bool FollowDanZhang();             //跟单牌bool FollowZhaDan();               //跟炸弹int m_position;                        //标记牌位置int m_lianziLen;                 //顺子的长度int m_lianziLast;                    //顺尾};class DouDizhuPlayerRole:public DouDizhuPlayerRobot
{
public:DouDizhuPlayerRole();virtual bool Start();virtual void Update();virtual void Render();virtual bool TryOutCard();                     //出牌void SaveOutCard();                 //保存待出的牌bool sd(int temp[]);                //是否三对,要求不同bool sfjdsd();                        //三飞机带三对bool ld7();                         //七连对bool ld6();                            //六连对bool ld5();                            //五连对bool fjd2d();                      //飞机带2对bool sfjbd();                        //三飞机不带bool sfjdsg();                       //三飞机带三个bool ld(int temp[]);                //连对bool sd2d();                        //四带二对bool ld4();                           //四连对bool fjd2g();                      //飞机带二个bool fjbd();                     //飞机不带bool sd2g();                      //三带二个bool ld3();                           //三连对bool sz(int);                      //顺子bool sd2();                         //四带二bool zd();                         //炸弹bool sd1();                         //三带一bool sgbd();                       //三个不带bool sw();                            //双王bool dz();                          //对子ToOutCardsDouDizhu*  m_toOutCard;   //准备要出的牌//int m_clickedNum;                 //点击待出的牌数};#endif//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerDouDiZhu.cpp
//  @Brief:     PokerDouDiZhu
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#include "General/Pch.h"
#include "General/Timer.h"
#include "General/Window.h"
#include "Input/InputMgr.h"
#include "Render/RendDriver.h"
#include "Poker/PokerDoudizhu.h"
#include "Poker/PokerGame.h"
#include "Poker/DouDiZhuPlayer.h"
#include "Poker/MiniGamePoker.h"
#include "Packet/PacketMiniGame.h"
#include "Sound/ChannelSound.h"
#include "Rpg/MiniGame.h"
#include "Gui/GuiMgr.h"
#include "Gui/GuiControlMisc.h"
#include "General/Pce.h"//DouDizhuPlayer析构的时候报告过heap corruption detected:after normal block(#xxx) at 0x xxxxxxxx
//原因:DouDizhuPlayer* p = new DouDizhuPlayer;  ((DouDizhuPlayerRobot*)p)->m_toOutCard = ; 错误的静态强制转换会导致堆栈溢出。
DouDizhuPlayer::DouDizhuPlayer()
{
}bool DouDizhuPlayer::Start()
{PokerPlayer::Start();m_notOut = 0;m_workingWithAI = false;return true;
}
void DouDizhuPlayer::Render()
{PokerPlayer::Render();int CardHeight=m_game->CardHeight;               int CardWidth=m_game->CardWidth;    Texture* texture;//switch()if(m_game->m_gameStatus == Playing&&IsLord()){//显示地主标志texture = G_PokerDouDiZhu->m_lordTexture;texture->Bind();if(m_screenPos == SP_Down){G_RendDriver->DrawTextureRect(vec2(Board2DCen.x - texture->GetWidth()/2,  G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace));}else if(m_screenPos == SP_Right){G_RendDriver->DrawTextureRect(vec2(G_PokerGame->BoardRect2D.GetRight()-RenderLeftRightSpace, Board2DCen.y - texture->GetHeight()));}else if(m_screenPos == SP_Left){G_RendDriver->DrawTextureRect(vec2(G_PokerGame->BoardRect2D.x+RenderLeftRightSpace-texture->GetWidth(), Board2DCen.y - texture->GetHeight()));}}//显示不出状态if(m_notOut == 1){int index = int(G_Timer->GetAccumTime()/10)%4;texture = m_game->m_passTexture[index];texture->Bind();if(m_screenPos == SP_Down){int posY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace - CardHeight * 2;G_RendDriver->DrawTextureRect(vec2(Board2DCen.x ,  posY));}else if(m_screenPos == SP_Left){G_RendDriver->DrawTextureRect(vec2(G_PokerGame->BoardRect2D.x+RenderLeftRightSpace+CardWidth*1.8f, Board2DCen.y - texture->GetHeight()));}else if(m_screenPos == SP_Right){G_RendDriver->DrawTextureRect(vec2(G_PokerGame->BoardRect2D.GetRight()-RenderLeftRightSpace-CardWidth*2.8f, Board2DCen.y - texture->GetHeight()));}}//显示思考中if((m_game->m_gameStatus==Playing||m_game->m_gameStatus==Preparing)&&IsMyTurn()){//m_ctrlThink->SetVisible(true);int index = int(G_Timer->GetAccumTime()*10)%4;texture = m_game->m_thinkTexture[index];texture->Bind();if(m_screenPos == SP_Down){G_RendDriver->DrawTextureRect(vec2(Board2DCen.x + 100 ,  G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-texture->GetHeight()));}else if(m_screenPos == SP_Left){G_RendDriver->DrawTextureRect(vec2(G_PokerGame->BoardRect2D.x+RenderLeftRightSpace+CardWidth, Board2DCen.y));}else if(m_screenPos == SP_Right){G_RendDriver->DrawTextureRect(vec2(G_PokerGame->BoardRect2D.GetRight()-RenderLeftRightSpace-CardWidth-texture->GetWidth(), Board2DCen.y));}}//显示叫地主按钮if(G_PokerDouDiZhu->m_gameStatus == Preparing){//显示叫地主按钮int posX;if(IsMyTurn()){if(m_screenPos == SP_Down){G_PokerDouDiZhu->m_sanfenButtonTexture->Bind();G_RendDriver->DrawTextureRect(vec2(Board2DCen.x - 80, G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-32));G_PokerDouDiZhu->m_notbeLordButtonTexture->Bind();G_RendDriver->DrawTextureRect(vec2(Board2DCen.x + 20, G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-32));}else if(m_screenPos == SP_Left){posX = G_PokerGame->BoardRect2D.x+RenderLeftRightSpace + CardWidth*1.8f; G_PokerDouDiZhu->m_sanfenButtonTexture->Bind();G_RendDriver->DrawTextureRect(vec2(posX, Board2DCen.y - 80));G_PokerDouDiZhu->m_notbeLordButtonTexture->Bind();G_RendDriver->DrawTextureRect(vec2(posX, Board2DCen.y + 20));}else if(m_screenPos == SP_Right){posX = G_PokerGame->BoardRect2D.GetRight() - RenderLeftRightSpace - CardWidth*2.8f; G_PokerDouDiZhu->m_sanfenButtonTexture->Bind();G_RendDriver->DrawTextureRect(vec2(posX, Board2DCen.y - 80));G_PokerDouDiZhu->m_notbeLordButtonTexture->Bind();G_RendDriver->DrawTextureRect(vec2(posX, Board2DCen.y + 20));}}else{//显示叫地主状态if(m_screenPos == SP_Down){G_PokerDouDiZhu->m_notbeLordTexture->Bind();int posY = G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace - CardHeight * 2;G_RendDriver->DrawTextureRect(vec2(Board2DCen.x, posY));}else if(m_screenPos == SP_Left){posX = G_PokerGame->BoardRect2D.x+RenderLeftRightSpace + CardWidth*1.8f; G_PokerDouDiZhu->m_notbeLordTexture->Bind();G_RendDriver->DrawTextureRect(vec2(posX, Board2DCen.y + 20));}else if(m_screenPos == SP_Right){posX = G_PokerGame->BoardRect2D.GetRight() - RenderLeftRightSpace - CardWidth*2.8f; G_PokerDouDiZhu->m_notbeLordTexture->Bind();G_RendDriver->DrawTextureRect(vec2(posX, Board2DCen.y + 20));}}}}
void DouDizhuPlayer::SortCard()
{int i, j;int idi, idj;Card card;for(i = 0 ; i < m_cardNum ; i++){for(j = i ; j < m_cardNum ; j++){idi = m_cards[i].cardValue;idj = m_cards[j].cardValue;if(idj > idi||((idi == idj) && (m_cards[j].Color() > m_cards[i].Color()))){card = m_cards[j];m_cards[j] = m_cards[i];m_cards[i] = card;}}}
}bool DouDizhuPlayer::IsLord()
{return G_PokerDouDiZhu->m_lordTurn == m_turn;
}bool DouDizhuPlayer::IsMyTurn()
{return G_PokerDouDiZhu->m_turn == m_turn;
}void DouDizhuPlayer::OutCard()
{PokerPlayer::OutCard();if(m_bBaoPai==false&&m_cardNum <=2){char sound[256];if(m_cardNum == 1){sprintf(sound,"data/sound/poker/play_bao1");}if(m_cardNum == 2){sprintf(sound,"data/sound/poker/play_bao2");}if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_sound->PlaySound__(sound);m_bBaoPai = true;return;}char sound[256];switch (g_curOutCards->type){case GZ:sprintf(sound,"data/sound/poker/one_poker_%d",g_curOutCards->value-PokerDouDiZhu::Value3);break;case DZ:sprintf(sound,"data/sound/poker/two_poker_%d",g_curOutCards->value-PokerDouDiZhu::Value3);break;case SGBD:sprintf(sound,"data/sound/poker/play_3zhang");break;case SD1:sprintf(sound,"data/sound/poker/play_3dai1");break;case SD2:sprintf(sound,"data/sound/poker/play_3dai2");break;case SD2G:case SD2D:sprintf(sound,"data/sound/poker/play_4dai2");break;case SZ:sprintf(sound,"data/sound/poker/play_shun");break;case LD3:sprintf(sound,"data/sound/poker/play_sandui");break;case LD4:case LD5:case LD6:case LD7:sprintf(sound,"data/sound/poker/play_liandui");break;case FJBD:case FJD2G:case FJD2D:case SFJBD:case SFJDSG:case SFJDSD:sprintf(sound,"data/sound/poker/play_feiji");break;case ZD:sprintf(sound,"data/sound/poker/play_zhadan_%d",Rand()%3);break;case SW:sprintf(sound,"data/sound/poker/play_wangzha");break;default:sprintf(sound,"data/sound/poker/play_dani");break;}if (m_turn%2) //{strcat(sound,"_femail.wav");}else{strcat(sound,".wav");}m_sound->PlaySound__(sound);//播放出牌动作 todo 装备扑克道具if(m_movieCtrl){String name = m_movieCtrl->GetRenderCharacterUI()->GetCurAnimName();if(name == "stand")m_movieCtrl->GetRenderCharacterUI()->PlayAnim("attack");elsem_movieCtrl->GetRenderCharacterUI()->PlayAnim("stand");}//todo call back 播一次结束后恢复站位
}bool DouDizhuPlayerRobot::Start()
{DouDizhuPlayer::Start();m_workingWithAI = true;return true;
}void DouDizhuPlayerRobot::Update()
{PokerPlayer::Update();//if (m_bAI == true)if (m_game->m_turn == m_turn&& m_game->m_turnTime>1.0f //思考时间){switch(m_game->m_gameStatus){case Preparing:{int cardNum = 0;for(int i = 0; i < m_cardNum; i++){if(m_cards[i].cardValue > PokerDouDiZhu::ValueA){cardNum++;}}//有两张大牌,叫地主if(cardNum >= 2){G_PokerDouDiZhu->SendDecideLord(m_turn);G_PokerDouDiZhu->DecideLord(m_turn);return;}else{//真实玩家都不叫if(Rand()%4==0){G_PokerDouDiZhu->SendDecideLord(m_turn);G_PokerDouDiZhu->DecideLord(m_turn);}return;}m_game->NextTurn();C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_NotBeLord);  packet.WriteValue(m_turn); G_MiniGame->SendPacketToOther(&packet);char sound[256];sprintf(sound,"data/sound/poker/call_bujiao");if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_sound->PlaySound__(sound);}break;case Playing:{ThinkOutCard();if(m_notOut==false){//outm_game->OutCard(this);//if (m_game->CheckRoundEnd()==false){C2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_OutCard);  packet.WriteValue(m_turn); packet.WriteValue(*g_curOutCards);  //packet.WriteValue(m_outNum); for(int i = MaxPlayerCard - m_outNum; i < MaxPlayerCard; i++){packet.WriteValue(m_cards[i].cardID);}G_MiniGame->SendPacketToOther(&packet);m_game->m_lastOutTurn = m_turn;m_game->NextTurn();}}else{//passC2SPacketMiniGameCmd packet;packet.WriteHeader();packet.WriteValue(CMD_Pass);  packet.WriteValue(m_turn); G_MiniGame->SendPacketToOther(&packet);m_game->NextTurn();char sound[256];sprintf(sound,"data/sound/poker/play_guo_%d",Rand()%2);if (m_turn%2) //strcat(sound,"_femail.wav");elsestrcat(sound,".wav");m_sound->PlaySound__(sound);}}break;}}
}void DouDizhuPlayerRobot::Render()
{DouDizhuPlayer::Render();
}bool DouDizhuPlayerRobot::ThinkOutCard()
{int LastOutTurn = G_PokerDouDiZhu->m_lastOutTurn;m_notOut = 1;AnalyseCard();if(LastOutTurn == m_turn){OutFirst();m_notOut = 0;}else{int before = (m_turn + 2) % 3;int after  = (m_turn + 1) % 3;bool tryFollow = false;//要不要出牌if(IsLord())   {//自己是地主tryFollow = true;}else if(LastOutTurn == G_PokerDouDiZhu->m_lordTurn) {//地主出的牌tryFollow = true;}else                                    {//非地主出的牌if(g_curOutCards->num==m_cardNum)//出牌可以赢 出完{tryFollow = true;}else if(m_cardNum <= 2)  //手里只有1、2张牌,快赢了{tryFollow = true;}else if(g_curOutCards->type == GZ && g_curOutCards->value <10) //出牌太小{tryFollow = true;}else if(g_curOutCards->type == DZ && g_curOutCards->value < 8) //出牌太小{tryFollow = true;}}if (tryFollow){//是否划算:拆牌   王打三if(OutFollow())//能不能出牌m_notOut = 0;}}return true;
}//先出算法
void DouDizhuPlayerRobot::OutFirst()
{//很少出4张,留着炸弹用//连子能找出飞机来?//先出得分最小的牌  可以被带的除外//出连子  连子太大也可以先不出  连到2 也可以只出一半if(searchLianZi()){FirstLianZi();return;}//出 单张 对子 三张中的较小者   单张数少的话考虑带OutType bestType = None;int     bestValue = 999;//单张if(searchDanZhang()){if (m_position<bestValue){bestType = GZ;bestValue = m_position;}}//对子if(searchDuiZi()){if (m_position<bestValue){bestType = DZ;bestValue = m_position;}}//三张if(searchSanZhang()){if (m_position<bestValue){bestType = SGBD;bestValue = m_position;}}//恢复m_position = bestValue;//出单张if(bestType == GZ){FirstDanZhang();return;}//出对子if(bestType == DZ){FirstDuiZi();return;}//出三张if(bestType == SGBD){FirstSanZhang(); //会带return;}//出炸弹if(searchZhaDan()){FirstZhaDan();return;}//出双王if(searchJoker()){FirstJoker();return;}//出单王if(searchDanJoker()){FirstDanJoker();return;}else{}
}//跟牌算法
bool DouDizhuPlayerRobot::OutFollow()
{if(g_curOutCards->type == GZ) //单张{if(FollowDanZhang()) return true;  else{if(searchDanJoker())   //有王出之{FirstDanJoker();return true;}if(searchZhaDan())      //有炸弹出之{FirstZhaDan();return true;}          }}else if(g_curOutCards->type == DZ)  //对子{if(FollowDuiZi()) return true;else {if(searchZhaDan())    //有炸弹出之{FirstZhaDan();return true;}else{if(searchJoker())//有双王出之{FirstJoker();return true;}}}}else if(g_curOutCards->type == SGBD)  //三张{if(FollowSanZhang())return true;else{if(searchZhaDan())    //有炸弹出之{FirstZhaDan();return true;}else if(searchJoker())   //有双王出之{FirstJoker();return true;}}}else if(g_curOutCards->type == SD1)    //三带一{if(FollowSanDaiYi())return true;else{if(searchZhaDan())    //有炸弹出之{FirstZhaDan();return true;}else if(searchJoker())  //有双王出之{FirstJoker();return true;}}}     else if(g_curOutCards->type == SZ)    //连子{if(FollowLianZi())return true;else{if(searchZhaDan())    //有炸弹出之{FirstZhaDan();return true;}else if(searchJoker()) //有双王出之{FirstJoker();return true;}; }}else if(g_curOutCards->type == SD2G) //四带二{if(FollowSiDai2())return true;else{if(searchZhaDan()) //有炸弹出之{FirstZhaDan();return true;}else if(searchJoker())   //有双王出之{FirstJoker();return true;}}}else if(g_curOutCards->type == ZD) //炸弹{if(FollowZhaDan())return true;else{if(searchJoker())//有双王出之{FirstJoker();return true;}}}return false;
}//出连子
void DouDizhuPlayerRobot::FirstLianZi()
{int start = m_lianziLast - m_lianziLen;   //连子开始组号int a1[12] = {0};int i = 0; for( i = 0; start < m_lianziLast + 1; start++, i++){a1[i] = start;}for(int j = 0; j < i + 1; j++)//改牌的状态为出了的{for(int k = 0;k < 20;k++){if(m_cards[k].cardValue == a1[j]){m_cards[k].bClicked = true;break;}}}g_curOutCards->value = a1[i - 1];g_curOutCards->num = i;g_curOutCards->min = a1[0];g_curOutCards->type = SZ;
}//出单张
void DouDizhuPlayerRobot::FirstDanZhang()
{for(int k = 0; k < 20; k++)//改牌的状态为出了的{if(m_cards[k].cardValue == m_position){             m_cards[k].bClicked = 1;break;}}g_curOutCards->value = m_position;g_curOutCards->num = 1 ;g_curOutCards->type = GZ;
}//出对子
void DouDizhuPlayerRobot::FirstDuiZi()
{int n = 0;for(int k = 0; k < 20; k++)//改牌的状态为出了的{if(m_cards[k].cardValue == m_position){m_cards[k].bClicked = true;n++;if(n >= 2)break;}}g_curOutCards->value = m_position;g_curOutCards->num = 2;g_curOutCards->type = DZ;
}//出三张
void DouDizhuPlayerRobot::FirstSanZhang()
{int i = m_position;assert(ValueCount[i] == 3);int j = 0;int bt = 0;while(!bt){if(ValueCount[j] == 1 && j != i){int a1[4] = {0};a1[0] = i;a1[1] = i;a1[2] = i;a1[3] = j;bt = 1;g_curOutCards->value = a1[0];g_curOutCards->num = 4;g_curOutCards->type = SD1;ClickCards(a1,g_curOutCards->num);return;}else {j++;if(j>12){int a1[3] = {0};a1[0] = i;a1[1] = i;a1[2] = i;g_curOutCards->value = a1[0];g_curOutCards->num = 3;g_curOutCards->type = SGBD;ClickCards(a1,g_curOutCards->num);return;}}       }
}//出炸弹
void DouDizhuPlayerRobot::FirstZhaDan()
{int n = 0;for(int k = 0; k < 20; k++)//改牌的状态为出了{if(m_cards[k].cardValue == m_position){m_cards[k].bClicked = true;n++;if(n >= 4)break;}}g_curOutCards->value = m_position;g_curOutCards->num = 4;g_curOutCards->type = ZD;
}//出双王
void DouDizhuPlayerRobot::FirstJoker()
{for(int k = 0; k < 20; k++)      //改牌的状态为出了的{if((m_cards[k].cardID == JokerSmall || m_cards[k].cardID == JokerBig) && m_cards[k].bClicked == false){m_cards[k].bClicked = true;}}g_curOutCards->num = 2 ;g_curOutCards->value = 17;g_curOutCards->type = SW;
}//出单大王
void DouDizhuPlayerRobot::FirstDanJoker()
{for(int k = 0; k < 20; k++)//改牌的状态为出了的{if(m_cards[k].cardValue == m_position){m_cards[k].bClicked = true;break;}}g_curOutCards->value = m_position;g_curOutCards->num = 1;g_curOutCards->type = GZ;
}//找单张,在顺子后找3---2
bool DouDizhuPlayerRobot::searchDanZhang()
{m_position = -1;  if(m_cardNum < 3 && !searchJoker()){//还剩两张int j = 0, a[2] = {0};for(int i = 0; i <= PokerDouDiZhu::ValueJokerBig; i++){if(ValueCount[i] == 1)a[j++] = i;}//第二张最大if(a[1] == G_PokerDouDiZhu->MaxCard())m_position = a[1];elsem_position = a[0];}else{//从小到大找for(int i = 0; i < PokerDouDiZhu::ValueJokerSmall; i++){if(ValueCount[i] == 1){m_position = i;break;    }}}if(m_position != -1) return true;else return false;
}//找对子
bool DouDizhuPlayerRobot::searchDuiZi()
{m_position = -1;for(int i = 0; i < PokerDouDiZhu::ValueJokerSmall; i++){if(ValueCount[i] == 2){m_position = i;break;    }    }if(m_position != -1) return true;else return false;
}//找三张
bool DouDizhuPlayerRobot::searchSanZhang()
{m_position = -1;for(int i = 0; i < PokerDouDiZhu::Value2; i++){if(ValueCount[i] == 3){m_position = i;break;    }    }if(m_position != -1) return true;return false;
}//找炸弹
bool DouDizhuPlayerRobot::searchZhaDan()
{m_position = -1;for(int i = 0; i < PokerDouDiZhu::ValueJokerSmall; i++){if(ValueCount[i] == 4){m_position = i;break;    }    }if(m_position != -1) return true; return false;
}//找双王
bool DouDizhuPlayerRobot::searchJoker()
{if(ValueCount[PokerDouDiZhu::ValueJokerBig] > 0 && ValueCount[PokerDouDiZhu::ValueJokerSmall] > 0){return true;}return false;
}//找连子
bool DouDizhuPlayerRobot::searchLianZi()
{int restValues[12] = {0};int maxLian = 0;m_lianziLast = -1;m_lianziLen = 1;for(int i = 0; i < PokerDouDiZhu::ValueQ; i++) //最大J可以连子{if(ValueCount[i] > 0) restValues[maxLian++] = i;    //连续存放还有的牌value-3, value不再连续}//不会找出三连对,play时只会抽出一张for(int i = 0; i < maxLian - 1; i++){if(restValues[i+1] == restValues[i]+1&& restValues[i]+1 < PokerDouDiZhu::Value2){m_lianziLen++;if(m_lianziLen >= 5)m_lianziLast = restValues[i] + 1;//能连一直继续continue;}//不能继续连了if(m_lianziLen < 5) {//打断连子,重新计数,继续m_lianziLen = 1;m_lianziLast = -1;}else{//已经找好return true;}}if(m_lianziLen < 5)return false;return true;
}//找单大王
bool DouDizhuPlayerRobot::searchDanJoker()
{if(ValueCount[PokerDouDiZhu::ValueJokerBig] > 0 && ValueCount[PokerDouDiZhu::ValueJokerSmall] == 0){m_position = PokerDouDiZhu::ValueJokerBig;return true;}return false;
}//跟单张牌的情况
bool DouDizhuPlayerRobot::FollowDanZhang()
{//对手连出 或对手牌很少 拆牌必要性加大for(int i = g_curOutCards->value+1; i <= PokerDouDiZhu::ValueJokerBig ; i++){if(ValueCount[i] == 1 || (ValueCount[i] > 1 && i == PokerDouDiZhu::Value2) //多个2可拆//|| //地主牌仅剩1张//|| 上家是地主 或自己是地主 上家一直破单张作弊){int a1[1] = {0};a1[0] = i;ClickCards(a1,g_curOutCards->num); //出牌后对玩家手中的牌进行相应清理g_curOutCards->value = a1[0];g_curOutCards->num = 1 ;g_curOutCards->type = GZ;return true;}}return false;
}//跟对子
bool DouDizhuPlayerRobot::FollowDuiZi()
{//不同时期 剩余牌数不同 评分标准也不同//对手连出 或对手牌很少 拆牌必要性加大for(int i = g_curOutCards->value+1; i <= PokerDouDiZhu::Value2; i++){if(ValueCount[i]==2 || (ValueCount[i] > 2 && i == PokerDouDiZhu::Value2)   //多个2可拆//|| (ValueCount[i] > 2 && i>= PokerDouDiZhu::ValueA)  //多个>A可拆   对2没有时再拆A//|| //地主牌仅剩2张){int a1[2] = {0};a1[0] = i;a1[1] = i;ClickCards(a1,g_curOutCards->num);        //出牌后对玩家手中的牌进行相应清理g_curOutCards->value = a1[0] ;g_curOutCards->num = 2;g_curOutCards->type = DZ;return 1;}}return 0;
}//跟三张
bool DouDizhuPlayerRobot::FollowSanZhang()
{for(int i = g_curOutCards->value+1; i <= PokerDouDiZhu::Value2; i++){if(ValueCount[i] == 3){int a1[3] = {0};a1[0] = i;a1[1] = i;a1[2] = i;ClickCards(a1,g_curOutCards->num);g_curOutCards->value = a1[0];g_curOutCards->num = 3;g_curOutCards->type = SGBD;return true;}}return false;
}//跟连子
bool DouDizhuPlayerRobot::FollowLianZi()
{int lens = 1;int end = 0;for(int i = g_curOutCards->value+1; i < PokerDouDiZhu::ValueQ && lens < g_curOutCards->num; i++){for(int j = 0; j < g_curOutCards->num; j++, i++)if(ValueCount[i] > 0){lens++;if(j == g_curOutCards->num - 1)end = i;}else{lens = 1;break;}}//找到匹配的连子if(lens == g_curOutCards->num){int start = -1;start = end - g_curOutCards->num + 1;  //连子开始组号int a1[12] = {0};int i = 0; for( i = 0; i < g_curOutCards->num; i++)a1[i] = start++;ClickCards(a1,g_curOutCards->num);g_curOutCards->value = a1[i];g_curOutCards->min = a1[0];g_curOutCards->num = i - 1;g_curOutCards->type = SZ;return true;}//未找到匹配的连子else   return false;
}//四带二只能带对子
bool DouDizhuPlayerRobot::FollowSiDai2()
{//4个2 不用作带牌?todo更智能的判断for(int i = g_curOutCards->value+1; i < PokerDouDiZhu::Value2; i++){if(ValueCount[i] == 4){int j = 0;int bt = 0;while(!bt){if(ValueCount[j] == 2){int a1[8] = {0};int ans = i;    for(int k = 0; k < 4; k++)a1[k] = ans++;    a1[4] = j;a1[5] = j + 1;ClickCards(a1,g_curOutCards->num); bt = 1;g_curOutCards->value = a1[0];g_curOutCards->num = 8;g_curOutCards->type = SD2G;return true;}else {j++;if(j > 12){bt = 1;return false;} }       } }}    return false;
}//用炸弹炸掉
bool DouDizhuPlayerRobot::FollowZhaDan()
{//4个2 用作炸弹?for(int i = g_curOutCards->value+1; i <= PokerDouDiZhu::Value2; i++){if(ValueCount[i] == 4){int a1[4] = {0};int ans = i;   for(int k = 0; k < 4; k++)a1[k] = ans++;ClickCards(a1,g_curOutCards->num); g_curOutCards->value = a1[0];g_curOutCards->num = 4;g_curOutCards->type = ZD;return true;}}return false;
}
//出三带一
bool DouDizhuPlayerRobot::FollowSanDaiYi()
{for(int i = g_curOutCards->value+1; i < PokerDouDiZhu::Value2; i++){if(ValueCount[i] == 3){int j = 0;int bt = 0;while(!bt){if(ValueCount[j] == 1 && j != i){int a1[4] = {0};a1[0] = i;a1[1] = i;a1[2] = i;a1[3] = j;bt = 1;g_curOutCards->value = a1[0];g_curOutCards->num = 4;g_curOutCards->type = SD1;ClickCards(a1,g_curOutCards->num); return true;}else {j++;if(j > 12) return false;}       }    }}return false;
}DouDizhuPlayerRole::DouDizhuPlayerRole()
//:m_clickedNum(0)
{}bool DouDizhuPlayerRole::Start()
{DouDizhuPlayerRobot::Start();m_workingWithAI = false;return true;
}void DouDizhuPlayerRole::Update()
{if (m_workingWithAI == true){DouDizhuPlayerRobot::Update();}else{if (m_game->m_turn == m_turn){switch(m_game->m_gameStatus){case Preparing:{//if (G_Mouse->IsButtonDowning(MOUSE_LEFT))//{//  if(Button_BeLord()) return;//   if(Button_NotBeLord()) return;//}}break;case Playing:{//if (G_Mouse->IsButtonDowning(MOUSE_LEFT))//{//   //todo set ui visible  + call back//   if(Button_Pass()) //        return true;//  m_myRolePlayer->ClickCard(this->GetMousePos());//}//if (G_Mouse->IsButtonDowning(MOUSE_RIGHT))//{//    OnRButtonDown();//}if (G_PokerGame->IsButtonDowning(MOUSE_LEFT)){ClickCard(G_PokerGame->GetMousePos());}}break;}}}
}void DouDizhuPlayerRole::Render()
{//PokerPlayer::Render();DouDizhuPlayerRobot::Render();int CardHeight=m_game->CardHeight;               int CardWidth=m_game->CardWidth;    //显示不出按钮{if(m_game->m_turn == m_turn && m_game->m_lastOutTurn != m_turn&& m_game->m_gameStatus == Playing){m_game->m_passButtonTexture->Bind(); G_RendDriver->DrawTextureRect(vec2(Board2DCen.x - 30, G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace-CardHeight-32));}}//if(m_game->m_gameStatus == Playing//    &&IsLord())//{//    //显示地主//    G_PokerDouDiZhu->m_isLordTexture->Bind();//   if(m_screenPos == SP_Down)//  {//     G_RendDriver->DrawTextureRect(vec2(Board2DCen.x - 33,  G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace));//    }//}显示叫地主按钮//{//    if(IsMyTurn()//     && G_PokerDouDiZhu->m_gameStatus == Preparing)//   {//     G_PokerDouDiZhu->m_sanfenButtonTexture->Bind();//     G_RendDriver->DrawTextureRect(vec2(Board2DCen.x - 80, G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace));//     G_PokerDouDiZhu->m_buJiaoButtonTexture->Bind();//     G_RendDriver->DrawTextureRect(vec2(Board2DCen.x + 20, G_PokerGame->BoardRect2D.GetBottom()-RenderUpDownSpace));//    }//}
}//保存待出的牌
void DouDizhuPlayerRole::SaveOutCard()
{for(int i = 0; i < MaxPlayerCard; i++)m_toOutCard->m_cards[i].cardID = (CardID)-1;int num = 0;for(int i = 0; i < m_cardNum; i++){if(m_cards[i].bClicked == true){m_toOutCard->m_cards[num++] = m_cards[i];    }}m_toOutCard->m_cardNum = num;
}bool DouDizhuPlayerRole::TryOutCard()
{if(m_clickedNum <= 0)return false;SaveOutCard();int tmp = g_curOutCards->value;if(G_PokerDouDiZhu->m_lastOutTurn != m_turn){switch(m_clickedNum){case 0:   return false;case 1:{if(g_curOutCards->type == GZ && m_toOutCard->m_cards[0].cardValue > g_curOutCards->value){g_curOutCards->value = m_toOutCard->m_cards[0].cardValue;g_curOutCards->num = 1;g_curOutCards->type = GZ;return true;}} case 2: {if(g_curOutCards->type == DZ && dz()) //是不是对子{if(tmp < m_toOutCard->m_cards[0].cardValue)return true; }if(sw())return true;}case 3:{if(g_curOutCards->type == SGBD && sgbd())if(tmp < m_toOutCard->m_cards[0].cardValue)return 1; }case 4:   {if(g_curOutCards->type == SD1 && sd1()){if(tmp < m_toOutCard->m_cards[1].cardValue)return true;  }if(g_curOutCards->type != ZD && zd())return true;  if(g_curOutCards->type == ZD && zd()){if(tmp < m_toOutCard->m_cards[1].cardValue)return true;}}case 5:  {if(g_curOutCards->type == SZ && sz(5))if(tmp < m_toOutCard->m_cards[0].cardValue)return true;if(g_curOutCards->type == SD2 && sd2())if(tmp < m_toOutCard->m_cards[2].cardValue)return true;} case 6: {if(g_curOutCards->type == SZ && sz(6))if(tmp < m_toOutCard->m_cards[0].cardValue)return true;if(g_curOutCards->type == LD3 && ld3())if(tmp < m_toOutCard->m_cards[5].cardValue)return true;if(g_curOutCards->type == SD2G && sd2g())if(tmp < m_toOutCard->m_cards[3].cardValue)return true;if(g_curOutCards->type == FJBD && fjbd())if(tmp < m_toOutCard->m_cards[4].cardValue)return true;} case 7:   {if(g_curOutCards->type == SZ && sz(7))if(tmp < m_toOutCard->m_cards[0].cardValue)return true;} case 8:  {if(g_curOutCards->type == SZ && sz(8))if(tmp < m_toOutCard->m_cards[0].cardValue)return true;if(g_curOutCards->type == FJD2G && fjd2g())if(tmp < m_toOutCard->m_cards[2].cardValue)return true;if(g_curOutCards->type == LD4 && ld4())if(tmp < m_toOutCard->m_cards[7].cardValue)return true;if(g_curOutCards->type == SD2G && sd2d())return true;}case 9:   {if(g_curOutCards->type == SZ && sz(9))if(tmp < m_toOutCard->m_cards[0].cardValue)return true;if(g_curOutCards->type == SFJBD && sfjbd())if(tmp < m_toOutCard->m_cards[8].cardValue)return true;} case 10:return sz(10) || fjd2d() || ld5(); case 11:return sz(11); case 12:return sz(12) || ld6() || sfjdsg();case 13:return sz(13);case 14:return ld7();case 15:return sfjdsd();default: return false; }}else{switch(m_clickedNum){case 0:  return false ; case 1:{g_curOutCards->value = m_toOutCard->m_cards[0].cardValue;g_curOutCards->num = 1;g_curOutCards->type = GZ;}return true; case 2:    return dz() || sw(); case 3:    return sgbd(); case 4:  return sd1() || zd(); case 5:   return sz(5) || sd2(); case 6: return sz(6) || ld3() || sd2g() || fjbd();case 7:    return sz(7);case 8:    return sz(8) || fjd2g() || ld4() || sd2d();case 9:  return sz(9) || sfjbd(); case 10: return sz(10) || fjd2d() || ld5(); case 11: return sz(11); case 12: return sz(12) || ld6() || sfjdsg();case 13: return sz(13);case 14: return ld7();case 15: return sfjdsd();default: return false;}}return false;
}//对子
bool DouDizhuPlayerRole::dz()
{if(m_toOutCard->m_cards[0].cardValue == m_toOutCard->m_cards[1].cardValue){g_curOutCards->value = m_toOutCard->m_cards[0].cardValue;g_curOutCards->num = 2;g_curOutCards->type = DZ;return true; }return false ;
}//双王
bool DouDizhuPlayerRole::sw()
{if(m_toOutCard->m_cards[0].cardValue + m_toOutCard->m_cards[1].cardValue == 33)           //记得改成和这个一样的{g_curOutCards->num =2;g_curOutCards->type = SW;return true; }return false ;
}//三个不带
bool DouDizhuPlayerRole::sgbd()
{if(m_toOutCard->m_cards[0].cardValue == m_toOutCard->m_cards[1].cardValue && m_toOutCard->m_cards[1].cardValue == m_toOutCard->m_cards[2].cardValue){g_curOutCards->value = m_toOutCard->m_cards[0].cardValue;g_curOutCards->num =3;g_curOutCards->type = SGBD;return true; }   return false;
}//三带一
bool DouDizhuPlayerRole::sd1()
{int analyse[2] , m = 0 , n = 0 , i , j , k , num = 5 ; for(i = 0 ; i < num ; i++)for(j = i+1 ; j < num ; j++)for(k = j+1 ; k < num ; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){for(m = 0 ; m < num ; m++){if(m !=  i  &&  m !=  j  &&  m !=  k)analyse[n++] = m_toOutCard->m_cards[m].cardValue; }if(analyse[0] != m_toOutCard->m_cards[i].cardValue){g_curOutCards->value = m_toOutCard->m_cards[i].cardValue;g_curOutCards->num = 3;g_curOutCards->type = SD1;return true; }else return false ; }}return false;
}//炸弹
bool DouDizhuPlayerRole::zd()
{if(m_toOutCard->m_cards[0].cardValue == m_toOutCard->m_cards[1].cardValue && m_toOutCard->m_cards[1].cardValue == m_toOutCard->m_cards[2].cardValue && m_toOutCard->m_cards[2].cardValue == m_toOutCard->m_cards[3].cardValue){g_curOutCards->value = m_toOutCard->m_cards[0].cardValue;g_curOutCards->num = 4;g_curOutCards->type = ZD;return true; }elsereturn false;
}//三带二
bool DouDizhuPlayerRole::sd2()
{int analyse[2] , m = 0 , n = 0 , i , j , k , num = 5 ; for(i = 0 ; i < num ; i++)for(j = i+1 ; j < num ; j++)for(k = j+1 ; k < num ; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){for(m = 0 ; m < num ; m++){if(m !=  i  &&  m !=  j  &&  m !=  k)analyse[n++] = m_toOutCard->m_cards[m].cardValue; }if(analyse[0] == analyse[1]){g_curOutCards->value = m_toOutCard->m_cards[i].cardValue;g_curOutCards->num =4;g_curOutCards->type = SD2;return true; }else return false; }}return false;
}//顺子  n 代表牌数
bool DouDizhuPlayerRole::sz(int n)
{int i ; for(i = 0 ; i < n-1 ; i++){if(m_toOutCard->m_cards[i].cardValue == PokerDouDiZhu::Value2|| m_toOutCard->m_cards[i + 1].cardValue == PokerDouDiZhu::Value2)return false; 不能有2if(m_toOutCard->m_cards[i].cardValue != m_toOutCard->m_cards[i + 1].cardValue + 1)return false; }g_curOutCards->value = m_toOutCard->m_cards[0].cardValue;g_curOutCards->min = m_toOutCard->m_cards[n -1].cardValue;g_curOutCards->num = n;g_curOutCards->type = SZ;return true;
}//连对3  (三连对)
bool DouDizhuPlayerRole::ld3()
{int min = m_toOutCard->MinCard(); //不能为KA2 (13 14 15)if(min == 13)return false; if(m_toOutCard->CountCard(min) == 2 && m_toOutCard->CountCard(min + 1) == 2 && m_toOutCard->CountCard(min + 2) == 2){g_curOutCards->value = min;g_curOutCards->num = 6;g_curOutCards->type = LD3;return true; }return false;
}//四带二个
bool DouDizhuPlayerRole::sd2g()
{int analyse[2], m = 0, n = 0, i, j, k, p; for(i = 0; i < 6; i++)for(j = i+1; j < 6; j++)for(k = j+1; k < 6; k++)for(p = k+1; p < 6; p++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue && m_toOutCard->m_cards[k].cardValue == m_toOutCard->m_cards[p].cardValue){for(n = 0, m = 0; m < 6; m++){if(m !=  i && m != j && m != k && m != p)analyse[n++] = m_toOutCard->m_cards[m].cardValue;}if(analyse[0] != analyse[1]){g_curOutCards->value = m_toOutCard->m_cards[i].cardValue;g_curOutCards->num =6;g_curOutCards->type = SD2G;return true; }return false; }}return false;
}//飞机不带
bool DouDizhuPlayerRole::fjbd()
{int analyse[3], m = 0, n = 0, i, j, k, num = 6;for(i = 0; i < num ; i++)for(j = i + 1; j < num; j++)for(k = j + 1; k < num; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){for(n = 0, m = 0; m < num; m++){if(m != i && m != j && m != k)analyse[n++] = m_toOutCard->m_cards[m].cardValue;}if(analyse[0] == analyse[1] && analyse[1] == analyse[2])//判断另外三个是否相等{if(abs(m_toOutCard->m_cards[i].cardValue - analyse[0]) !=  1)return false;   //当两个三个不是连着的时if(((m_toOutCard->m_cards[i].cardValue > analyse[0]) ? m_toOutCard->m_cards[i].cardValue : analyse[0]) == PokerDouDiZhu::Value2)return false;   //最大不能为2g_curOutCards->value = m_toOutCard->m_cards[i].cardValue < analyse[0] ? m_toOutCard->m_cards[i].cardValue : analyse[0];g_curOutCards->num =6;g_curOutCards->type = FJBD;return true; }return false; }}return false;
}
//飞机带二个
bool DouDizhuPlayerRole::fjd2g()
{int analyse[2], m = 0, n = 0, i, j, k, t[2][3] = {0}, num = 8; for(i = 0; i < num; i++){for(j = i+1; j < num; j++){for(k = j+1; k < num; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){t[n][0] = i; t[n][1] = j; t[n++][2] = k; }if(n == 2){if(abs(m_toOutCard->m_cards[t[0][0]].cardValue - m_toOutCard->m_cards[t[1][0]].cardValue) != 1)return false;     //当两个三个不是连着的时for(n = 0, m = 0; m < num; m++){if(m != t[0][0] && m != t[0][1] && m != t[0][2] && m != t[1][0] && m != t[1][1] && m != t[1][2])analyse[n++] = m_toOutCard->m_cards[m].cardValue;}if(analyse[0] != analyse[1]){if((m_toOutCard->m_cards[t[0][0]].cardValue < m_toOutCard->m_cards[t[1][0]].cardValue ? m_toOutCard->m_cards[t[0][0]].cardValue : m_toOutCard->m_cards[t[1][0]].cardValue) == 14)return false;     //最大不能为2g_curOutCards->value = m_toOutCard->m_cards[t[0][0]].cardValue < m_toOutCard->m_cards[t[1][0]].cardValue ? m_toOutCard->m_cards[t[0][0]].cardValue : m_toOutCard->m_cards[t[1][0]].cardValue;g_curOutCards->num = 8;g_curOutCards->type = FJD2G;return true; }return false; }}}}return false;
}//4连对
bool DouDizhuPlayerRole::ld4()
{int min = m_toOutCard->MinCard();if(min == 12)return false;  //最大不能为2if(m_toOutCard->CountCard(min) == 2 && m_toOutCard->CountCard(min+1) == 2 && m_toOutCard->CountCard(min + 2) == 2  &&  m_toOutCard->CountCard(min + 3) == 2){g_curOutCards->value = min;g_curOutCards->num = 8;g_curOutCards->type = LD4;return true;}return false;
}//四带两对
bool DouDizhuPlayerRole::sd2d()
{int analyse[4], m = 0, n = 0, i, j, k, p; for(i = 0; i < 8; i++)for(j = i+1; j < 8; j++)for(k = j+1; k < 8; k++)for(p = k+1; p < 8; p++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue && m_toOutCard->m_cards[k].cardValue == m_toOutCard->m_cards[p].cardValue){for(n = 0, m = 0; m < 8; m++){if(m != i && m != j && m != k && m != p)analyse[n++] = m_toOutCard->m_cards[m].cardValue;}if(ld(analyse))  {g_curOutCards->value = m_toOutCard->m_cards[i].cardValue;g_curOutCards->num = 8;g_curOutCards->type = SD2D;return true;}return false;}}return false;
}//是不是二对 , 要求不一样
bool DouDizhuPlayerRole::ld(int temp[])
{int i, j, m, n = 0, analyse[2], num = 4;for (i = 0; i < num; i++)for (j = i+1 ; j < num ; j++){if(temp[i] == temp[j])for(m = 0 ; m < num ; m++){if(m != i && m != j)analyse[n++] = temp[m];}if(analyse[0] == analyse[1] && analyse[0] != temp[i]){return true;}}return false;
}//三飞机带三个
bool DouDizhuPlayerRole::sfjdsg()
{int analyse[3], m = 0, n = 0, i, j, k, t[3][3] = {0}, num = 12; for(i = 0; i < num ; i++)for(j = i+1; j < num; j++)for(k = j+1; k < num; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){t[n][0]  =  i; t[n][1]  =  j; t[n++][2] = k; }if(n == 3){for(n = 0, m = 0; m < num; m++){if(m != t[0][0] && m != t[0][1] && m != t[0][2] && m != t[1][0] && m != t[1][1] && m != t[1][2]&& m != t[2][0] && m != t[2][1] && m != t[2][2])analyse[n++] = m_toOutCard->m_cards[m].cardValue ; }if(analyse[0] != analyse[1] && analyse[0] != analyse[2] && analyse[2] != analyse[1]){analyse[0] = m_toOutCard->m_cards[t[0][0]].cardValue; analyse[1] = m_toOutCard->m_cards[t[1][0]].cardValue; analyse[2] = m_toOutCard->m_cards[t[2][0]].cardValue; if((analyse[0] + analyse[1] + analyse[2]) != (MinCard(analyse, 3) + 1) * 3) return false; //三个是不是连着的if(MinCard(analyse, 3) == 13) return false; //最大不能为2g_curOutCards->value = MinCard(analyse, 3);g_curOutCards->num =12;g_curOutCards->type = SFJDSG;return  true; }return false ; }}return false;
}//三飞机不带
bool DouDizhuPlayerRole::sfjbd()
{int min = m_toOutCard->MinCard(); if(min == 13) return false; //最大不能为2if(    m_toOutCard->CountCard(min) == 3 && m_toOutCard->CountCard(min + 1) == 3 && m_toOutCard->CountCard(min + 2) == 3){g_curOutCards->value = min;g_curOutCards->num = 9;g_curOutCards->type = SFJBD;return true; }return false;
}//飞机带两对
bool DouDizhuPlayerRole::fjd2d()
{int analyse[4], m = 0, n = 0, i, j, k, t[3][3] = {0}, num = 10; for(i = 0; i < num; i++)for(j = i+1; j < num; j++)for(k = j+1; k < num; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){t[n][0] = i; t[n][1] = j; t[n++][2] = k; }if(n == 2){if(abs(m_toOutCard->m_cards[t[0][0]].cardValue - m_toOutCard->m_cards[t[1][0]].cardValue) != 1) return false; //当两个三个不是连着的时for(n = 0, m = 0; m < num; m++){if(m != t[0][0] && m != t[0][1] && m != t[0][2] && m != t[1][0] && m != t[1][1] && m != t[1][2])analyse[n++] = m_toOutCard->m_cards[m].cardValue; }if(ld(analyse)){if(((m_toOutCard->m_cards[t[0][0]].cardValue < m_toOutCard->m_cards[t[1][0]].cardValue) ? m_toOutCard->m_cards[t[0][0]].cardValue : m_toOutCard->m_cards[t[1][0]].cardValue) == 14) return false; //最大不能为2g_curOutCards->value = m_toOutCard->m_cards[t[0][0]].cardValue < m_toOutCard->m_cards[t[1][0]].cardValue ? m_toOutCard->m_cards[t[0][0]].cardValue : m_toOutCard->m_cards[t[1][0]].cardValue;g_curOutCards->num =10;g_curOutCards->type = FJD2D;return true; }return false; }}return false;
}//五连对
bool DouDizhuPlayerRole::ld5()
{int min = m_toOutCard->MinCard(); if(min == 11) return false; //最大不能为2if(    m_toOutCard->CountCard(min) == 2      && m_toOutCard->CountCard(min + 1) == 2 && m_toOutCard->CountCard(min + 2) == 2  && m_toOutCard->CountCard(min + 3) == 2 && m_toOutCard->CountCard(min + 4) == 2){g_curOutCards->value = min;g_curOutCards->num =10;g_curOutCards->type = LD5;return true; }return false;
}
//六连对
bool DouDizhuPlayerRole::ld6()
{int min = m_toOutCard->MinCard(); if(min == 10)return false; //最大不能为2if(    m_toOutCard->CountCard(min) == 2     && m_toOutCard->CountCard(min + 1) == 2&& m_toOutCard->CountCard(min + 2) == 2 && m_toOutCard->CountCard(min + 3) == 2&& m_toOutCard->CountCard(min + 4) == 2 && m_toOutCard->CountCard(min + 5) == 2){g_curOutCards->value = min;g_curOutCards->num =12;g_curOutCards->type = LD6;return true;}return false;
}//七连对
bool DouDizhuPlayerRole::ld7()
{int min = m_toOutCard->MinCard();if(min == 9)return false;   //最大不能为2if(    m_toOutCard->CountCard(min) == 2     && m_toOutCard->CountCard(min + 1) == 2&& m_toOutCard->CountCard(min + 2) == 2 && m_toOutCard->CountCard(min + 3) == 2&& m_toOutCard->CountCard(min + 4) == 2 && m_toOutCard->CountCard(min + 5) == 2&& m_toOutCard->CountCard(min + 6) == 2){g_curOutCards->value = min;g_curOutCards->num =14;g_curOutCards->type = LD7;return true;}return false;
}//三飞机带三对
bool DouDizhuPlayerRole::sfjdsd()
{int analyse[6], m = 0, n = 0, i, j, k, t[3][3] = {0}, num = 15;for(i = 0; i < num; i++)for(j = i+1; j < num; j++)for(k = j+1; k < num; k++){if(m_toOutCard->m_cards[i].cardValue == m_toOutCard->m_cards[j].cardValue && m_toOutCard->m_cards[j].cardValue == m_toOutCard->m_cards[k].cardValue){t[n][0] = i;t[n][1] = j;t[n++][2] = k;}if(n == 3){for(n = 0, m = 0; m < num; m++){if(m != t[0][0] && m != t[0][1] && m != t[0][2]&& m != t[1][0] && m != t[1][1] && m != t[1][2]&& m != t[2][0] && m != t[2][1] && m != t[2][2])analyse[n++] = m_toOutCard->m_cards[m].cardValue;}if(sd(analyse)){analyse[0] = m_toOutCard->m_cards[t[0][0]].cardValue;analyse[1] = m_toOutCard->m_cards[t[1][0]].cardValue;analyse[2] = m_toOutCard->m_cards[t[2][0]].cardValue;if((analyse[0] + analyse[1] + analyse[2]) != (MinCard(analyse, 3) + 1) * 3)return false;    //三个是不是连着的if(MinCard(analyse, 3) == 13)return false;  //最大不能为2g_curOutCards->value = MinCard(analyse, 3);g_curOutCards->num =15;g_curOutCards->type = SFJDSD;return true; }return false;}}return false;
}//是不是三对, 要求不一样
bool DouDizhuPlayerRole::sd(int temp[])
{int i, j, m = 0, n = 0, num = 6, t[3];for (i = 0; i < num; i++)for (j = i+1 ; j < num ; j++){if(temp[i] == temp[j])t[m++] = j;if((m > 1) && (temp[t[m - 2]] == temp[t[m - 1]]))  //除出三个一样的return false;}if(m == 3)return true;return false;
}

蜘蛛纸牌代码:

//========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerHongXin.cpp
//  @Brief:     SpiderGame
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#ifndef _SpideGame_
#define _SpideGame_#include "Math/MathLib.h"
#include "General/Vector.h"
#include "Render/Texture.h"
#include "PokerCard.h"
#include "Rpg/MiniGame.h"typedef Vector<int> IntVector;struct   ScreenStruct
{char LbFrom;      //牌从该列移出char LbTo;          //移出的牌移到该列char MoveCardNum;  //拖动牌数int  nBackNum;     //主列牌的覆盖牌数
};enum SpiderGameStatus
{Waiting,Dealing,   //发牌Completing,//收牌Tiping,Playing,Resulting,
};#define DOWNPOS (BoardRect2D.y + BoardRect2D.height - 30)        //分数区域底部位置
#define CARDDIS_BACK  17 //8    //未翻牌重叠间距高度
#define CARDDIS_FRONT 20        //翻开牌重叠间距高度
#define CardWidth  71
#define CardHeight 96class SoundChannel;//顶部的一列牌
class Every
{
public:int  CardAt(int index);void PushCard(int card);void DeleteCard(int index);//某一个牌是否上一张牌小bool IsLessThenTop(int index);//计算最大可拖动牌数int  CalMaxMoveNum();RectF CardRect(int index);int  m_index;IntVector m_cards;          //所有牌int  m_backNum;             //未翻牌数int  m_maxMoveNum;          //最大可拖动牌数
};class MiniGameSpiderPoker:public MiniGame
{
public:MiniGameSpiderPoker();virtual~MiniGameSpiderPoker();virtual bool Start();virtual bool Stop();virtual bool Render();virtual bool Update();virtual bool Free();//三种类型结构virtual MiniPlayer*  CreatePlayer();virtual MiniPlayer*  CreateRobot ();virtual MiniPlayer*  CreateRole  ();//发牌过程函数bool OnDeal();//根据给定牌的列和链表,计算出可以拖动的矩形大小void GetRecvRect(Every*every,RectF &rect);//判断拖动牌的个数int GetMoveCardNum(Every*every,const vec2& point);//计算拖动牌左上角坐标和鼠标按下点坐标的横纵距离void GetTwoPointJL(Every*every,const vec2& point);//判断一列牌中是否可以收牌void IsCardAccess(Every*ever);//提示功能bool OnTip();void OnUndo();void OnGameRead();void OnGameSave();//判断是否胜利bool IsGameEnd();//增加一个撤消状态void AddScreen(char CardList,char CardListOther,char MoveCardNum,int BackNum);void DebugCheck();public:SpiderGameStatus   m_gameStatus;float   m_stateAccumeTime;#define MaxEveryNum 10int EveryNum;//十列牌Every m_cardEverys[MaxEveryNum];IntVector  m_cardsDealLeft;         //剩余牌链表IntVector  m_cardsComplete;          //已经完成的牌int m_dealLeft;                     //剩余发牌轮数Every*  m_curDealEvery;vec2 m_curDealPoint;         //发牌或收牌的起点和终点vec2 m_curDealPointEnd;int  m_curDealCardVal;Every*  m_curCompleteEvery;vec2 m_curCompletePoint;   //发牌或收牌的起点和终点vec2 m_curCompletePointEnd;int  m_curCompleteCardNum;int  m_curCompleteCardVal;int m_moveComplete;         //已完成的列数int m_Score;                //总分数int m_moveNum;             //拖动次数bool m_tipButton;bool m_dealButton;//撤消功能ScreenStruct * m_undos;              int m_curUndo;              //当前屏幕号int m_MaxScreen;         //记录的最大屏幕数float EveryDis;               //列间距bool m_openPoker;private:vec2I m_moveOffset;           //鼠标点和拖动牌左上角的偏移int   m_curMoveNum;          //跟随鼠标拖动牌个数Every*   m_curMoveEvery; //拖动的列IntVector  m_movingCards; //拖动的牌//存储牌拖动信息IntVector  m_tipMoves;       //依次存储当前列、对比列、当前列与对比列可以拖动牌的个数int m_curTip;              //当前可拖动牌信息个数,值为1到一拖动牌信息个数最大值TexturePtr m_texCards[CardNum];TexturePtr m_texCardBack;TexturePtr m_texCardSlot;TexturePtr m_texBack;SoundChannel*  m_sound;
};extern MiniGameSpiderPoker* G_SpiderGame;#endif //========================================================
//  @Date:     2016.05
//  @File:     SourceDemoClient/Poker/PokerHongXin.cpp
//  @Brief:     SpiderGame
//  @Author:     LouLei
//  @Email:  twopointfive@163.com
//  @Copyright (Crapell) - All Rights Reserved
//========================================================#include "General/Pch.h"
#include "General/Timer.h"
#include "General/Window.h"
#include "MiniGameSpiderPoker.h"
#include "Input/InputMgr.h"
#include "Render/RendDriver.h"
#include "Render/Font.h"
#include "Sound/ChannelSound.h"
#include "General/Vector.cpp"
#include "General/Pce.h"
#include "Render/MC_MovieClip.h"
#include "Render/Camera.h"
#include "Gui/GuiMgr.h"
#include "Gui/RpgGuis.h"
#include "Render/Shader.h"template class Vector<int>;
MiniGameSpiderPoker* G_SpiderGame = NULL;
MiniGameSpiderPoker::MiniGameSpiderPoker()
{G_SpiderGame = this;m_MaxScreen   =  50;m_undos  =  new ScreenStruct[m_MaxScreen];m_sound = new SoundChannel;
}
MiniGameSpiderPoker::~MiniGameSpiderPoker()
{SafeDeleteArray(m_undos);SafeDelete(m_sound);G_SpiderGame = NULL;
}bool MiniGameSpiderPoker::Start()
{if(!MiniGame::Start())return false;m_openPoker = false;const char* cardTexName[] ={"data/minigame/poker/mei2.png","data/minigame/poker/mei3.png",...};for(int i = 0; i < CardNum; i++){G_TextureMgr->AddTexture(m_texCards[i], cardTexName[i]);}G_TextureMgr->AddTexture(m_texCardBack, "data/minigame/poker/cardback01.png");G_TextureMgr->AddTexture(m_texCardSlot, "data/minigame/poker/cardslot.png");G_TextureMgr->AddTexture(m_texBack, "data/minigame/poker/back.png");//if(m_movieScene == NULL){LoadConfig loader(LoadConfig::GenDonotReShrinkBound, true, true);m_movieScene = new RendSys::MovieClip;m_movieScene->LoadFromFile("data/minigame/poker/board.movie", &loader);Frame frame;frame.SetPos(m_startPos);m_movieScene->SetProgramFrame(&frame);m_movieScene->Advance();}if(m_movieScene->IsLoadComplete() == false){m_gameState = MS_End;return false;}SetBoardRect(RectF(100, 100, G_Window->m_iWidth-200, G_Window->m_iHeight-200),RectF(m_startPos.x - 50, m_startPos.z - 33, 100, 66),m_startPos.y + 10.1f);EveryNum        =  10;m_moveNum       =  0;m_Score           =  0;m_moveComplete    =  0;m_curUndo     =  0;m_undos[0].LbFrom =  0;m_undos[0].LbTo   =  0;m_undos[0].MoveCardNum    =  0;m_curMoveEvery        =  0;m_curTip =   0;EveryDis = (BoardRect2D.width - CardWidth * EveryNum) / 11;      //利用总距离减去牌的总宽度//先清除所有链表中数据for(int i = 0; i < EveryNum; i++){m_cardEverys[i].m_cards.clear();m_cardEverys[i].m_maxMoveNum  =  0;m_cardEverys[i].m_index   =  i;}m_cardsDealLeft.clear();m_movingCards.clear();104张牌数组int level = Rand()%2+1;//int level = 1;if(level == 1){//单色for(int i = 0; i < 8; i++){for(int j = 1; j <= 13; j++){m_cardsDealLeft.push_back(j);}}}else if(level == 2){//双色for(int i = 0; i < 4; i++){for(int j = 1; j <= 26; j++){m_cardsDealLeft.push_back(j);}}}//else if (level ==3)//{// //4色//  for(int i=0;i<2;i++)//    {//     for(int j=1;j<=52;j++)//     {//         m_cardsDealLeft.push_back(j);//     }// }//}刷牌: 随机i-1中的任意一个数与i交换//for (int i = 2; i < 104; i++)//{//   int ran = Rand()%i;//  char temp = m_cardsDealLeft[ran];//    m_cardsDealLeft[ran] = m_cardsDealLeft[i];//   m_cardsDealLeft[i] = temp;//}//设置10个列的牌while(true){if(m_cardsDealLeft.size() == 60)break;for(int i = 0; i < EveryNum; i++){if(m_cardsDealLeft.size() == 60)break;m_cardEverys[i].m_cards.push_back(m_cardsDealLeft.back());m_cardsDealLeft.pop_back();}}DebugCheck();//给每列未翻的牌个数赋值for(int i = 0; i < EveryNum; i++){if (m_cardEverys[i].m_cards.size()>0){m_cardEverys[i].m_backNum = m_cardEverys[i].m_cards.size()-1;}else{m_cardEverys[i].m_backNum = 0;}}//给剩余发牌次数和已完成列牌次数赋值m_dealLeft        =  6;m_moveComplete    =  0;//分数和拖动数重新计算m_Score   =  500;m_moveNum =    0;OnDeal();//进入miniplaygui,(选人、选关卡都已在房间里进行完毕)。if(GetStyle()) G_GuiMgr->PushGui(GetStyle()->playGUI.c_str(),GL_DIALOG);//for(int i = 0; i < m_allPlayerNum; i++){if(m_miniPlayer[i])m_miniPlayer[i]->Start();}//设置摄像机CameraCtrlerTarget* ctrler = new CameraCtrlerTarget;ctrler->SetDistToTar(60);ctrler->SetTarPos(m_startPos);G_Camera->PushCtrler(ctrler);G_Camera->SetEuler(0, -60, 0);//片头摄像机PushIntroCamera();return true;
}MiniPlayer* MiniGameSpiderPoker::CreatePlayer()
{return NULL;//new ChessPlayer;
}MiniPlayer* MiniGameSpiderPoker::CreateRobot()
{return NULL;// new ChessPlayerRobot;
}MiniPlayer* MiniGameSpiderPoker::CreateRole()
{//m_myRolePlayer = NULL;//new ChessPlayerRole;//return m_myRolePlayer;return NULL;
}bool MiniGameSpiderPoker::Stop()
{{if(m_myPlayer && m_myPlayer->m_liveNum > 0){G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(true);}else{G_GuiMgr->GetGui<Rpg_ResultDialog>()->ShowResult(false);}G_GuiMgr->PushGui("Rpg_ResultDialog", GL_DIALOGBOTTOM);}return MiniGame::Stop();
}
bool MiniGameSpiderPoker::Update()
{SetBoardRect(RectF(100, 100, G_Window->m_iWidth-200, G_Window->m_iHeight-200),RectF(m_startPos.x - 50, m_startPos.z - 33, 100, 66),m_startPos.y + 10.1f);EveryDis = (BoardRect2D.width - CardWidth * 10) / 11;     //利用总距离减去牌的总宽度if(m_3dMode){m_movieScene->Advance();}if(G_Keyboard->IsKeyUping(DIK_Z) && G_Keyboard->IsKeyPressed(DIK_LCONTROL)){OnUndo();}if(m_gameStatus == Playing){vec2 pos = this->GetMousePos();//if (G_Mouse->IsButtonPressed(MOUSE_LEFT)){RectF rect;//提示rect.x   = BoardRect2D.x + BoardRect2D.width / 2 - 100;rect.y    = DOWNPOS - 100;rect.width  = 200;rect.height = 100;if(rect.IsPointIn(pos)){m_tipButton = true;}else{m_tipButton = false;}//发牌rect.x   = BoardRect2D.x + BoardRect2D.width - EveryDis - (m_dealLeft - 1) * CARDDIS_BACK - CardWidth;rect.y    = DOWNPOS - CardHeight;rect.width  = CardWidth;rect.height = CardHeight;if(rect.IsPointIn(pos)){m_dealButton = true;}else{m_dealButton = false;}}if(G_Mouse->IsButtonDowning(MOUSE_LEFT)){//拖动牌RectF rect;for(int m = 0; m < EveryNum; m++){//得到需要跟随牌的个数m_curMoveNum    =  GetMoveCardNum(&m_cardEverys[m], pos);//按下点在矩形区域内,并且当前列有元素if(m_curMoveNum > 0){m_curMoveEvery = &m_cardEverys[m];//计算鼠标点和拖动牌左上角坐标的距离GetTwoPointJL(m_curMoveEvery, pos);int nCount    = m_curMoveEvery->m_cards.size();//删除指定列中被拖动的牌for(int i = 1; i <= m_curMoveNum; i++){m_movingCards.push_back(m_curMoveEvery->m_cards.at(nCount - i));m_curMoveEvery->DeleteCard(nCount - i);}break;}}//提示if(m_tipButton){OnTip();m_gameStatus = Tiping;m_stateAccumeTime = 0;}//发牌if(m_dealButton){OnDeal();}}if(G_Mouse->IsButtonUping(MOUSE_LEFT)){if(m_movingCards.size() > 0){RectF rectSave;                  //可以接收列的范围RectF rectCard;                   //列牌可拖动的矩形区域bool bMoveSuccess =    false;      //是否在当前列中加了临时数组的牌for(int i = 0; i < EveryNum; i++){Every* it = &m_cardEverys[i];//计算可接收拖动牌的范围GetRecvRect(it, rectCard);rectSave.x    =  rectCard.x - EveryDis / 2;rectSave.width    =  rectCard.width  + EveryDis;rectSave.y  =  rectCard.y;rectSave.height  =  rectCard.height + CardHeight;int nCount        =  it->m_cards.size();int nCount1       =  m_movingCards.size();if (rectSave.IsPointIn(pos)){if((nCount    ==    0 || m_curMoveEvery == it)){bMoveSuccess  =  true;}else{int toCard = -1;if(nCount > 0)toCard = it->m_cards.at(nCount - 1);int moveCard = m_movingCards.at(nCount1 - 1);if(    toCard == (moveCard + 1) || toCard == (moveCard + 1 + 13) || toCard == (moveCard + 1 - 13)){bMoveSuccess    =  true;}}}if(bMoveSuccess){//在新列牌中加入拖动过来的牌for(int j = m_movingCards.size(); j > 0; j--){it->PushCard(m_movingCards.at(j - 1));}AddScreen(m_curMoveEvery->m_index, i, m_movingCards.size(), m_curMoveEvery->m_backNum);//移完翻牌if(m_curMoveEvery->m_cards.size() == m_curMoveEvery->m_backNum&& m_curMoveEvery->m_backNum > 0){m_curMoveEvery->m_backNum   -= 1;}m_curMoveEvery->CalMaxMoveNum();//分数和拖动牌次数更新if(it != m_curMoveEvery){m_moveNum++;m_Score   --;}//收牌IsCardAccess(it);break;}}//拖动失败if(bMoveSuccess == false){for(int j = m_movingCards.size(); j > 0; j--)m_curMoveEvery->PushCard(m_movingCards.at(j - 1));}//清空拖动牌m_movingCards.clear();}}}return true;
}bool MiniGameSpiderPoker::Free()
{MiniGame::Free();return true;
}
void MiniGameSpiderPoker::DebugCheck()
{return;for(int c = 1; c <= 26; c++){int num = 0;for(int i = 0; i < 10; i++){for(int j = 0; j < m_cardEverys[i].m_cards.size(); j++){if(m_cardEverys[i].m_cards[j] == c){num++;}}}for(int j = 0; j < m_cardsDealLeft.size(); j++){if(m_cardsDealLeft[j] == c){num++;}}if(num != (8 - m_moveComplete) && num != 0){int a = 0;}}
}int  Value2CardID(int value)
{if(value == 1){return HONGTA;}else if(2 <= value && value <= 13){return HONGT2 + value - 2;}else if(value == 14){return HEITA;}else if(15 <= value && value <= 26){return HEIT2 + value - 15;}return JokerBig;
};bool MiniGameSpiderPoker::Render()
{if(m_3dMode){G_RendDriver->EndUI();if(m_movieScene == NULL|| m_movieScene->IsLoadComplete() == false)return false;m_movieScene->RendClip();G_RendDriver->PushMatrix();G_RendDriver->MultMatrix(mat2Dto3D);if(G_ShaderMgr && G_ShaderMgr->m_curEffect){G_ShaderMgr->m_picked = false;//todo  每个物体单独设置 没必要//G_ShaderMgr->m_doReceiveShadow = m_doReceiveShadow;G_ShaderMgr->MapChangeParm();}}else{G_RendDriver->BeginUI();if(G_ShaderMgr && G_ShaderMgr->m_curEffect){G_ShaderMgr->m_picked = false;//todo  每个物体单独设置 没必要//G_ShaderMgr->m_doReceiveShadow = m_doReceiveShadow;G_ShaderMgr->MapChangeParm();}//背景 G_RendDriver->ShaderColor4f(1, 1, 1, 1);G_RendDriver->SetRenderStateEnable(RS_DEPTH_TEST, false);m_texBack->Bind();G_RendDriver->DrawTextureRect(BoardRect2D);}//10列牌的槽位G_RendDriver->ShaderColor4f(1, 1, 1, 1);m_texCardSlot->Bind(); for(int i = 0; i < EveryNum; i++){if(m_cardEverys[i].m_cards.size()==0){G_RendDriver->DrawTextureRect(m_cardEverys[i].CardRect(0));}}//显示分数和点击数//brush.CreateSolidBrush(RGB(0,255,150));//画矩形if(m_gameStatus == Playing && m_tipButton){G_RendDriver->ShaderColor4f(0, 1, 0, 1);}else{G_RendDriver->ShaderColor4f(1, 1, 1, 1);}G_RendDriver->DrawTextureRect(RectF(BoardRect2D.x+BoardRect2D.width / 2 - 100,DOWNPOS - 100,200, 100));G_RendDriver->ShaderColor4f(1, 1, 1, 1);String str;str.format("score: %d", m_Score);G_FontMgr->TextAtPos(vec2(BoardRect2D.x+BoardRect2D.width / 2 - 30, DOWNPOS - 80), str.c_str());   //显示分数str.format("move: %d", m_moveNum);G_FontMgr->TextAtPos(vec2(BoardRect2D.x+BoardRect2D.width / 2 - 30, DOWNPOS - 60), str.c_str());  //显示操作数//显示所有牌{//绘制10列牌for(int m = 0; m < EveryNum; m++){//未翻的牌if (m_openPoker)//作弊显示翻开{G_RendDriver->ShaderColor4f(0.3f, 1, 0.5f, 1); } else{G_RendDriver->ShaderColor4f(1, 1, 1, 1);}int backNum = m_cardEverys[m].m_backNum;m_texCardBack->Bind();for(int i = 0; i < backNum; i++){if (m_openPoker)//作弊显示翻开{m_texCards[Value2CardID(m_cardEverys[m].m_cards[i])]->Bind();}G_RendDriver->DrawTextureRect(m_cardEverys[m].CardRect(i));}//翻开的牌G_RendDriver->ShaderColor4f(1, 1, 1, 1);int frontNum = m_cardEverys[m].m_cards.size() - backNum;for(int i = 0; i < frontNum; i++){m_texCards[Value2CardID(m_cardEverys[m].m_cards[backNum + i])]->Bind();G_RendDriver->DrawTextureRect(m_cardEverys[m].CardRect(i+backNum));}}//下面可发牌m_texCardBack->Bind();for(int i = 0; i < m_dealLeft; i++){if(i == m_dealLeft - 1 && m_gameStatus == Playing && m_dealButton){G_RendDriver->ShaderColor4f(0, 1, 0, 1);}else{G_RendDriver->ShaderColor4f(1, 1, 1, 1);}int x = BoardRect2D.x + BoardRect2D.width - EveryDis - i * CARDDIS_BACK - CardWidth;int y = DOWNPOS - CardHeight;G_RendDriver->DrawTextureRect(RectF(x, y, CardWidth, CardHeight));}G_RendDriver->ShaderColor4f(1, 1, 1, 1);//左下已完成列for(int i = 0; i < m_moveComplete; i++){if(m_cardsComplete.at(i) == 1)m_texCards[HONGTK]->Bind();elsem_texCards[HEITK]->Bind();int x    =  BoardRect2D.x + EveryDis + i * CARDDIS_BACK;int y =  DOWNPOS - CardHeight;G_RendDriver->DrawTextureRect(RectF(x, y, CardWidth, CardHeight));}int moveNum  =  m_movingCards.size();vec2 point = this->GetMousePos();//拖动的牌for(int i = 0; i < moveNum; i++){m_texCards[Value2CardID(m_movingCards[moveNum - i - 1])]->Bind();G_RendDriver->DrawTextureRect(RectF(point.x - m_moveOffset.x, point.y + i * CARDDIS_FRONT - m_moveOffset.y, CardWidth, CardHeight));}}m_stateAccumeTime += G_Timer->GetStepTimeLimited();if(m_gameStatus == Tiping){if(m_stateAccumeTime > 1){m_gameStatus = Playing;m_stateAccumeTime = 0;}G_RendDriver->ShaderColor4f(0, 1, 0, 1);if(m_tipMoves.size() != 0){//取得需特殊显示牌信息Every* List1  =  &m_cardEverys[m_tipMoves.at(3 * m_curTip)];         //得到当前列数Every* List2    =  &m_cardEverys[m_tipMoves.at(3 * m_curTip + 1)];        //得到对比列数int moveNum =  m_tipMoves.at(3 * m_curTip + 2);int count1 =  List1->m_cards.size();                           //计算当前列元素个数//特殊显示主列牌for(int i = 0; i <= moveNum - 1; i++){int val = List1->CardAt(count1 - moveNum + i);m_texCards[Value2CardID(val)]->Bind();G_RendDriver->DrawTextureRect(List1->CardRect(count1 - moveNum + i));}//特殊显示对比列牌int count2  =  List2->m_cards.size();                       //计算对比列元素个数if (count2>0){int val = List2->CardAt(count2 - 1);m_texCards[Value2CardID(val)]->Bind();}else{m_texCardSlot->Bind();}G_RendDriver->DrawTextureRect(List2->CardRect(count2 - 1));}G_RendDriver->ShaderColor4f(1, 1, 1, 1);}if(m_gameStatus == Dealing){if(m_curDealEvery->m_index >= EveryNum-1){m_gameStatus = Playing;m_stateAccumeTime = 0;DebugCheck();//发牌次数减少一m_dealLeft--;//判断完整列for(int i = 0; i < EveryNum; i++){IsCardAccess(&m_cardEverys[i]);}//清除撤销m_curUndo  =  0;}else{vec2 oldPoint = m_curDealPoint;vec2 dif = m_curDealPointEnd - m_curDealPoint;dif.Normalize();m_curDealPoint += dif * (G_Timer->GetStepTimeLimited() * 2800);if((m_curDealPointEnd - m_curDealPoint).Dot(dif) <= 0){m_curDealPoint.x = BoardRect2D.width - EveryDis - (m_dealLeft - 1) * CARDDIS_BACK - CardWidth;m_curDealPoint.y = DOWNPOS - CardHeight;m_curDealPointEnd = m_curDealEvery->CardRect(m_curDealEvery->m_cards.size()).GetPos();//加入发的牌m_curDealEvery->PushCard(m_cardsDealLeft.back());m_cardsDealLeft.pop_back();m_sound->PlaySound__("data/sound/poker/deal.wav");m_curDealEvery++;if(m_cardsDealLeft.size() > 0){m_curDealCardVal = m_cardsDealLeft.back();}else{m_gameStatus = Playing;m_stateAccumeTime = 0;m_dealLeft = 0;//判断完整列for(int i = 0; i < EveryNum; i++){IsCardAccess(&m_cardEverys[i]);}//清除撤销m_curUndo =  0;}}m_texCards[Value2CardID(m_curDealCardVal)]->Bind();G_RendDriver->DrawTextureRect(RectF(m_curDealPoint.x, m_curDealPoint.y, CardWidth, CardHeight));}}if(m_gameStatus == Completing){vec2 oldPoint = m_curCompletePoint;vec2 dif = m_curCompletePointEnd - m_curCompletePoint;dif.Normalize();m_curCompletePoint += dif * (G_Timer->GetStepTimeLimited() * 2800);if((m_curCompletePointEnd - m_curCompletePoint).Dot(dif) <= 0){m_curCompleteCardNum++;//收完if(m_curCompleteCardNum >= 13){m_moveComplete    +=    1;//更新已完成牌链表if(m_curCompleteCardVal <= 13)m_cardsComplete.push_back(1);elsem_cardsComplete.push_back(-1);m_curCompleteEvery->m_maxMoveNum    -= 13;m_curUndo    =  0;m_gameStatus = Playing;m_stateAccumeTime = 0;//收完翻牌if(m_curCompleteEvery->m_cards.size() == m_curCompleteEvery->m_backNum&& m_curCompleteEvery->m_backNum > 0){m_curCompleteEvery->m_backNum--;m_curCompleteEvery->m_maxMoveNum = 1;}}else{m_sound->PlaySound__("data/sound/poker/deal.wav");m_curCompleteCardVal = m_curCompleteEvery->m_cards.back();//删除最后一张牌m_curCompleteEvery->m_cards.pop_back();//计算发牌的起点和终点位置int nCount    =  m_curCompleteEvery->m_cards.size();int nBack =  m_curCompleteEvery->m_backNum;m_curCompletePoint =  m_curCompleteEvery->CardRect(m_curCompleteEvery->m_cards.size()).GetPos();}}m_texCards[Value2CardID(m_curCompleteCardVal)]->Bind();G_RendDriver->DrawTextureRect(RectF(m_curCompletePoint.x, m_curCompletePoint.y, CardWidth, CardHeight));//绘制已经收好的if(m_curCompleteCardNum > 0){m_texCards[Value2CardID(m_curCompleteCardVal - 1)]->Bind();G_RendDriver->DrawTextureRect(RectF(m_curCompletePointEnd.x, m_curCompletePointEnd.y, CardWidth, CardHeight));}}if(m_3dMode){G_RendDriver->PopMatrix();}return true;
}//发牌
bool MiniGameSpiderPoker::OnDeal()
{if(m_cardsDealLeft.size() <= 0){return false;}m_gameStatus = Dealing;m_stateAccumeTime = 0;m_curDealEvery = m_cardEverys;//发牌的起点和终点m_curDealPoint.x = BoardRect2D.width - EveryDis - (m_dealLeft - 1) * CARDDIS_BACK - CardWidth;m_curDealPoint.y = DOWNPOS - CardHeight;m_curDealPointEnd = m_curDealEvery->CardRect(m_curDealEvery->m_cards.size()).GetPos();return true;
}//得到每一列牌的可以相应鼠标消息的区域大小
void MiniGameSpiderPoker::GetRecvRect(Every*every, RectF &rect)
{int nCount     =  every->m_cards.size();int maxMove    =  every->m_maxMoveNum;int nBack    =  every->m_backNum;rect  = every->CardRect(every->m_backNum);rect.height    = CardHeight + (maxMove - 1) * CARDDIS_FRONT;
}//判断拖动的牌的个数
int  MiniGameSpiderPoker::GetMoveCardNum(Every*every, const vec2& point)
{int nCount     =  every->m_cards.size();int maxMove    =  every->m_maxMoveNum;int nBack        =  every->m_backNum;if(nCount == 0)return 0;//定义可以移动的矩形最大范围RectF rect;for(int i = 0; i < maxMove; i++){rect =  every->CardRect(nCount - i - 1);if(i == 0)     //如果鼠标左键点下位置在最上面一张牌上{rect.height    = CardHeight;} else{rect.height    = CARDDIS_FRONT;}if(rect.IsPointIn(point))return i + 1;}return 0;
}//计算鼠标点和拖动牌左上角坐标的距离
void MiniGameSpiderPoker::GetTwoPointJL(Every*every, const vec2& point)
{int nCount     =  every->m_cards.size();int maxMove    =  every->m_maxMoveNum;RectF rect;for(int i = 0; i < maxMove; i++){rect = every->CardRect(nCount - maxMove + i);if(maxMove == i){rect.height   = CardHeight;}else{rect.height = CARDDIS_FRONT;}if(rect.IsPointIn(point)){m_moveOffset.x  =  point.x - rect.x;m_moveOffset.y =  point.y - rect.y;return;}}
}bool MiniGameSpiderPoker::OnTip()
{m_tipMoves.clear();//提示第一个//m_curTip   =  0;for(int i = 0; i < EveryNum; i++){int nCount        =  m_cardEverys[i].m_cards.size();int nMoveCard    =  m_cardEverys[i].m_maxMoveNum;if(nCount == 0)continue;int  nCountOther =  0;for(int n = 1; n <= nMoveCard; n++)    //对选定列每张可移动牌进行判断{for(int j = 0; j < EveryNum; j++)        //对选定牌与其他列最后一张牌进行对比{nCountOther = m_cardEverys[j].m_cards.size();if(j == i || nCountOther == 0)continue;//如果可移动牌可以移动,依次加入当前列,对比列,当前列与对比列可以移动牌的个数int ij = m_cardEverys[i].CardAt(nCount - n);int kc = m_cardEverys[j].CardAt(nCountOther - 1);if((ij ==  kc - 1|| ij == kc - 1 - 13|| ij == kc - 1 + 13)&& ij != 13&& ij != 26){//如果提示牌前还有牌if(nCount - n - 1 >= m_cardEverys[i].m_backNum){int ij_ = m_cardEverys[i].CardAt(nCount - n - 1);if(ij_ != kc&& ij_ != kc + 13&& ij_ != kc - 13){m_tipMoves.push_back(i);m_tipMoves.push_back(j);m_tipMoves.push_back(n);}}else{m_tipMoves.push_back(i);m_tipMoves.push_back(j);m_tipMoves.push_back(n);}}}}}//如果保存有可移动信息if(m_tipMoves.size() != 0){m_sound->PlaySound__("data/sound/poker/deal.wav");//更新显示信息数m_curTip += 1;if(m_curTip >= m_tipMoves.size() / 3)m_curTip   =  0;return true;}else{m_sound->PlaySound__("data/sound/poker/cannot.wav");return false;}
}//撤消
void MiniGameSpiderPoker::OnUndo()
{if(m_curUndo == 0)return;else{char Lb    =  m_undos[m_curUndo].LbFrom;char LbTo =  m_undos[m_curUndo].LbTo;char MoveCardNum    =  m_undos[m_curUndo].MoveCardNum;int nBackNum     =  m_undos[m_curUndo].nBackNum;Every* every = &m_cardEverys[Lb];Every* everyTo = &m_cardEverys[LbTo];int nCount  =  everyTo->m_cards.size();for(int i = 0; i < MoveCardNum; i++){//接收列减去移动牌int CurrentMoveCard =  everyTo->m_cards.at(nCount - MoveCardNum);everyTo->DeleteCard(nCount - MoveCardNum);//移出牌的列增加移动牌every->PushCard(CurrentMoveCard);}//重新设置发牌列的未翻牌数every->m_backNum    =  nBackNum;every->m_maxMoveNum   =    every->CalMaxMoveNum();m_curUndo--;}
}//判断某一列牌是否可以收牌
void MiniGameSpiderPoker::IsCardAccess(Every*every)
{int nCount     =  every->m_cards.size();int maxMove    =  every->m_maxMoveNum;int nBack        =  every->m_backNum;if(nCount - nBack < 13)return;//定义一个数组,存储1---13数字int cardNum[13];for(int i = 0; i < 13; i++)cardNum[i]  =  i + 1;bool isCardFullRedT  =  true;//利用循环进行判断for(int i = nCount; i > nCount - 13; i--){if(every->m_cards.at(i - 1) != cardNum[nCount - i]){isCardFullRedT =  false;m_curCompleteEvery = every;break;}}for(int i = 0; i < 13; i++)cardNum[i]   =  i + 14;bool isCardFullBlackT   =  true;for(int i = nCount; i > nCount - 13; i--){if(every->m_cards.at(i - 1) != cardNum[nCount - i]){isCardFullBlackT =  false;m_curCompleteEvery = every;break;}}//收牌(1--13或14--26依次存在)if(isCardFullRedT || isCardFullBlackT){m_curCompleteCardNum = 0;m_curCompleteCardVal = m_curCompleteEvery->m_cards.back();//将当前列最后一张牌删除m_curCompleteEvery->m_cards.pop_back();//计算发牌的起点和终点位置m_curCompletePoint  =  m_curCompleteEvery->CardRect(nCount).GetPos();m_curCompletePointEnd.x        =  BoardRect2D.x + EveryDis + m_moveComplete * CARDDIS_BACK;m_curCompletePointEnd.y      =  DOWNPOS - CardHeight;m_gameStatus = Completing;m_stateAccumeTime = 0;m_curUndo    =  0;}
}
bool MiniGameSpiderPoker::IsGameEnd()
{bool IsGameEnd =  true;for(int i = 0; i < EveryNum; i++){if(m_cardEverys[i].m_cards.size() != 0){IsGameEnd =  false;break;}}return IsGameEnd;
}void MiniGameSpiderPoker::AddScreen(char LbFrom, char LbTo, char MoveCardNum, int BackNum)
{if(m_curUndo == m_MaxScreen){for(int i = 1; i < m_MaxScreen; i++)      //第一个屏幕状态不变,做为一个标志m_undos[i] =  m_undos[i + 1];}elsem_curUndo++;m_undos[m_curUndo].LbFrom    =  LbFrom;m_undos[m_curUndo].LbTo  =  LbTo;m_undos[m_curUndo].MoveCardNum =  MoveCardNum;m_undos[m_curUndo].nBackNum     =  BackNum;
}int  Every::CalMaxMoveNum()
{int cardNum    =  m_cards.size();for(int i = 1; i < cardNum - m_backNum + 1; i++){if(IsLessThenTop(cardNum - i) || cardNum == 0)continue;else{m_maxMoveNum = i;return i;}}m_maxMoveNum = 0;return 0;
}bool Every::IsLessThenTop(int index)
{if(index <= m_backNum || (index+1) > m_cards.size())return false;//如果当前牌比上一张牌小,并且当前牌数不是13,或者这张牌是最后一张牌if((m_cards.at(index) == m_cards.at(index - 1) - 1)&& (m_cards.at(index) != 13) || index == 0)return true;elsereturn false;
}void Every::DeleteCard(int index)
{if(index < 0 || index > m_cards.size() - 1)return;m_cards.erase(m_cards.begin() + index);CalMaxMoveNum();
}void Every::PushCard(int card)
{m_cards.push_back(card);CalMaxMoveNum();
}int  Every::CardAt(int Index)
{return m_cards[Index];
}RectF Every::CardRect(int index)
{RectF rect;rect. x = G_SpiderGame->BoardRect2D.x + G_SpiderGame->EveryDis*(m_index + 1) + CardWidth * m_index;if (index < m_backNum){//未翻的牌rect.y = G_SpiderGame->BoardRect2D.y+30 + index * CARDDIS_BACK;}else{//翻开的牌rect.y = G_SpiderGame->BoardRect2D.y+30 + m_backNum * CARDDIS_BACK + (index-m_backNum) * CARDDIS_FRONT;}rect.width  = CardWidth;rect.height = CardHeight;return rect;
}

扑克类游戏斗地主、蜘蛛纸牌源码相关推荐

  1. 蜘蛛纸牌java注释_GitHub - tangguangyao/SpiderSolitaire: 蜘蛛纸牌源码学习+注释

    SpiderSolitaire 蜘蛛纸牌源码学习+注释 源码分析思路: 首先,用了2个构造函数Spider和Poker Spider构造函数拥有以下方法: init:函数初始化 start:游戏开始 ...

  2. 非常经典的飞行射击类游戏飞离神庙源码

    非常经典的飞行射击类游戏飞离神庙android源码,源码是从安卓教程网android.662p.com分享过来的,该游戏源码实现了一款很不错的飞行射击类游戏,飞离神庙游戏,游戏的操作玩法简单,跟我们平 ...

  3. 最新好看的自适应手机版软件APP下载类网站源码,游戏软件应用网站源码,自适应手机端Pbootcms模板

    自适应手机软件APP下载类网站源码/游戏软件应用网站源码/自适应手机端 Pbootcms模板 测试环境:Linux  nginx1.18  PHP7.3 下载地址:自适应手机端软件APP下载网站源码 ...

  4. Cocos Creator小游戏-2048(PC、安卓、H5)益智类 项目展示+完整项目源码

    游戏录像 Cocos Creator小游戏-2048 游戏玩法 在棋盘上,每次会增加一个小动物,你可以选择四个方向滑动,然后小动物会按方向移动,遇到相同的小动物就会合并,看谁合并的最多. 功能 1.初 ...

  5. vs+cmake完美编译RTS游戏,类似魔兽争霸源码

    网上的一个RTS游戏,网上的代码比较老,不能直接编译.这个仓库是我整理编译通过的.代码版权归于原作者. 源码下载 vs+cmake完美编译RTS游戏,类似魔兽争霸源码下载-其他文档类资源-CSDN文库 ...

  6. Java SpringMVC+H5飞翔的小鸟游戏微信小程序源码

    源码介绍 Java SpringMVC+H5飞翔的小鸟游戏微信小程序源码 试验性质的一个微信小程序,用canvas做的一个类似flappy-bird的小游戏. 包含一些基本的功能:躲避障碍物.计分.排 ...

  7. 最新酒桌小游戏喝酒小程序源码_带流量主源码下载

    2022最新酒桌小游戏喝酒小程序源码_带流量主 喝酒神器3.6,我修改增加了广告位,根据文档直接替换即可,原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码,然后关闭广告展示提交,通过后打 ...

  8. 2022最新酒桌小游戏喝酒小程序源码_带流量主

    2022最新酒桌小游戏喝酒小程序源码_带流量主 喝酒神器3.6,我修改增加了广告位,根据文档直接替换即可,原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码,然后关闭广告展示提交,通过后打 ...

  9. 仿《游戏鸟》网站源码+手游发号评测/游戏下载网站模板

    正文: 帝国cms仿<游戏鸟>模板源码,92kaifa版APP下载类整站源码.手机游戏门户网站模板,大型手游门户网站模板. 支持PC与手机端同步生成html,需多端同步生成插件. PS:图 ...

  10. <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(五)——Plugins

    <2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(五)--Plugins 前言 DataDispatcher DDSource DDTarget IPlugin ...

最新文章

  1. Web Api单元测试写法
  2. html双人台球游戏,使用h5和matter.js实现的简化版台球小游戏
  3. 03_数据的特征抽取,sklearn特征抽取API,字典特征抽取DictVectorizer,文本特征抽取CountVectorizer,TF-IDF(TfidfVectorizer),详细案例
  4. How to Use Command to Execute Git Push with Review from Sean
  5. Elastic发布K8s部署和控制数据管理工具官方解决方案
  6. ArrayList 相关总结
  7. matlab找距离最近的元素,如何用MATLAB找到给定坐标的最近点?
  8. linux验证db2安装成功_DB2(Linux 64位)安装教程
  9. 【编程珠玑】读书笔记 第五章 编程小事
  10. Mysql更新关联子查询报错
  11. 前端小报 - 201812 月刊
  12. 微信棋牌游戏开发 h5游戏平台制作教程linux系统
  13. Xcopy 复制文件和目录,包括子目录。
  14. oracle wmsys.wm_concat ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB
  15. 简单的WOW DKP系统
  16. Android打开系统设置界面
  17. 一着不慎被蛇咬,最近半月终出坑
  18. ArcGIS的栅格数据空间分析——栅格插值(1)
  19. Ubuntu关机和重启的命令
  20. MySql数据库中的权限授予

热门文章

  1. ubuntu里面控制器放大缩小屏幕
  2. Java 实现 POS 打印机无驱打印
  3. 7大浏览器颜值代表,谁才是真正的浏览器颜值之王呢?
  4. 一个产品经理的工作经历与总结
  5. Windows下Postman安装以及汉化
  6. slk文件(QQ or 微信) 转为 mp3
  7. pt100热电阻计算公式C语言,pt100计算公式,PT100实际应用中的两种形式
  8. imdisk虚拟光驱安装linux,ImDisk Virtual Disk Driver(虚拟光驱)
  9. HTML5-单、多选框,按钮
  10. 起底 ARM:留给中国队的时间不多了