⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 game.cpp

📁 这是纸牌游戏斗地主,算法完整,可以单机,网络连线玩.
💻 CPP
字号:
#include "stdafx.h"
#include "斗地主.h"
#include "MainFrm.h"

#include "My_DirectInput.h"
#include "my_directdraw.h"

#include "Playing_Cards.h"

#include "Game.h"

#include "Draw_Item_Engine.h"
#include "Draw_Cards_Engine.h"

//#include "Single_Game.h"
//主窗口句柄;
HWND hWnd;		
//主窗口类指针;设为全局变量便于各个类访问其方法;
CMainFrame* pCMainFrame;

//DirectDraw设备对象指针;
CMyDirectInput* pInput;
CMyDirectDraw* pDraw;
LPDIRECTDRAWSURFACE7  lpddsprimary;		// dd primary surface
LPDIRECTDRAWSURFACE7  lpddsback;		// dd back surface
LPDIRECTDRAWSURFACE7  lpddsbg_Game;		//离屏表面;

//游戏主体框架类指针;
CGame* pGame;
//54张扑克;
CCard g_cAllCards[54];

//存储玩家信息的类;
CPlayerInfo* pCenterPlayer;
CPlayerInfo* pLeftPlayer;
CPlayerInfo* pRightPlayer;

CPlayingCards* pLeftCards;      //左边玩家的牌对象;
CPlayingCards* pCenterCards;		  //主机玩家的牌对象;
CPlayingCards* pRightCards;	  //右边玩家的牌对象;

//关于其他精灵的绘制引擎;
CDrawItemEngine* pDrawItem;
//关于扑克绘制的引擎;
CDrawCardsEngine* pDrawCards;
//游戏牌面坐标系统;
CCardsMap* pCardsMap;

//网络设备;
CLink* pServerLink1;  //连接客户1;
CLink* pServerLink2;  //连接客户2;
CLink* pClientLink;   //客户端1;

//位置坐标;
int Screen_Width = 1024;	int Screen_Height = 768;  //屏幕长,宽;

int Cards_Width = 82;		int Cards_Height = 114;  //扑克长宽;

//int Face_Width = 70;		int Face_Height = 70;	//头像的长宽;

int	Center_x0 = 350;	    int Center_y0 = 620; //中间玩家未出的牌;
int	Center_x1 = 230;	    int Center_y1 = 470; //中间玩家已经出过的牌;
int	Center_x2 = 330;	    int Center_y2 = 340; //中间玩家刚出的牌;

int	Left_x0 = 35;		    int Left_y0 = 140;	//左边玩家未出的牌;
int	Left_x1 = 140;		    int Left_y1 = 30;	//左边玩家已经出过的牌;
int	Left_x2 = 240;		    int Left_y2 = 65;	//左边玩家刚出的牌;

int Right_x0 = 905;		    int Right_y0 = 140;  //右边玩家未出的牌;
int	Right_x1 = 800;		    int Right_y1 = 30;  //右边玩家已经出过的牌;
int	Right_x2 = 700;		    int Right_y2 = 65;  //右边玩家刚出的牌;
//三张显示的地主牌;
int Lord_Card1_x = 379;		int Lord_Card1_y =  30;
int Lord_Card2_x = 471;		int Lord_Card2_y =  30;
int Lord_Card3_x = 563;		int Lord_Card3_y =  30;
              
int	Card_x = 471;		    int Card_y = 190;	//发牌的起始位置;
//左,右玩家未出牌和中间玩家已出牌的间距:
int	Card_Distance0 = 18;
//左,右玩家已出牌的间距;
int	Card_Distance1 = 23;
//中间玩家未出牌和刚出的牌的间距;
int	Card_Distance2 = 25;
//中间扑克选择后突出的高度;
int	Card_Up = 20;

CPlayerInfo::CPlayerInfo()
{
	m_nPlayerType = -1;
	m_nFaceID     = -1;
	m_nScore      = 50;			
	m_nWin        = 0;			
	m_nLose       = 0;		
}

