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: [email protected]
// @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: [email protected]
// @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第一张牌左上角 xy
int 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: [email protected]
// @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++;
}
else
i++;
}
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();
else
m_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();
else
m_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();
else
m_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: [email protected]
// @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: [email protected]
// @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 back
if (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 back
if(Button_Pass())
return true;
}
//call back
if (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 ;
else
m_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");
else
strcat(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");
else
strcat(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");
else
strcat(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");
else
strcat(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");
else
strcat(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");
else
strcat(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");
else
strcat(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: [email protected]
// @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: [email protected]
// @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");
else
strcat(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");
else
m_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");
else
strcat(sound,".wav");
m_sound->PlaySound__(sound);
}
break;
case Playing:
{
ThinkOutCard();
if(m_notOut==false)
{
//out
m_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
{
//pass
C2SPacketMiniGameCmd 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");
else
strcat(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];
else
m_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;
}
else
return 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; 不能有2
if(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; //最大不能为2
g_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; //最大不能为2
g_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; //最大不能为2
if(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; //最大不能为2
g_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; //最大不能为2
if( 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; //最大不能为2
g_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; //最大不能为2
if( 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; //最大不能为2
if( 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; //最大不能为2
if( 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; //最大不能为2
g_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: [email protected]
// @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 96
class 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 10
int 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: [email protected]
// @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();
else
m_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);
else
m_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];
}
else
m_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;
else
return 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;
}
完