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

📄 gamemap.cpp

📁 纸牌源码
💻 CPP
字号:
#include "stdafx.h"
#include "gamemap.h"
#include "resource.h"
#include "time.h"
#include "tool.h"

#include "filereport.h"
//FILEREPORT f1("m1.txt");

#define FROM_REST 0
#define FROM_FINISH 1
#define FROM_COL 2

#define ISNORMAL(x) ((x)>=0 && (x)<52)
#define ISBACK(x) ((x)>=52 && (x)<104)

GAMEMAP::GAMEMAP()
{
	iLevel=0;
}

GAMEMAP::~GAMEMAP()
{
}

void GAMEMAP::SetDC(HDC hdest,HDC hsrc)
{
	hdcdest=hdest;
	hdcsrc=hsrc;
}

void GAMEMAP::Init(HINSTANCE hInstance)
{
	hPaperBack=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP_PAPER_BACK));
	hPaper=LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_BITMAP_PAPER));

	//hBrushEmpty=(HBRUSH)CreateSolidBrush(HS_CROSS,RGB(0,128,0));
	hBrushEmpty=(HBRUSH)GetStockObject(NULL_BRUSH);
	hback=(HBRUSH)CreateSolidBrush(RGB(0,128,0));
}


void GAMEMAP::Show()
{
	int i,j;
	int tempy,tempx;

	//背景	
	SelectObject(hdcdest,hback);
	Rectangle(hdcdest,0,0,GAMEWIDTH,GAMEHEIGHT);
	
	//左上角
	ShowRestPaper();

	//右上角
	ShowFinishPaper();
	
	//摆七列牌
	for(i=0;i<7;i++)
	{
		tempy=PAPER_Y;
		tempx=PAPER_X+i*(PAPERWIDTH + PAPER_BETWEEN_WIDTH);

		for(j=0;j<pColNum[i];j++)
		{
			if(pCol[i*20+j]<52)
			{
				if(!IsMove[pCol[i*20+j]])
				{
					DrawPaper(pCol[i*20+j],tempx,tempy);
					tempy+=PAPER_BETWEEN;
				}
			}
			else
			{
				DrawClosePaper(tempx,tempy);
				tempy+=PAPER_BACK_BETWEEN;			
			}
		}
	}

}

void GAMEMAP::SetPaper()
{
	int temppaper[52];
	int i,j,ipaper;
	int addr;

	//洗牌
	memset(temppaper,-1,sizeof(temppaper));
	srand(time(NULL));
	for(i=0;i<52;i++)
	{
		addr=rand()%52;
		while(temppaper[addr]!=-1)
		{
			addr+=3;
			addr%=52;
		}
		temppaper[addr]=i;
	}

	memset(pCol,-1,sizeof(pCol));
	ipaper=0;
	//摆七列牌
	for(i=0;i<7;i++)
	{
		//每列的数量
		pColNum[i]=i+1;
		for(j=0;j<=i;j++)
		{
			pCol[i*20+j]=temppaper[ipaper];
			ipaper++;
		}
	}
	memset(pColTopY,0,sizeof(pColTopY));
	for(i=0;i<7;i++)
	{
		pColTopY[i]=PAPER_Y + i*PAPER_BACK_BETWEEN;
	}

	//剩余的牌
	memset(pRest,-1,sizeof(pRest));
	for(i=0;ipaper<52;i++)
	{
		pRest[i]=temppaper[ipaper];
		ipaper++;
	}
	iRestNum=24;

	//初始化背面的牌,原牌值+52
	for(i=1;i<7;i++)
	{
		for(j=0;j<i;j++)
		{
			pCol[i*20+j]+=52;
		}
	}

	//
	iRestPaperNow=-1;
	memset(CatchPaper,-1,sizeof(CatchPaper));

	//右上角
	memset(pFinish,-1,sizeof(pFinish));	
	memset(pFinishNum,0,sizeof(pFinishNum));
	
	//移动状态标记数组
	memset(IsMove,0,sizeof(IsMove));	

	//过关动画
	memset(&aniwin,0,sizeof(aniwin));

	iShowBack=0;	
}

//牌的序号0-51
//背面朝上的牌52-103
void GAMEMAP::DrawPaper(int id,int x,int y)
{
	if(id<0 || id>51)
		return;

	if(0==iLevel)
	{
		if(id>=26)
		{
			id-=26;
		}
	}

	SelectObject(hdcsrc,hPaper);	
	BitBlt(hdcdest,x,y,PAPERWIDTH,PAPERHEIGHT,hdcsrc,
		(id%13)*PAPERWIDTH,(id/13)*PAPERHEIGHT,SRCCOPY);	
}