//游戏屏幕刷新函数;
int RedrawGame(BOOL bSprimary)
{
	pDraw->DrawSurface(lpddsbg_Game,0,0, Screen_Width,Screen_Height,lpddsback,0); 
	//重画整个牌面布局;
	pDrawCards->Redraw();
	pDrawItem->Redraw();

	if(bSprimary == 1)
		while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));

	return 1;
}


CGame::CGame():m_cCardsRect(Center_x0,
						    Center_y0,
						    0,          //这个值会变,不定;
						    Center_y0 + Cards_Height),
			  m_cCardsUpRect(Center_x0,
							 Center_y0 - Card_Up,
							 0,		//这个值会变,不定;
							 Center_y0 + Cards_Height - Card_Up),
			  m_cOK_RECT(660,550,660+80,550+30),
			  m_cYES_RECT(335,540,335+80,540+30),
			  m_cNO_RECT(425,540,425+80,540+30),
			  m_cEXIT_RECT(900,695,900+100,695+30)
{
	m_nCurrentLord = -1;  
	m_nDefaultLord = -1;	
	m_nLordLock    = -1; 

	m_bButton	   = 1;

	m_bOperate     = FALSE;

	m_nRoundCounter = 0;	
	m_nGameCounter  = 0;
	m_nBombCounter  = 0;
}

CGame::~CGame()
{
}

