1.介绍
基类CCObject有两个派生类:一个是CCardsRank类,实现牌组的相关链表操作,并按规则显示纸牌;另一个是CRule类,类中运用算法实现接受纸牌和发送纸牌的规则,同时更新坐标。CAAAACardRank类、CAAAARule类分别继承CCardsRank类、CRule类实现细化的功能。
2.程序
CAAAACardRank.h
#pragma once
#include "cardsrank.h"
class CAAAACardRank :
public CCardsRank
{
public:
DECLARE_DYNCREATE()
public:
CAAAACardRank(void);
~CAAAACardRank(void);
public:
virtual void InitCardsRank(HINSTANCE hlns);
};
CAAAACardRank.cpp
#include "AAAACardRank.h"
IMPLEMENT_DYNCREATE(CAAAACardRank,CCardsRank)
CAAAACardRank::CAAAACardRank(void):CCardsRank(11)
{
}
CAAAACardRank::~CAAAACardRank(void)
{
}
void CAAAACardRank::InitCardsRank(HINSTANCE hlns)
{
m_hCardsBackBmp=::LoadBitmap(hlns,MAKEINTRESOURCE(IDB_BACK));
m_pPoker=new CPoker[8];
for(int i=0;i<8;i++)
{
m_pPoker[i].InitPokerCards(hlns,Cards_Black);
m_pPoker[i].RandomPokerCards();
}
int j=0;
int k=0;
vector<CCards *>vtr(104);
for(int i=0;i<104;i++)
{
if(j==13)
{
k++;
j=0;
}
vtr[i]=m_pPoker[k].m_vtrPoker[j++];
}
::random_shuffle(vtr.begin(),vtr.end());
k=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<6;j++)
{
Node *node=new Node;
node->bFlag=false;
node->pCards=vtr[k++];
node->x=i*81+10;
node->y=j*20+10;
m_vtrRank[i].push_back(node);
}
m_vtrRank[i].back()->bFlag=true;
}
for(int i=4;i<10;i++)
{
for(int j=0;j<5;j++)
{
Node *node=new Node;
node->bFlag=false;
node->pCards=vtr[k++];
node->x=i*81+10;
node->y=j*20+10;
m_vtrRank[i].push_back(node);
}
m_vtrRank[i].back()->bFlag=true;
}
for(int i=49;i>=0;i--)
{
Node *node=new Node;
node->bFlag=false;
node->pCards=vtr[k++];
node->x=i*3+500;
node->y=500;
m_vtrRank[10].push_back(node);
}
}
CAAAARule.h
#include "AAAARule.h"
IMPLEMENT_DYNCREATE(CAAAARule,CRule)
CAAAARule::CAAAARule(void)
{
}
CAAAARule::~CAAAARule(void)
{
}
// 拿牌的规则
bool CAAAARule::IsGetCardsRole(CCardsRank* pCardsRank, int nlstID, list<Node*>::iterator iteCursorPos)
{
if(nlstID>=0&&nlstID<=9)
{
int num=(*iteCursorPos)->pCards->m_nCardsNum;
while(iteCursorPos!=pCardsRank->m_vtrRank[nlstID].end())
{
if((*iteCursorPos)->bFlag==false)
{
return false;
}
--num;
++iteCursorPos;
}
}
return true;
}
// 发牌
bool CAAAARule::IsOpenCards(POINT point, CCardsRank* pCardsRank)
{
if(pCardsRank->m_vtrRank[10].empty()==false)
{
for(int i=0;i<10;i++)
{
if(pCardsRank->m_vtrRank[i].empty()==true)
{
return false;
}
}
if(point.x >= pCardsRank->m_vtrRank[10].back()->x && point.x <= pCardsRank->m_vtrRank[10].back()->x+71
&& point.y >= pCardsRank->m_vtrRank[10].back()->y && point.y <= pCardsRank->m_vtrRank[10].back()->y+96)
{
return true;
}
}
return false;
}
void CAAAARule::OpenCards(CCardsRank* pCardsRank)
{
for(int i = 0;i<10;i++)
{
pCardsRank->m_vtrRank[10].back()->bFlag = true;
pCardsRank->m_vtrRank[10].back()->x = pCardsRank->m_vtrRank[i].back()->x;
pCardsRank->m_vtrRank[10].back()->y = pCardsRank->m_vtrRank[i].back()->y+20;
pCardsRank->m_vtrRank[i].push_back(pCardsRank->m_vtrRank[10].back());
pCardsRank->m_vtrRank[10].pop_back();
}
}
// 接收牌的规则
bool CAAAARule::ReceiveCardsRole(POINT point, int nlstID, CCardsRank* pCardsRank, list<Node*>& lstCursorCards)
{
if(nlstID>=0&&nlstID<=9)
{
if(pCardsRank->m_vtrRank[nlstID].empty() == true)//判断是否为空
{
//判断矩形框
if(point.x>=nlstID*81+10&&point.x<=nlstID*81+71&&point.y>=10&&point.y<=10+96)
{
return true;
}
}else
{
//比较两个大小
if(pCardsRank->m_vtrRank[nlstID].back()->pCards->m_nCardsNum==lstCursorCards.front()->pCards->m_nCardsNum+1)
{
return true;
}
}
}
return false;
}
// 更新坐标
void CAAAARule::UpDatePos(CCardsRank* pCardsRank, int nlstID)
{
int j=0;
list<Node *>::iterator ite=pCardsRank->m_vtrRank[nlstID].begin();
while(ite!=pCardsRank->m_vtrRank[nlstID].end())
{
(*ite)->x=nlstID*81+10;
(*ite)->y=(j++)*20+10;
ite++;
}
int nNum=1;
list<Node *>::reverse_iterator recite=pCardsRank->m_vtrRank[nlstID].rbegin();
if(pCardsRank->m_vtrRank[nlstID].size()>=13&&pCardsRank->m_vtrRank[nlstID].back()->pCards->m_nCardsNum==1)
{
for(int i=0;i<13;i++)
{
if((*recite)->bFlag==false)
{
return ;
}
if(nNum!=(*recite)->pCards->m_nCardsNum)
{
return;
}
++nNum;
++recite;
}
}
//删除节点及节点的内容
list<Node *>::iterator itedel=recite.base();
while(itedel!=pCardsRank->m_vtrRank[nlstID].end())
{
delete (*itedel);
itedel=pCardsRank->m_vtrRank[nlstID].erase(itedel);
}
if(pCardsRank->m_vtrRank[nlstID].empty()==false)
{
pCardsRank->m_vtrRank[nlstID].back()->bFlag=true;
}
}
CAAAARule.cpp
#pragma once
#include "rule.h"
class CAAAARule :
public CRule
{
public:
DECLARE_DYNCREATE()
public:
CAAAARule(void);
~CAAAARule(void);
#pragma once
#include "Sys.h"
class CCards
{
public:
HBITMAP m_hCardsBmp;
int m_nCardsColor;
int m_nCardsNum;
public:
CCards(void);
~CCards(void);
public:
void InitCards(HINSTANCE hIns, int nBmpID,int nColor, int nNum);
};
public:// 拿牌的规则virtual bool IsGetCardsRole(CCardsRank* pCardsRank, int nlstID, list<Node*>::iterator iteCursorPos);// 发牌virtual bool IsOpenCards(POINT point, CCardsRank* pCardsRank) ;virtual void OpenCards(CCardsRank* pCardsRank);// 接收牌的规则virtual bool ReceiveCardsRole(POINT point, int nlstID, CCardsRank* pCardsRank, list<Node*>& lstCursorCards);// 更新坐标virtual void UpDatePos(CCardsRank* pCardsRank, int nlstID);};
CCards.h
#pragma once
#include "Sys.h"
class CCards
{
public:
HBITMAP m_hCardsBmp;
int m_nCardsColor;
int m_nCardsNum;
public:
CCards(void);
~CCards(void);
public:
void InitCards(HINSTANCE hIns, int nBmpID,int nColor, int nNum);
};
CCards.cpp
#include "Cards.h"
CCards::CCards(void)
{
m_hCardsBmp = 0;
m_nCardsColor = 0;
m_nCardsNum = 0;
}
CCards::~CCards(void)
{
::DeleteObject(m_hCardsBmp);
m_hCardsBmp = 0;
}
void CCards::InitCards(HINSTANCE hIns, int nBmpID,int nColor, int nNum)
{
m_hCardsBmp = ::LoadBitmap(hIns,MAKEINTRESOURCE(nBmpID));
m_nCardsColor = nColor;
m_nCardsNum = nNum;
}
CCardsCtrl.h
#pragma once
#include "cgamectrl.h"
#include "CardsRank.h"
#include "Rule.h"
class CCardsCtrl :
public CGameCtrl
{
public:
CCardsRank* m_pRank;
CRule* m_pRule;
int X;
int Y;
POINT pointMouseDown;
POINT pointMouseMove;
list<Node*> lstCursor;
public:
DECLARE()
public:
CCardsCtrl(void);
~CCardsCtrl(void);
public:
virtual void OnCreateGame(); // WM_CREATE
virtual void OnGameDraw(); // WM_PAINT
virtual void OnLButtonDown(POINT point); //WM_LBUTTONDOWN
virtual void OnLButtonUp(POINT point); //WM_RBUTTONDOWN
virtual void OnMouseMove(POINT point); //WM_MOUSEMOVE
public:
void ShowCursorCards(HDC hMemDC);
};
CCardsCtrl.cpp
#include "CardsCtrl.h"
IMPLEMENT(CCardsCtrl)
CCardsCtrl::CCardsCtrl(void)
{
m_pRank = NULL;
X = 0;
Y = 0;
}
CCardsCtrl::~CCardsCtrl(void)
{
delete m_pRank;
m_pRank = NULL;
delete m_pRule;
m_pRule = NULL;
}
void CCardsCtrl::OnCreateGame()
{
m_pRank = (CCardsRank*)CCObject::Create("CCardsRank");
m_pRule = (CRule*)CCObject::Create("CRule");
if(m_pRule == NULL)
MessageBox(NULL,"游戏初始化失败","提示",MB_OK);
if(m_pRank != NULL)
m_pRank->InitCardsRank(m_hIns); // 初始化游戏
}
void CCardsCtrl::OnGameDraw()
{
if(m_pRank == NULL)
return;
HDC dc = ::GetDC(m_hWnd);
HDC hMemDC = ::CreateCompatibleDC(dc);
HBITMAP hBitmap = ::CreateCompatibleBitmap(dc,1024,768);
::SelectObject(hMemDC,hBitmap);
//----------------------------------------------------
m_pRank->ShowRank(hMemDC);
this->ShowCursorCards(hMemDC);
//----------------------------------------------------
::BitBlt(dc,0,0,1024,768,hMemDC,0,0,SRCCOPY);
::DeleteDC(hMemDC);
::DeleteObject(hBitmap);
::ReleaseDC(m_hWnd,dc);
}
void CCardsCtrl::OnLButtonDown(POINT point)
{
pointMouseDown = point;
if(m_pRule != NULL && lstCursor.empty() == true)
m_pRule->GetCards(point,m_pRank,lstCursor);
this->OnGameDraw(); // 重绘
}
void CCardsCtrl::OnLButtonUp(POINT point)
{
// 光标有没有牌
if(lstCursor.empty() == false) // 执行接收
{
if(m_pRule->ReceiveCards(point,m_pRank,lstCursor) == false)
{
// 没有被接收 要回到原来的位置
m_pRule->RevertCards(m_pRank,lstCursor);
}
this->OnGameDraw();// 重绘
}
else // 有可能要发牌
{
if(m_pRule->IsOpenCards(point,m_pRank) == true)
{
// 发牌
m_pRule->OpenCards(m_pRank);
this->OnGameDraw();// 重绘
}
}
}
void CCardsCtrl::OnMouseMove(POINT point)
{
pointMouseMove = point;
if(lstCursor.empty() == false)
this->OnGameDraw();
}
void CCardsCtrl::ShowCursorCards(HDC hMemDC)
{
X = pointMouseMove.x - pointMouseDown.x;
Y = pointMouseMove.y - pointMouseDown.y;
// 显示光标上的链表
list<Node*>::iterator ite = lstCursor.begin();
while(ite != lstCursor.end())
{
// 贴图
HDC hTempDC = ::CreateCompatibleDC(hMemDC);
::SelectObject(hTempDC,(*ite)->pCards->m_hCardsBmp);
::BitBlt(hMemDC,(*ite)->x+X,(*ite)->y+Y,71,96,hTempDC,0,0,SRCCOPY);
::DeleteDC(hTempDC);
++ite;
}
}
CCardsRank.h
#include "CardsRank.h"
CCardsRank::CCardsRank(int nCount):m_vtrRank(nCount)
{
m_pPoker = 0;
m_hBackBmp = 0;
m_hCardsBackBmp = 0;
}
CCardsRank::~CCardsRank(void)
{
::DeleteObject(m_hBackBmp);
m_hBackBmp = NULL;
::DeleteObject(m_hCardsBackBmp);
m_hCardsBackBmp = NULL;
delete[] m_pPoker;
m_pPoker = NULL;
// 删除 所有链表
vector<list<Node*>>::iterator vtr_ite = m_vtrRank.begin();
while(vtr_ite != m_vtrRank.end())
{
//-----------------------------------------
list<Node*>::iterator lst_ite = (*vtr_ite).begin();
while(lst_ite != (*vtr_ite).end())
{
delete (*lst_ite);
++lst_ite;
}
//-----------------------------------------
++vtr_ite;
}
}
void CCardsRank::ShowRank(HDC hMemDC)
{
if(m_hBackBmp == 0)
{
// 加载 默认的 背景图片
m_hBackBmp = ::CreateCompatibleBitmap(hMemDC,1024,768);
}
// 贴背景图片
HDC hBackDC = ::CreateCompatibleDC(hMemDC);
::SelectObject(hBackDC,m_hBackBmp);
::BitBlt(hMemDC,0,0,1024,768,hBackDC,0,0,SRCCOPY);
::DeleteDC(hBackDC);
hBackDC = NULL;
if(m_hCardsBackBmp == 0)
{
// 加载 默认的 牌的背面图片
}
// 删除 所有链表
vector<list<Node*>>::iterator vtr_ite = m_vtrRank.begin();
while(vtr_ite != m_vtrRank.end())
{
//-----------------------------------------
list<Node*>::iterator lst_ite = (*vtr_ite).begin();
while(lst_ite != (*vtr_ite).end())
{
// ----------------- 贴图 -----------------
HDC hTempDC = ::CreateCompatibleDC(hMemDC);
if((*lst_ite)->bFlag == false)
::SelectObject(hTempDC,m_hCardsBackBmp);
else
::SelectObject(hTempDC,(*lst_ite)->pCards->m_hCardsBmp);
::BitBlt(hMemDC,(*lst_ite)->x,(*lst_ite)->y,71,96,hTempDC,0,0,SRCCOPY);
::DeleteDC(hTempDC);
hTempDC = NULL;
//---------------------------------------
++lst_ite;
}
//-----------------------------------------
++vtr_ite;
}
}
CGameCtrl.h
#pragma once
#ifndef _GAMECTRL_H_
#define _GAMECTRL_H_
#include <windows.h>
class CGameCtrl;
typedef CGameCtrl* (*PFUN_CREATE_OBJECT)(); // 创建对象的函数指针的类型
#define DECLARE() static CGameCtrl* CreateObject();
#define IMPLEMENT(ThisClass)\
CGameCtrl* ThisClass::CreateObject()\
{\
return new ThisClass;\
}\
Init init##ThisClass(&ThisClass::CreateObject);
class CGameCtrl
{
public:
static PFUN_CREATE_OBJECT pfun_create_object; // 创建子类对象的函数指针
public:
HINSTANCE m_hIns;
HWND m_hWnd;
public:
CGameCtrl()
{
m_hIns = NULL;
m_hWnd = NULL;
}
virtual ~CGameCtrl()
{
//::DestroyWindow(m_hWnd);
}
void SetHandle(HINSTANCE hIns,HWND hwnd)
{
m_hIns = hIns;
m_hWnd = hwnd;
}
public:
virtual void OnCreateGame(){} // WM_CREATE
virtual void OnGameDraw(){} // WM_PAINT
virtual void OnGameRun(WPARAM nTimeID){} // WM_TIMER
virtual void OnKeyDown(WPARAM nKey){} //WM_KEYDOWN
virtual void OnKeyUp(WPARAM nKey){} //WM_KEYUP
virtual void OnLButtonDown(POINT point){} //WM_LBUTTONDOWN
virtual void OnRButtonDown(POINT point){} //WM_RBUTTONDOWN
virtual void OnLButtonUp(POINT point){} //WM_LBUTTONUP
virtual void OnRButtonUp(POINT point){} //WM_RBUTTONUP
virtual void OnMouseMove(POINT point){} //WM_MOUSEMOVE
};
class Init
{
public:
Init(PFUN_CREATE_OBJECT pfun)
{
CGameCtrl::pfun_create_object = pfun;
}
};
#endif //_GAMECTRL_H_
Node.h
#pragma once
#include "Cards.h"
struct Node
{
bool bFlag; // 显示正反面
int x;
int y;
CCards* pCards; // 装一张牌
};
CPoker.h
#pragma once
#include "Sys.h"
#include "Cards.h"
class CPoker
{
public:
CPoker(void);
~CPoker(void);
public:
vector<CCards*> m_vtrPoker;
public:
void InitPokerCards(HINSTANCE hIns, int nColor);
void RandomPokerCards();
};
CPoker.cpp
#include "Poker.h"
CPoker::CPoker(void):m_vtrPoker(13)
{
}
CPoker::~CPoker(void)
{
for(int i=0;i<13;i++)
delete m_vtrPoker[i];
}
void CPoker::InitPokerCards(HINSTANCE hIns, int nColor)
{
for(int i=0;i<13;i++)
{
m_vtrPoker[i] = new CCards;
m_vtrPoker[i]->InitCards(hIns,IDB_BITMAP1+(nColor*13)+i,nColor,i+1);
}
}
void CPoker::RandomPokerCards()
{
::random_shuffle(m_vtrPoker.begin(),m_vtrPoker.end());
}
CRule.h
#pragma once
#include "cobject.h"
#include "CardsRank.h"
#include "Sys.h"
class CRule :
public CCObject
{
public:
int m_nGetCardsListID;
public:
CRule(void);
~CRule(void);
public:
bool ReceiveCards(POINT point, CCardsRank* pCardsRank, list<Node*>& lstCursor);
void GetCards(POINT point, CCardsRank* pCardsRank, list<Node*>& lstCursor);
void RevertCards(CCardsRank* pCardsRank, list<Node*>& lstCursor);
public:
// 拿牌的规则
virtual bool IsGetCardsRole(CCardsRank* pCardsRank, int nlstID, list<Node*>::iterator iteCursorPos) = 0;
// 发牌
virtual bool IsOpenCards(POINT point, CCardsRank* pCardsRank) = 0;
virtual void OpenCards(CCardsRank* pCardsRank) = 0;
// 接收牌的规则
virtual bool ReceiveCardsRole(POINT point, int nlstID, CCardsRank* pCardsRank, list<Node*>& lstCursorCards) = 0;
// 更新坐标
virtual void UpDatePos(CCardsRank* pCardsRank, int nlstID) = 0;
};
CRule.cpp
#include "Rule.h"
CRule::CRule(void)
{
m_nGetCardsListID = -1;
}
CRule::~CRule(void)
{
}
bool CRule::ReceiveCards(POINT point, CCardsRank* pCardsRank, list<Node*>& lstCursor)
{
// 判断是否点击到 尾节点
for(size_t i=0; i<pCardsRank->m_vtrRank.size(); i++) // 遍历所有链表
{
if(pCardsRank->m_vtrRank[i].empty() == true) // 链表是 NULL 让 子类 判断 是否在 固定的 矩形框
{
if(this->ReceiveCardsRole(point,i,pCardsRank,lstCursor) == true) // 判断 是否可以接收
{
// 把 光标的链表 和 第i 个链表 结合
pCardsRank->m_vtrRank[i].splice(pCardsRank->m_vtrRank[i].end(),lstCursor);
// 更新坐标
this->UpDatePos(pCardsRank,i);
// 翻牌 把 拿牌的那个链表的 尾 bFlag 变成 true
if(pCardsRank->m_vtrRank[m_nGetCardsListID].empty() == false)
pCardsRank->m_vtrRank[m_nGetCardsListID].back()->bFlag = true;
return true;
}
} // 是否拖到 尾节点的范围
else if(point.x >= pCardsRank->m_vtrRank[i].back()->x && point.x <= pCardsRank->m_vtrRank[i].back()->x+71
&& point.y >= pCardsRank->m_vtrRank[i].back()->y && point.y <= pCardsRank->m_vtrRank[i].back()->y+96)
{
if(this->ReceiveCardsRole(point,i,pCardsRank,lstCursor) == true) // 判断 是否可以接收
{
// 把 光标的链表 和 第i 个链表 结合
pCardsRank->m_vtrRank[i].splice(pCardsRank->m_vtrRank[i].end(),lstCursor);
// 更新坐标
this->UpDatePos(pCardsRank,i);
// 翻牌 把 拿牌的那个链表的 尾 bFlag 变成 true
if(pCardsRank->m_vtrRank[m_nGetCardsListID].empty() == false)
pCardsRank->m_vtrRank[m_nGetCardsListID].back()->bFlag = true;
return true;
}
}
}
return false;
}
void CRule::GetCards(POINT point, CCardsRank* pCardsRank, list<Node*>& lstCursor)
{
// 遍历链表 看 光标 点击了 哪一张上
for(size_t i=0; i<pCardsRank->m_vtrRank.size(); i++) // 遍历所有链表
{
// 遍历 第几个链表
list<Node*>::reverse_iterator rev_ite = pCardsRank->m_vtrRank[i].rbegin();
while(rev_ite != pCardsRank->m_vtrRank[i].rend())
{
//--------------------判断 光标的坐标 是否点击这个牌上----------------
if(point.x >= (*rev_ite)->x && point.x <= (*rev_ite)->x+71
&& point.y >= (*rev_ite)->y && point.y <= (*rev_ite)->y+96 )
{
if((*rev_ite)->bFlag == true) // 正面 才有可能拿牌
{
list<Node*>::iterator ite = (++rev_ite).base();
// 能不能拿起来
if(this->IsGetCardsRole(pCardsRank,i,ite) == true)
{
// 把拿起来的牌和光标结合
lstCursor.splice(lstCursor.end(),pCardsRank->m_vtrRank[i],ite,pCardsRank->m_vtrRank[i].end());
// 记录在第几个链表上拿起来的
m_nGetCardsListID = i;
}
}
return;
}
//-------------------------------------------------------------------
++rev_ite;
}
}
}
void CRule::RevertCards(CCardsRank* pCardsRank, list<Node*>& lstCursor)
{
// 把 光标上的链表 和 m_nGetCardsListID 链表链接
pCardsRank->m_vtrRank[m_nGetCardsListID].splice(pCardsRank->m_vtrRank[m_nGetCardsListID].end(),lstCursor);
m_nGetCardsListID = -1;
}