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; }