void CGame::Init()
{
	//Dx设备的初始化;

	//产生DirctDraw对象;
	pDraw = new CMyDirectDraw;		
	pDraw->Init();

	//初始化鼠标输入设备;
	pInput = new CMyDirectInput;   
	pInput->MouseInit();
	
	pLeftCards  = new CPlayingCards;      //左边玩家的牌对象;
	pCenterCards    = new CPlayingCards;  //主机玩家的牌对象;
	pRightCards = new CPlayingCards;	  //右边玩家的牌对象;

	pCardsMap = new CCardsMap;           

	pDrawItem = new CDrawItemEngine;	
	pDrawItem->Init();

	pDrawCards = new CDrawCardsEngine;  
	pDrawCards->Init();
}
//新一局,洗牌;
void CGame::NewGame()
{
	m_nGameCounter++;

	m_nCurrentLord = -1;  
	m_nDefaultLord = -1;	
	m_nLordLock    = -1; 

	m_bButton	 = 1;
	m_bOperate   = FALSE;

	m_nRoundCounter = 0;  
	m_nBombCounter = 0;

	pDrawCards->m_bVisual = FALSE;

	pLeftCards->New();
	pCenterCards->New();
	pRightCards->New();

//让新的地主牌不可见,让发的牌可见;
	pCardsMap->m_nLordCards = 1;
	pCardsMap->m_cDistributeCard.m_bVisual = 1;

	for(int i=0;i<3;i++)
	{
		pCardsMap->m_cLordCards[i].m_bVisual = 0;  //0为不可见;
	}
}
//洗牌;
void CGame::ShuffleCards()
{
//将牌放入;
	for(int i=3,j=0;j<=12;i++,j++)
	{
			//黑桃
		g_cAllCards[j*4+0].m_nColor = 0;
		g_cAllCards[j*4+0].m_nValue = i;
			//红桃
		g_cAllCards[j*4+1].m_nColor = 1;
		g_cAllCards[j*4+1].m_nValue = i;
			//梅花
		g_cAllCards[j*4+2].m_nColor = 2;
		g_cAllCards[j*4+2].m_nValue = i;
			//方块
		g_cAllCards[j*4+3].m_nColor = 3;
		g_cAllCards[j*4+3].m_nValue = i;
	}
	
	g_cAllCards[52].m_nColor = 1;   //正百搭;
	g_cAllCards[52].m_nValue = 16;

	g_cAllCards[53].m_nColor = 0;	//副百搭;
	g_cAllCards[53].m_nValue = 16;	

//高效洗牌;
	int nRandPos;   
	CCard cTempCard;

	for(int k=0;k<54;k++)
	{
//产生一个随机位置;
		nRandPos = rand()%54;  
//把当前牌与这个随机位置的牌交换;
		cTempCard = g_cAllCards[k];
		g_cAllCards[k] = g_cAllCards[nRandPos];
		g_cAllCards[nRandPos] = cTempCard;	
	}
}
//当轮到本机玩家出牌时的屏幕刷新函数;
int CGame::RefreshMyTurn()
{
//	::Redraw_Game();
	if( m_nLordLock != 1 )
	{
		if( m_bButton )   //延时锁;
		{
		//当鼠标点击到按钮并且提起牌数不为0时才执行出牌操作
		if( pInput->IsLButtonDown(m_cOK_RECT) )  
		{
			::KillTimer(hWnd,20);
			PlaySound(MAKEINTRESOURCE(IDR_DING),AfxGetResourceHandle(),
				SND_ASYNC|SND_RESOURCE|SND_NODEFAULT );  //
			int i = CenterDoing();
			if( i == 0 )
			{			
				::SetTimer(hWnd,20,50,NULL);  //恢复计时器;
			}
			else if( i == 1 )
			{
				//左边玩家(电脑)思考,并决定要出的牌;
				if( RightDoing() == 0 )
				{
					return 0;
				}
				//右边玩家(电脑)思考,并决定要出的牌;
				if( LeftDoing() == 0 )
				{
					return 0;
				}
				::SetTimer(hWnd,20,50,NULL);
			}
			else if( i == 2 )
			{
				return 0;
			}
		}
		//
		}
	}
	else
	{
		::KillTimer(hWnd,20);

		CenterDoing();
		if( RightDoing() == 0 )
		{
			return 0;
		}
		Sleep(1000);  //延时;
		//右边玩家(电脑)思考,并决定要出的牌;
		if( LeftDoing() == 0 )
		{
			return 0;
		}
		Sleep(1000);  //延时;
		::SetTimer(hWnd,20,50,NULL);
	}
	return 1;
}
//刷新菜单控制整个游戏生命周期的全局线程函数;
DWORD WINAPI CGame::RefreshMenu(LPVOID pParam)
{
	int pos;
	CPoint point;

while(1)
{
	//如果正在游戏当中;
	if( pGame->m_bOperate  )
	{
	pGame->m_cCardsRect.right    = Center_x0 + Card_Distance1 * (pCenterCards->m_nCardsCounter - 1) + Cards_Width;
	pGame->m_cCardsUpRect.right	= Center_x0 + Card_Distance1 * (pCenterCards->m_nCardsCounter - 1) + Cards_Width;
	if( pInput->IsLButtonDown(pGame->m_cCardsRect) )
	{
		::GetCursorPos(&point);
		pos = (point.x - Center_x0)/Card_Distance1 + 1;  //左键点击的牌;

		if(pos >= pCenterCards->m_nCardsCounter)
		{
			if(pCardsMap->Center0[pCenterCards->m_nCardsCounter - 1].m_nY != Center_y0 - Card_Up)
			{
				PlaySound(MAKEINTRESOURCE(IDR_GIVE),AfxGetResourceHandle(),
					SND_ASYNC|SND_RESOURCE|SND_NODEFAULT );  //
				pCardsMap->Center0[pCenterCards->m_nCardsCounter - 1].m_nY -= Card_Up;
				pCardsMap->m_nUpCounter++;			//选择提起的牌数加一;
				::RedrawGame();
//				return 1;
			}//end if(pCardsMap->Center0[pCenterCards->Cards_Counter - 1].m_nY == Center_y0 - Card_Up)
		}
		else
		{
			if(pCardsMap->Center0[pos - 1].m_nY != Center_y0 - Card_Up)
			{
				PlaySound(MAKEINTRESOURCE(IDR_GIVE),AfxGetResourceHandle(),
					SND_ASYNC|SND_RESOURCE|SND_NODEFAULT );  //
				pCardsMap->Center0[pos - 1].m_nY -= Card_Up;
				pCardsMap->m_nUpCounter++;			//选择提起的牌数加一;
				::RedrawGame();
//				return 1;
			}
		}// end if(pos >= pCenterCards->Cards_Counter)
	}
	else if( pInput->IsRButtonDown(pGame->m_cCardsUpRect) )
	{
		::GetCursorPos(&point);
		pos = (point.x - Center_x0)/Card_Distance1 + 1;  //右键点击的牌;

		if(pos >= pCenterCards->m_nCardsCounter)
		{
			if(pCardsMap->Center0[pCenterCards->m_nCardsCounter - 1].m_nY == Center_y0 - Card_Up)
			{
				PlaySound(MAKEINTRESOURCE(IDR_GIVE),AfxGetResourceHandle(),
					SND_ASYNC|SND_RESOURCE|SND_NODEFAULT );  //
				pCardsMap->Center0[pCenterCards->m_nCardsCounter - 1].m_nY += Card_Up;
				pCardsMap->m_nUpCounter--;			//选择提起的牌数减一;
				::RedrawGame();
			}
		}
	    else
		{
			if(pCardsMap->Center0[pos - 1].m_nY == Center_y0 - Card_Up)
			{
				PlaySound(MAKEINTRESOURCE(IDR_GIVE),AfxGetResourceHandle(),
					SND_ASYNC|SND_RESOURCE|SND_NODEFAULT );  //
				pCardsMap->Center0[pos - 1].m_nY += Card_Up;
				pCardsMap->m_nUpCounter--;			//选择提起的牌数减一;
				::RedrawGame();
			}
		}// end if(pos >= pCenterCards->Cards_Counter)
	}//end if 点击在未出牌区;

	} //end if;
	//刷新菜单;
	if( pInput->IsLButtonDown(pGame->m_cEXIT_RECT) )  
	{
		::PostMessage(hWnd,WM_CLOSE,NULL,NULL); 
		::ExitProcess(NULL);
		//强制结束游戏;
	}
	Sleep(20);
}//end while;

	return 1;
}

