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. Java程序员校招蚂蚁金服,mysql培训考试
  2. NYOJ 469 擅长排列的小明 II (dp问题)
  3. 第 171 章 vagrant - Tool for building and distributing virtualized development environments
  4. Echarts多个坐标轴多组/一组数据 - 温度降水量示例
  5. 怎样调用另一个html中的元素,html – 使用DIV作为另一个元素的背景
  6. linux 使用命令直接查看带单位的文件大小
  7. python 字节码操作_从操作码和参数列表创建Python字节码?
  8. python死锁案例_Python 多线程死锁
  9. 如何创建 Visual Studio 2017 RC 离线安装包
  10. 函数内联inline
  11. Apple Silicon配置二进制环境(一)
  12. 普洱学院java教务系统_2020年普洱学院教务处登录入口
  13. 1.74HC138控制LED发光
  14. windows cmd 快速编辑模式
  15. 7-46 新浪微博热门话题 (30 分)
  16. 如何书写一手优雅的代码之小刚有话说
  17. EOS私链发币简要说明
  18. Unity 触摸事件的运用
  19. 默然日记20151123
  20. 微服务架构如何设计API代理网关和OAuth2授权认证框架

热门文章

  1. 解读2021年智源 AI 前沿报告:医疗领域最新进展
  2. python 爬取阳光电影资源
  3. pwrkey直接接地 sim7020_有方模块常见问题解答
  4. 4.2 制定项目章程
  5. php蝠衭厍桴埭钨,有没办法判断输入汉字的笔划数?
  6. 工厂物资管理E-R图
  7. 每日一书丨尼克新书《人工智能简史》全新升级 全方位解读AI历史和未来
  8. 关于PMSM的弱磁与MTPA结合控制超详细分析
  9. testbed 桩函数设置
  10. Java音频格式转换,支持amr、aud、slk、silk转成mp3