void GAMEMAP::DrawClosePaper(int x,int y)
{
	SelectObject(hdcsrc,hPaperBack);
	BitBlt(hdcdest,x,y,PAPERWIDTH,PAPERHEIGHT,hdcsrc,
		0,0,SRCCOPY);	
}

void GAMEMAP::DrawCatchPaper()
{
	int i;
	int tempx,tempy;

	tempx=moveposx-moveoffx;
	tempy=moveposy-moveoffy;
	for(i=0;i<13;i++)
	{
		if(-1==CatchPaper[i])
		{
			break;
		}
		DrawPaper(CatchPaper[i],tempx,tempy);
		tempy+=PAPER_BETWEEN;
	}
}

void GAMEMAP::LUPproc(int x,int y)
{
	int iCol,i;

	if(-1== CatchPaper[0])
	{
		//检测左上角,翻剩余的牌
		if(PointInRect(x,y,REST_X,REST_Y,PAPERWIDTH,PAPERHEIGHT))
		{
			GetOneRestPaper();			
			memset(CatchPaper,-1,sizeof(CatchPaper));
			return;
		}

		//检测是否翻开牌
		iCol=GetPutCol(x,y);
		if(iCol>=0 && iCol<7)
		{
			if(ISBACK(pCol[iCol*20+pColNum[iCol]-1]))
			{
				pCol[iCol*20+pColNum[iCol]-1]-=52;
			}
		}
	}
	else
	{
		//检查是否能放到下边七列中
		iCol=GetPutCol(x,y);
		if(iCol>=0 && iCol<7)
		{
			AddCol(iCol);			
		}
		else
		{
			//是否是右上角的四个格
			iCol=GetPutFinish(x,y);
			if(iCol>=0 && iCol<4)
			{
				AddFinish(iCol);					
			}
		}

		//清除当前移动的牌
		memset(CatchPaper,-1,sizeof(CatchPaper));
		//清除牌的移动状态
		memset(IsMove,0,sizeof(IsMove));
	}
}

void GAMEMAP::LDOWNproc(int x,int y)
{
	int iCol;
	int i;

	if(CatchPaper[0]!=-1)
	{
		//如果当前正在移动牌
		memset(CatchPaper,-1,sizeof(CatchPaper));
		return;
	}

	//检测拾取的牌
	if(PointInRect(x,y,REST_X+PAPERWIDTH + PAPER_BETWEEN_WIDTH,REST_Y,
		PAPERWIDTH,PAPERHEIGHT))
	{
		if(-1 !=iRestPaperNow)
		{
			memset(CatchPaper,-1,sizeof(CatchPaper));
			CatchPaper[0]=pRest[iRestPaperNow];	
			//
			moveposx=x;
			moveposy=y;
			moveoffx=x-REST_X-PAPERWIDTH-PAPER_BETWEEN_WIDTH;
			moveoffy=y-REST_Y;

			//from
			ipaperfrom=FROM_REST;
		}		
	}
	else
	{
		//从右上角取牌
		iCol=GetPutFinish(x,y);
		if(iCol>=0 && iCol<4)
		{
			if(0 == pFinishNum[iCol])
				return;

			memset(CatchPaper,-1,sizeof(CatchPaper));
			CatchPaper[0]=pFinish[iCol*13+pFinishNum[iCol]-1];

			moveposx=x;
			moveposy=y;
			moveoffx=x-REST_X-(iCol+3)*(PAPERWIDTH+PAPER_BETWEEN_WIDTH);
			moveoffy=y-REST_Y;

			ipaperfrom=FROM_FINISH;

		}
		else
		{
			GetPickCol(x,y);			
		}
	}

	//设置移动的牌的状态
	for(i=0;i<13;i++)
	{
		if(-1 == CatchPaper[i])
		{
			break;
		}
		else
		{
			IsMove[CatchPaper[i]]=1;
		}
	}
}

//移动拾取的牌
void GAMEMAP::LMOVEproc(int x,int y)
{
	if(-1==CatchPaper[0])
	{
		//没有拾取的牌
		return;
	}

	moveposx=x;
	moveposy=y;
}
//左上角弹出的牌
void GAMEMAP::ShowRestPaper()
{
	int i;

	//画背面的图案
	SelectObject(hdcsrc,hPaperBack);
	if(0==iRestNum || iRestNum-1==iRestPaperNow)
	{
		//已经取到最后一张牌
		//没有剩余的牌
		BitBlt(hdcdest,REST_X,REST_Y,PAPERWIDTH,PAPERHEIGHT,hdcsrc,PAPERWIDTH,0,SRCCOPY);
	}
	else
	{
		BitBlt(hdcdest,REST_X,REST_Y,PAPERWIDTH,PAPERHEIGHT,hdcsrc,0,0,SRCCOPY);
	}

	//显示当前翻出的牌
	for(i=0;i<=iRestPaperNow;i++)
	{
		if(!IsMove[pRest[i]])
		{
			DrawPaper(pRest[i],REST_X+PAPERWIDTH + PAPER_BETWEEN_WIDTH,REST_Y);
		}
	}
}

void GAMEMAP::GetOneRestPaper()
{
	if(iRestNum<=0)
	{
		return;
	}

	//依次从剩余的牌中,找出一张
	if(-1==iRestPaperNow)
	{
		iRestPaperNow=0;
	}
	else
	{
		iRestPaperNow++;
		//下标最大
		if(iRestPaperNow>23 || pRest[iRestPaperNow]==-1)
		{
			iRestPaperNow=-1;
		}
	}
}

void GAMEMAP::ClearPaper()
{
	int i,j;

	switch(ipaperfrom)
	{
	case FROM_REST:
		pRest[iRestPaperNow]=-1;
		//从剩余牌中取出
		for(i=iRestPaperNow;i<23;i++)
		{
			pRest[i]=pRest[i+1];
		}
		pRest[23]=-1;

		iRestPaperNow--;
		iRestNum--;
		break;

	case FROM_FINISH:
		//从完成的牌中取出
		for(i=0;i<52;i++)
		{
			if(pFinish[i]==CatchPaper[0])
			{
				pFinish[i]=-1;
				pFinishNum[i/13]--;
				break;
			}
		}		
		break;

	case FROM_COL:
		//从下边的牌中取出
		i=iColFrom*20;
		while(pCol[i]!=CatchPaper[0] )
		{
			i++;
		}

		//找到该列
		for(j=0;j<13;j++)
		{
			if(-1 == CatchPaper[j])
				break;
			pCol[i]=-1;					
			pColNum[i/20]--;
			pColTopY[i/20] -= PAPER_BETWEEN;	
			i++;	
		}	
		break;
	}
	
}

//放到哪一列中
int GAMEMAP::GetPutCol(int x,int y)
{
	int iCol,tempy;
	int i;
	int iback=0;
	int inormal=0;
	
	//放到下边的七列中
	iCol=(x-PAPER_X )/(PAPERWIDTH +PAPER_BETWEEN_WIDTH );
	if(iCol>=0 && iCol<7)
	{
		if(x-PAPER_X-iCol*(PAPERWIDTH +PAPER_BETWEEN_WIDTH) > PAPERWIDTH )
		{
			iCol=-1;
		}
		else
		{
			tempy=PAPER_Y;
			for(i=0;i<pColNum[iCol];i++)
			{
				if(ISBACK(pCol[20*iCol+i]))
				{
					tempy+=PAPER_BACK_BETWEEN;
				}
				else
				{
					tempy+=PAPER_BETWEEN ;
				}
			}
			if(y<tempy || y>tempy+PAPERHEIGHT )
			{
				iCol=-1;				
			}		
		}
	}
	else
	{
		iCol=-1;	
	}
	return iCol;
}

//右上角
int GAMEMAP::GetPutFinish(int x,int y)
{
	int iCol;
	
	iCol=(x-PAPER_X-3*(PAPERWIDTH +PAPER_BETWEEN_WIDTH) )
		/(PAPERWIDTH +PAPER_BETWEEN_WIDTH );
	if(iCol>=0 && iCol<4)
	{
		if(x-PAPER_X-3*(PAPERWIDTH +PAPER_BETWEEN_WIDTH)
			-iCol*(PAPERWIDTH +PAPER_BETWEEN_WIDTH) > PAPERWIDTH )
		{
			iCol=-1;
		}
		else
		{
			if(y<REST_Y || y>REST_Y+PAPERHEIGHT )
			{
				iCol=-1;				
			}		
		}
	}
	else
	{
		iCol=-1;	
	}
	return iCol;
}

void GAMEMAP::ShowFinishPaper()
{
	int i,j;
	int tempx;

	tempx=PAPER_X+3*(PAPERWIDTH + PAPER_BETWEEN_WIDTH);
	for(i=0;i<4;i++)
	{	
		SelectObject(hdcdest,hBrushEmpty);
		Rectangle(hdcdest,
			tempx,
			REST_Y,
			tempx+PAPERWIDTH,
			REST_Y + PAPERHEIGHT);
		
		for(j=12;j>=0;j--)
		{
			if(pFinish[i*13+j]!=-1 && !IsMove[pFinish[i*13+j]]	)
				break;
		}
		if(j>=0 && j<13)
		{
			DrawPaper(pFinish[i*13+j],tempx,REST_Y);
		}

		tempx+=PAPERWIDTH + PAPER_BETWEEN_WIDTH;
	}
}


int GAMEMAP::AddFinish(int icol)
{
	int i=0;
	int ivalue,ikind,ikind2;

	//右上角的牌不能互相移动
	if(ipaperfrom == FROM_FINISH)
		return 0;

	//移动的牌多于1张返回
	if(CatchPaper[1]!=-1)
	{
		return 0;
	}	

	//当前已经放满了十三张牌,返回零
	while(i<13 && pFinish[icol*13+i]!=-1 )
	{
		i++;
	}
	if(i>=13)
	{
		return 0;
	}

	if(i>0)
	{
		if(0==iLevel)
		{
			//初级,只区分两种花色
			ikind=(pFinish[icol*13+i-1]/13)%2;
			ikind2=(CatchPaper[0]/13)%2;
		}
		else
		{
			ikind=pFinish[icol*13+i-1]/13;
			ikind2=CatchPaper[0]/13;
		}
		if(ikind!=ikind2)
		{
			return 0;
		}

		ivalue=pFinish[icol*13+i-1]%13;
		//每张牌递增
		if(ivalue!=CatchPaper[0]%13-1)
			return 0;
	}
	else
	{
		//第一张牌是A
		if(CatchPaper[0]%13 != 0)
			return 0;
	}

	pFinish[icol*13+i]=CatchPaper[0];
	//设置数量
	pFinishNum[icol]++;

	ClearPaper();
	return 1;
}

int GAMEMAP::AddCol(int iCol)
{
	int i,ikind,ivalue;

	//如果移动前后属于同一列
	if( ipaperfrom == FROM_COL && iColFrom == iCol  )
		return 0;

	//该列最上面的牌是背面朝上
	if(0!=pColNum[iCol])
	{
		if( ISBACK(pCol[iCol*20+pColNum[iCol]-1]))
			return 0;

		//ikind 0 红 1黑
		ikind= (pCol[iCol*20+pColNum[iCol]-1]/13)%2;
		if(ikind == (CatchPaper[0]/13)%2 )
			return 0;

		//每张牌递减
		ivalue=pCol[iCol*20+pColNum[iCol]-1]%13;
		if(ivalue != CatchPaper[0]%13 + 1 )
			return 0;
	}
	else
	{
		//空的列只能放k
		if(CatchPaper[0]%13 != 12 )
			return 0;
	}

	for(i=0;i<13;i++)
	{
		if(CatchPaper[i]==-1)
		{
			break;
		}
		pCol[iCol*20+pColNum[iCol]] = CatchPaper[i];
		pColNum[iCol]++;
		pColTopY[iCol] += PAPER_BETWEEN;
	}

	ClearPaper();	
	return 1;
}

void GAMEMAP::GetPickCol(int x,int y)
{
	int i,iCol,tempy,iPick;

	//从下边的七列中取牌
	iCol=(x-PAPER_X )/(PAPERWIDTH +PAPER_BETWEEN_WIDTH );
	if(iCol>=0 && iCol<7)
	{
		if(x-PAPER_X-iCol*(PAPERWIDTH +PAPER_BETWEEN_WIDTH) > PAPERWIDTH )
		{
			iCol=-1;
		}		
	}
	else
	{
		iCol=-1;	
	}

	if(-1== iCol)
		return;

	//判断纵坐标
	if(iCol>=0 && iCol<7)
	{	
		tempy=PAPER_Y;
		iPick=-1;
		for(i=0;i<pColNum[iCol];i++)
		{
			if(!ISNORMAL(pCol[iCol*20+i]))
			{
				tempy+=PAPER_BACK_BETWEEN;
				continue;
			}
			if(i==pColNum[iCol]-1)
			{
				if(y>tempy && y<(tempy+ PAPERHEIGHT ) )
				{
					iPick=i;
					break;
				}
			}
			else
			{
				if(y>tempy && y<(tempy+ PAPER_BETWEEN  ) )
				{
					iPick=i;
					break;
				}
			}	

			tempy+=PAPER_BETWEEN;
		}

		//如果当前有牌
		//如果牌正面朝上
		if(iPick>=0 &&  iPick<pColNum[iCol])
		{
			memset(CatchPaper,-1,sizeof(CatchPaper));
			i=0;
			while(iPick < pColNum[iCol])
			{
				CatchPaper[i]=pCol[iCol*20+iPick];
				iPick++;
				i++;
			}
			
			ipaperfrom=FROM_COL;
			iColFrom=iCol;
		}
	}

	//
	moveposx=x;
	moveposy=y;
	moveoffx=x-PAPER_X -iCol*(PAPERWIDTH+PAPER_BETWEEN_WIDTH);
	moveoffy=y-tempy;
}

int GAMEMAP::CheckWin()
{
	int i;
	for(i=0;i<4;i++)
	{
		if(pFinish[i*13+12]==-1)
			return 0;
	}

	return 1;	
}

void GAMEMAP::ShowWin()
{	
	if(!aniwin.iStart)
		return;
	DrawPaper(aniwin.id,aniwin.x,aniwin.y);

	//扑克牌的弹跳
	aniwin.x+=aniwin.xoff;
	aniwin.y+=aniwin.yoff;
	if(aniwin.yoff>0)
	{
		aniwin.yoff+=2;
	}
	else if(aniwin.yoff<0)
	{
		aniwin.yoff+=2;
		if(aniwin.yoff>=0)
		{
			aniwin.yoff=5;
		}
	}
	else
	{
		
		
	}

	if(aniwin.x<-PAPERWIDTH || aniwin.x>GAMEWIDTH)
	{
		//下一张牌
		aniwin.i++;
		if(aniwin.i>3)
		{
			aniwin.i=0;
			aniwin.j--;
			if(aniwin.j<0)
			{
				aniwin.iStart=0;//动画结束
			}				
		}
		aniwin.id=pFinish[aniwin.i*13+aniwin.j];
		aniwin.x=PAPER_X+(3+aniwin.i)*(PAPERWIDTH + PAPER_BETWEEN_WIDTH);
		aniwin.y=REST_Y;
		aniwin.xoff=-10+(rand()%10)*2;
		if(0==aniwin.xoff)
			aniwin.xoff=-3;
		aniwin.yoff=5;
	}

	if(aniwin.y>GAMEHEIGHT-PAPERHEIGHT )
	{
		aniwin.y=GAMEHEIGHT-PAPERHEIGHT;

		if(aniwin.yoff>=0 && aniwin.yoff<=10)
		{
			aniwin.yoff=0;			
		}
		else
		{
			aniwin.yoff/=2;
			aniwin.yoff=-aniwin.yoff;
		}
	}
}

void GAMEMAP::ShowWinStart()
{	
	aniwin.iStart=1;
	aniwin.i=0;
	aniwin.j=12;
	aniwin.id=pFinish[aniwin.i*13+aniwin.j];	
	aniwin.x=PAPER_X+(3+aniwin.i)*(PAPERWIDTH + PAPER_BETWEEN_WIDTH);
	aniwin.y=REST_Y;
	aniwin.xoff=-3;
	aniwin.yoff=5;
}

void GAMEMAP::SetLevel(int i)
{
	iLevel=i;
}

void GAMEMAP::ClearCatchPaper()
{
	//清除当前移动的牌
	memset(CatchPaper,-1,sizeof(CatchPaper));
	//清除牌的移动状态
	memset(IsMove,0,sizeof(IsMove));
}

//显示背面的牌
void GAMEMAP::ShowBack()
{
	int i,j,id;
	int tempx,tempy;

	if(!iShowBack)
		return;

	tempx=PAPER_X+PAPER_BETWEEN_WIDTH+PAPERWIDTH ;
	SelectObject(hdcsrc,hPaper);	
	for(i=1;i<7;i++)
	{
		tempy=PAPER_Y -PAPER_BETWEEN ;
		for(j=0;j<20;j++)
		{
			id=pCol[i*20+j];

			if(!ISBACK(id))
				break;

			//得到这张背面牌的牌值
			id-=52;
			if(0==iLevel)
			{
				if(id>=26)
				{
					id-=26;
				}
			}

			BitBlt(hdcdest,tempx+j*11,tempy,14,PAPER_BETWEEN ,hdcsrc,
				(id%13)*PAPERWIDTH,(id/13)*PAPERHEIGHT,SRCCOPY);
			tempy+=PAPER_BACK_BETWEEN;
		}
		
		tempx+=PAPER_BETWEEN_WIDTH+PAPERWIDTH ;
	}
}

void GAMEMAP::SetShowBack(int i)
{
	iShowBack=i;
}

⌨️ 快捷键说明

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