void CGame::AccountScore(int player)
{
	//地主胜;
	int score = 0;
	if( m_nBombCounter == 0 )
	{
		score = 1;
	}
	else
	{	
		score = 2;
		m_nBombCounter--;
		while( m_nBombCounter )
		{
			score *= 2;
			m_nBombCounter--;	
		}

//		char table_info[10];
		//左边玩家得分信息;
//		sprintf(table_info,"%d",score);
//		pDraw->Draw_Text_GDI(table_info,300,300,RGB(255,0,0),500,"华文新魏",lpddsprimary);
//		Sleep(2000);
	}

	if( player == m_nCurrentLord )
	{
		switch(	m_nCurrentLord )
		{
		case 0:
			pLeftPlayer->m_nScore += score*2;
			pLeftPlayer->m_nWin++;

			pCenterPlayer->m_nScore -= score;	
			pCenterPlayer->m_nLose++;
			
			pRightPlayer->m_nScore  -= score;	
			pRightPlayer->m_nLose++;

			pDrawItem->GameScore(m_nCurrentLord,score*2,-score,-score);
			break;
		case 1:
			pCenterPlayer->m_nScore += score*2;
			pCenterPlayer->m_nWin++;

			pLeftPlayer->m_nScore -= score;	
			pLeftPlayer->m_nLose++;
			
			pRightPlayer->m_nScore  -= score;	
			pRightPlayer->m_nLose++;

			pDrawItem->GameScore(m_nCurrentLord,-score,score*2,-score);
			break;
		case 2:
			pRightPlayer->m_nScore += score*2;
			pRightPlayer->m_nWin++;

			pLeftPlayer->m_nScore -= score;	
			pLeftPlayer->m_nLose++;
			
			pCenterPlayer->m_nScore  -= score;	
			pCenterPlayer->m_nLose++;

			pDrawItem->GameScore(m_nCurrentLord,-score,-score,score*2);
			break;
		}
	}
	else
	{
		switch(	m_nCurrentLord )
		{
		case 0:
			pLeftPlayer->m_nScore -= score*2;
			pLeftPlayer->m_nLose++;

			pCenterPlayer->m_nScore += score;	
			pCenterPlayer->m_nWin++;
			
			pRightPlayer->m_nScore  += score;	
			pRightPlayer->m_nWin++;

			pDrawItem->GameScore(m_nCurrentLord,-score*2,score,score);
			break;
		case 1:
			pCenterPlayer->m_nScore -= score*2;
			pCenterPlayer->m_nLose++;

			pLeftPlayer->m_nScore += score;	
			pLeftPlayer->m_nWin++;
			
			pRightPlayer->m_nScore  += score;	
			pRightPlayer->m_nWin++;

			pDrawItem->GameScore(m_nCurrentLord,score,-score*2,score);
			break;
		case 2:
			pRightPlayer->m_nScore -= score*2;
			pRightPlayer->m_nLose++;

			pLeftPlayer->m_nScore += score;	
			pLeftPlayer->m_nWin++;
			
			pCenterPlayer->m_nScore  += score;	
			pCenterPlayer->m_nWin++;

			pDrawItem->GameScore(m_nCurrentLord,score,score,-score*2);
			break;
		}
	}
}
//比较当前牌是否为合法;			
int CGame::CompareCards()	
{
	//大小判断;
	if( pLeftCards->m_cDiscardingType.m_nTypeNum != 0 )
	{
		if(	pCenterCards->m_cDiscardingType.m_nTypeNum != 
			pLeftCards->m_cDiscardingType.m_nTypeNum )
		{
			if( pCenterCards->m_cDiscardingType.m_nTypeNum == 4 ) //炸弹;
			{
				return 1;	//合法;
			}
			else
			{
				return 0;  //不合法;
			}
		}
		else
		{	
			//补丁:
			if( pLeftCards->m_cDiscardingType.m_nTypeValue == 16 && 
				pLeftCards->m_cDiscardingType.m_nTypeNum == 1 )
			{
				if( pCenterCards->m_cDiscardingType.m_nTypeValue == 16 && //大王,可以出;
					pCenterCards->m_cChoosingCards[0].m_nColor == 1 )  
				{
					return 1;
				}
				else   //要不起;
				{
					return 0;
				}
			}
			//如果牌型相同;
			if( pCenterCards->m_cDiscardingType.m_nTypeValue > 
				pLeftCards->m_cDiscardingType.m_nTypeValue )
			{
				return 1;  //合法;
			}
			else
			{
				return 0; //不合法;
			}
		}
	}
	//如果左边玩家没出牌,则比较右边玩家;
	else if( pRightCards->m_cDiscardingType.m_nTypeNum != 0 )
	{
		if(	pCenterCards->m_cDiscardingType.m_nTypeNum != 
			pRightCards->m_cDiscardingType.m_nTypeNum )
		{
			if( pCenterCards->m_cDiscardingType.m_nTypeNum == 4 ) //炸弹;
			{
				return 1;	//合法;
			}
			else
			{
				return 0;  //不合法;
			}
		}
		else
		{	
			//补丁:
			if( pRightCards->m_cDiscardingType.m_nTypeValue == 16 && 
				pRightCards->m_cDiscardingType.m_nTypeNum == 1 )
			{
				if( pCenterCards->m_cDiscardingType.m_nTypeValue == 16 && //大王,可以出;
					pCenterCards->m_cChoosingCards[0].m_nColor == 1 )  
				{
					return 1;
				}
				else   //要不起;
				{
					return 0;
				}
			}
			//如果牌型相同;
			if( pCenterCards->m_cDiscardingType.m_nTypeValue > 
				pRightCards->m_cDiscardingType.m_nTypeValue )
			{
				return 1;  //合法;
			}
			else
			{
				return 0; //不合法;
			}
		}
	}
	else
	{
		m_nLordLock = 3;	
		return 1;
	}
	return -1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -