基于MFC的纸牌游戏

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

猜你喜欢

转载自blog.csdn.net/qq_35703848/article/details/79742187