扑克类游戏斗地主、蜘蛛纸牌源码
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;
}
完
扑克类游戏斗地主、蜘蛛纸牌源码相关推荐
- 蜘蛛纸牌java注释_GitHub - tangguangyao/SpiderSolitaire: 蜘蛛纸牌源码学习+注释
SpiderSolitaire 蜘蛛纸牌源码学习+注释 源码分析思路: 首先,用了2个构造函数Spider和Poker Spider构造函数拥有以下方法: init:函数初始化 start:游戏开始 ...
- 非常经典的飞行射击类游戏飞离神庙源码
非常经典的飞行射击类游戏飞离神庙android源码,源码是从安卓教程网android.662p.com分享过来的,该游戏源码实现了一款很不错的飞行射击类游戏,飞离神庙游戏,游戏的操作玩法简单,跟我们平 ...
- 最新好看的自适应手机版软件APP下载类网站源码,游戏软件应用网站源码,自适应手机端Pbootcms模板
自适应手机软件APP下载类网站源码/游戏软件应用网站源码/自适应手机端 Pbootcms模板 测试环境:Linux nginx1.18 PHP7.3 下载地址:自适应手机端软件APP下载网站源码 ...
- Cocos Creator小游戏-2048(PC、安卓、H5)益智类 项目展示+完整项目源码
游戏录像 Cocos Creator小游戏-2048 游戏玩法 在棋盘上,每次会增加一个小动物,你可以选择四个方向滑动,然后小动物会按方向移动,遇到相同的小动物就会合并,看谁合并的最多. 功能 1.初 ...
- vs+cmake完美编译RTS游戏,类似魔兽争霸源码
网上的一个RTS游戏,网上的代码比较老,不能直接编译.这个仓库是我整理编译通过的.代码版权归于原作者. 源码下载 vs+cmake完美编译RTS游戏,类似魔兽争霸源码下载-其他文档类资源-CSDN文库 ...
- Java SpringMVC+H5飞翔的小鸟游戏微信小程序源码
源码介绍 Java SpringMVC+H5飞翔的小鸟游戏微信小程序源码 试验性质的一个微信小程序,用canvas做的一个类似flappy-bird的小游戏. 包含一些基本的功能:躲避障碍物.计分.排 ...
- 最新酒桌小游戏喝酒小程序源码_带流量主源码下载
2022最新酒桌小游戏喝酒小程序源码_带流量主 喝酒神器3.6,我修改增加了广告位,根据文档直接替换即可,原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码,然后关闭广告展示提交,通过后打 ...
- 2022最新酒桌小游戏喝酒小程序源码_带流量主
2022最新酒桌小游戏喝酒小程序源码_带流量主 喝酒神器3.6,我修改增加了广告位,根据文档直接替换即可,原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码,然后关闭广告展示提交,通过后打 ...
- 仿《游戏鸟》网站源码+手游发号评测/游戏下载网站模板
正文: 帝国cms仿<游戏鸟>模板源码,92kaifa版APP下载类整站源码.手机游戏门户网站模板,大型手游门户网站模板. 支持PC与手机端同步生成html,需多端同步生成插件. PS:图 ...
- <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(五)——Plugins
<2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(五)--Plugins 前言 DataDispatcher DDSource DDTarget IPlugin ...
最新文章
- Web Api单元测试写法
- html双人台球游戏,使用h5和matter.js实现的简化版台球小游戏
- 03_数据的特征抽取,sklearn特征抽取API,字典特征抽取DictVectorizer,文本特征抽取CountVectorizer,TF-IDF(TfidfVectorizer),详细案例
- How to Use Command to Execute Git Push with Review from Sean
- Elastic发布K8s部署和控制数据管理工具官方解决方案
- ArrayList 相关总结
- matlab找距离最近的元素,如何用MATLAB找到给定坐标的最近点?
- linux验证db2安装成功_DB2(Linux 64位)安装教程
- 【编程珠玑】读书笔记 第五章 编程小事
- Mysql更新关联子查询报错
- 前端小报 - 201812 月刊
- 微信棋牌游戏开发 h5游戏平台制作教程linux系统
- Xcopy 复制文件和目录,包括子目录。
- oracle wmsys.wm_concat ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB
- 简单的WOW DKP系统
- Android打开系统设置界面
- 一着不慎被蛇咬,最近半月终出坑
- ArcGIS的栅格数据空间分析——栅格插值(1)
- Ubuntu关机和重启的命令
- MySql数据库中的权限授予