win32游戏开发(2) --连连看游戏制作(vc++版)

文章索引

    • 源代码下载
    • 工程目录一览
    • 实现细节

源代码下载

附上下载链接:连连看vc++版源代码

工程目录一览

文件功能及关系图:
GameEngine类

成员名 作用
static GameEngine * m_pGameEngine 指向自身的指针,供外界程序访问
HINSTANCE m_hInstance 实例句柄
HWND m_hWnd 窗口句柄
TCHAR m_szWindowClass[32] 窗口类名
TCHAR m_szWndTitle[32] 窗口标题
int m_iWidth,m_iHeight 窗口宽高
int m_iFrameDelay 调节游戏帧数
bool start_sign 游戏开始标记
函数名 功能
GameEngine(HINSTANCE hInstance,LPTSTR szWindowClass,LPTSTR szTitle,int iWidth,int iHeight,int iDelay) 构造函数创建游戏实例
static GameEngine* GetEngine() 返回成员 *m_pGameEngine
HINSTANCE GetInstance() 返回成员 m_hInstance
HWND GetWnd() 返回成员 m_hWnd
void SetWnd(HWND hWnd) 赋值给 m_hWnd
LPTSTR GetTitle() 返回成员 m_szWndTitle
int GetWidth() 返回成员 m_iWidth
void SetWidth(int iWidth) 赋值给 m_iWidth
int GetHeight() 返回成员 m_iHeight
void SetHeight(int iHeight) 赋值给 m_iHeight
int GetDelay() 返回成员 m_iFrameDelay
void SetDelay(int iDelay) 赋值给 m_iFrameDelay
void setStart(bool sign) 赋值给 start_sign
bool getStart() 返回成员start_sign
BOOL Initiallize(int cmdShow) 创建窗口
LRESULT HandleEvent(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) 消息处理

GameEgine核心函数(不是GameEngine类函数)

函数名 功能
BOOL GameInitial(HINSTANCE hInstance) 创建GameEgine类对象
void GameStartBg() 绘制游戏初始画面(游戏界面)
void setDffclt(int difficult) 设置游戏难度
void GameStart() 绘制游戏初始画面(开始游戏画面)
void LButtonDown(int x,int y) 鼠标单击触发函数
void GameEnd() 游戏结束相关操作
void GamePaint() 游戏重绘
void GameCycle() 游戏循环
bool IsResult() 判断初始化后的2维数组是否有解
void set_clue_sign(bool sign) 设置提示标志
bool IsTimeEnd() 判断时间是否已经用完(倒计时)
void playSound(int s_sort) 播放音乐
void setSound(int s_sort) 选择音乐

针对连连看设置的全局常量

宏定义 常量值 作用
row 16 地图行数
col 17 地图列数
BLANK_STATE -2 用于判断是否加边框(选中加边框,再次点击不加,)
EASY 1 简单难度
NORMAL 2 中等难度
HARD 3 困难难度

针对连连看游戏设置的变量(声明在llk.h)

变量名 作用
int map[row][col] 保存图片位置的2维数组(在数组中-1为有图片(之后会赋值),0为无图片)
int num 方块总个数
int sort_num[39] 39个图形,每种图形4个
int sort_place[39][16] 记录图形位置,即每种图片4个,位置表示(举例)[1][0]和[1][1]表示行坐标(十位和个位),[1][2]和[1][3]表示列坐标
POINT p1,p2 记录选中的两个方块位置
bool fram_sign 绘画边框标志,true为有边框,false为无边框
int clue_x1,clue_y1,clue_x2,clue_y2 用于提示的一对方块(能消掉的)
bool clue_sign 提示标志
long int score 分数
int game_time 游戏时间

针对连连看游戏设置的函数

函数名 功能
void SortPlace(int p_sort,int p_sort_num,int p_row,int p_col) 记录图片放置位置
void temp_SortPlace(int p_sort,int p_sort_num,int p_row,int p_col) 临时记录图片放置位置
void initial() 初始化游戏变量
void ReInitial() 重新初始化游戏变量
void clue() 提示边框
void set_clue_sign(bool sign) 设置提示标志
void PaintFrame(int g_left,int g_right,int g_top,int g_bottom,int c_index,int r_index) 方块外框绘制,线条环绕绘制框架
bool IsLink(int x1, int y1, int x2, int y2) 判断选中的两个方块是否可以连接
bool X1_Link_X2(int x,int y1,int y2) X直连
bool Y1_Link_Y2(int x1,int x2,int y) Y直连
bool OneCornerLink(int x1,int y1,int x2,int y2) 判断是否只有一个拐角
bool TwoCornerLink(int x1,int y1,int x2,int y2) 判断是否有两个拐角
bool X_Link(int x,int y1,int y2) 判断有拐角是否能x直连
bool Y_Link(int x1,int x2,int y) 判断有拐角是否能y直连
void playStartSound() 播放游戏开始音乐
bool end(int n) 判断游戏是否结束
void paintInfo() 显示信息

实现细节

在具体实现每一个函数之前,首先要清楚的是应该在哪些地方调用这些函数.因此我们不妨跟随着游戏运行时的执行顺序对这些函数进行放置,并对函数进行定义.
首先是winmain部分:

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hpreInstance,LPSTR lpcmdline,int iShowCmd)
{
  MSG msg;
  static int iticktrigger=0;//设为开始时间0ms
  int itickcount;
  if(!GameInitial(hInstance))//创建GameEngine类对象g_pGame
     return 0;
  if(!GameEngine::GetEngine()->Initiallize(SW_SHOWNORMAL))//对窗口类对象wndclass进行赋值并注册,创建窗口
     return 0;
  ::ZeroMemory(&msg,sizeof(msg));
    GameStartBg();//绘制游戏背景
  while(msg.message!=WM_QUIT)
  {
	  if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	  {
		  ::TranslateMessage(&msg);
		  ::DispatchMessage(&msg);
	  }
	  else
	  {
		  ::Sleep(1);
		  itickcount=::GetTickCount();//返回从程序开始到现在的执行ms数
		  if(itickcount-iticktrigger>0)
		  {		 
			 if(GameEngine::GetEngine()->getStart() == true)//如果获取到的start_sign为真,开始游戏
			 {
				GamePaint();//游戏重绘
				GameCycle();//游戏循环
				iticktrigger= itickcount+GameEngine::GetEngine()->GetDelay();//设置下一次重绘时间
			 }
		  }
	  }
  }
  return TRUE;

}

对winmain中出现的未定义函数进行定义:

BOOL GameInitial(HINSTANCE hInstance)
{
   g_pGame=new GameEngine(hInstance,"MYCLASS","连连看 v1.0",960,600,delay);
   if(g_pGame==NULL)
	   return FALSE;
   return TRUE;
}

GameEngine::GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle, 
					  int iWidth, int iHeight,int iDelay)
{
  m_pGameEngine=this;
  m_hInstance=hInstance;
  m_hWnd=NULL;
  if(lstrlen(szWindowClass)>0)
	  lstrcpy(m_szWindowClass,szWindowClass);
  if(lstrlen(szTitle)>0)
	  lstrcpy(m_szWndTitle,szTitle);
  m_iWidth=iWidth;
  m_iHeight=iHeight;
  m_iFrameDelay=iDelay;
  start_sign = false;
}

BOOL GameEngine::Initiallize(int icmdShow)
{
  static WNDCLASS wndclass;
  wndclass.hInstance=m_hInstance;
  wndclass.lpszClassName=m_szWindowClass;
  wndclass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
  wndclass.style=CS_HREDRAW|CS_VREDRAW;
  wndclass.lpfnWndProc=WndProc;
  wndclass.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
  if(!RegisterClass(&wndclass))
	  return FALSE;
m_hWnd=CreateWindow(m_szWindowClass,m_szWndTitle,WS_OVERLAPPEDWINDOW,150,50,m_iWidth,m_iHeight,NULL,NULL,m_hInstance,NULL);
  if(!m_hWnd)
	  return FALSE;
  SendMessage(m_hWnd,WM_SETICON,(WPARAM)TRUE,(LPARAM)LoadIcon(GetModuleHandle(NULL),(LPCTSTR)IDI_ICON1));
  ::ShowWindow(m_hWnd,icmdShow);
  ::UpdateWindow(m_hWnd);	 
  return TRUE;
}

void GameStartBg()
{   
	HWND hwnd = g_pGame->GetWnd();
	dc = ::GetDC(hwnd);
	bufdc = ::CreateCompatibleDC(dc);
	mdc = ::CreateCompatibleDC(dc);
	mid = ::CreateCompatibleBitmap(dc,960,600);

	bg = (HBITMAP)::LoadImage(NULL,"./image/bg.bmp",IMAGE_BITMAP,960,600,LR_LOADFROMFILE);	//加载背景图片
	::SelectObject(mdc,bg);
	::BitBlt(dc,0,0,960,600,mdc,0,0,SRCCOPY);

	::ReleaseDC(hwnd,bufdc);
	::ReleaseDC(hwnd,mdc);
}

void GamePaint()
{
	HWND hwnd = g_pGame->GetWnd();
	int i,j,m;
	//重绘背景
	::SelectObject(bufdc,game_bg);
	::BitBlt(mdc,0,0,960,600,bufdc,0,0,SRCCOPY);
	//重绘游戏区
	for(i = 0;i < row;i++)
	{
		for(j = 0;j < col;j++)
		{
			::ReleaseDC(hwnd,bufdc);
			for(m = 1;m <= 39;m++)
			{
				if(map[i][j] == m)
				{
					::SelectObject(bufdc,pic[m-1]);
					::BitBlt(mdc,game_left+j*31-2*31,game_top+i*34-2*34,31,34,bufdc,0,0,SRCCOPY);
				}
			}
		}
	}
	//绘制边框
	if(fram_sign == true)
		PaintFrame(game_left,game_right,game_top,game_bottom,g_col_index,g_row_index);//绘制矩形边框
	if(clue_sign == true)
		clue();//绘制提示框
	//显示信息
	paintInfo();
	::BitBlt(dc,0,0,960,600,mdc,0,0,SRCCOPY);
	::ReleaseDC(hwnd,bufdc);
	::ReleaseDC(hwnd,mdc);
}

//方块外框绘制,线条环绕绘制框架
void PaintFrame(int g_left,int g_right,int g_top,int g_bottom,int c_index,int r_index)
{
	HWND hwnd = g_pGame->GetWnd();	

	::SelectObject(mdc,pen);

	::MoveToEx(mdc,g_left+c_index*31,g_top+r_index*34,NULL);
	::LineTo(mdc,g_left+c_index*31+31,g_top+r_index*34);
	::LineTo(mdc,g_left+c_index*31+31,g_top+r_index*34+34);
	::LineTo(mdc,g_left+c_index*31,g_top+r_index*34+34);
	::LineTo(mdc,g_left+c_index*31,g_top+r_index*34);
}

//提示边框
void clue()
{
	fram_sign = false;
	//方块外框绘制,线条环绕绘制框架
	PaintFrame(game_left,game_right,game_top,game_bottom,clue_y1,clue_x1);		
	PaintFrame(game_left,game_right,game_top,game_bottom,clue_y2,clue_x2);
}
//显示信息
void paintInfo()
{
	char s_level[20]={0};
	char s_score[20]={0};
	char s_time[20]={0};
	if( difficult == EASY)
		::TextOut(mdc,100,34*2,"级别: 简单",10);
	else if( difficult == NORMAL)
		::TextOut(mdc,100,34*2,"级别: 中等",10);
	else if( difficult == HARD)
		::TextOut(mdc,100,34*2,"级别: 难",8);
	::sprintf(s_score,"得分: %d",score);
	::sprintf(s_time,"剩余时间: %d",game_time);
   	::TextOut(mdc,100,34*2+25,s_score,strlen(s_score));
	::TextOut(mdc,100,34*2+50,s_time,strlen(s_time));
	::TextOut(mdc,100,34*2+75+50,"“空格”键: 提示!",18);
}	

void GameCycle()
{
    
}

接下来是最重要的消息机制设置,

LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
   return GameEngine::GetEngine()->HandleEvent(hWnd,msg,wParam,lParam);
}

对于HandleEvent(hWnd,msg,wParam,lParam)的定义:

LRESULT GameEngine::HandleEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  int m,x,y;
  switch(msg)
  {
  case WM_SYSCOMMAND:							//使最大化失效
      if(wParam == SC_MAXIMIZE)   
         return 0;   
      break;;
  case WM_COMMAND:
	  {
		m = LOWORD(wParam);
		switch(m)
		{
		case ID_EASY:							//处理菜单“简单”事件
			start_sign = true;
			setDffclt(1);
			GameStart();
			::SetTimer(m_hWnd,1,1000,NULL);
			break;
		case ID_NORMAL:							//处理菜单“正常”事件
			start_sign = true;
			setDffclt(2);
			GameStart();
			::SetTimer(m_hWnd,1,1000,NULL);
			break;
		case ID_HARD:							//处理菜单“难”事件
			start_sign = true;
			setDffclt(3);
			GameStart();
			::SetTimer(m_hWnd,1,1000,NULL);
			break;
		case ID_EXIT:							//处理菜单“退出”事件
			::PostQuitMessage(0);
			break;
		case ID_SOUND0:							//处理菜单“音乐1”事件
			setSound(0);
			break;
		case ID_SOUND1:							//处理菜单“音乐2”事件
			setSound(1);
			break;
		case ID_SOUND2:							//处理菜单“音乐3”事件
			setSound(2);
			break;
		case ID_HELP1:							//处理菜单“帮助”事件		
			::MessageBox(hWnd," 操作说明:\n1. 选择“音乐”\n2. 选择游戏难度进行游戏(默认是音乐1)\n\n按键说明:\n1. “空格”键将会有提示出现\n3.选择“退出”,退出整个游戏\n","说明",MB_OK);
			break;
		case ID_ABOUT1:							//处理菜单“关于”事件
			::MessageBox(hWnd,"版本:\t连连看 v1.0","关于",MB_OK);
			break;
		}
	  }
	  break;
  case WM_TIMER:								//响应定时器
	  if( IsTimeEnd() )
		  start_sign = false;
	  break;
  case WM_CHAR:
	  switch(wParam)
	  {
	  case ' ':									//处理“空格”事件
		  set_clue_sign(true);
		  break;
	  }
	  break;
  case WM_LBUTTONDOWN:							//处理鼠标左键单击事件
	  x = LOWORD(lParam);
	  y = HIWORD(lParam);
	  LButtonDown(x,y);
	  break;
  case WM_DESTROY:
	   GameEnd();
	   ::PostQuitMessage(0);
	   return 0;
  }
  return ::DefWindowProc(hWnd,msg,wParam,lParam);
}

对在消息机制出现的未定义函数进行定义:

void setDffclt(int n)
{
	difficult = n;
	if(n == EASY)            //简单
		game_time = 180;
	if(n == NORMAL)			 //中等
		game_time = 120;
	if(n == HARD)			 //难
		game_time = 60;
}

void GameStart()
{
	HWND hwnd = g_pGame->GetWnd();//获取窗口句柄m_hWnd
	RECT rect;
	char s[16];
	int i,j,m;
	//载入方块图片
	for(i = 0;i < 39;i++)
	{
		sprintf(s,"./image/%d.bmp",i+1);
		pic[i] = (HBITMAP)::LoadImage(NULL,s,IMAGE_BITMAP,31,34,LR_LOADFROMFILE);
	}
	initial();			//初始化
	IsResult();			//判断是否有解
	playStartSound();	//播放开始音乐
	dc = ::GetDC(hwnd);
	bufdc = ::CreateCompatibleDC(dc);
	mdc = ::CreateCompatibleDC(dc);
	mid = ::CreateCompatibleBitmap(dc,960,600);
	::SelectObject(mdc,mid);
	//绘制背景
	game_bg = (HBITMAP)::LoadImage(NULL,"./image/GameBg.bmp",IMAGE_BITMAP,960,600,LR_LOADFROMFILE);
	::SelectObject(bufdc,game_bg);
	::BitBlt(mdc,0,0,960,600,bufdc,0,0,SRCCOPY);
	//绘制游戏区
	::GetClientRect(hwnd,&rect);
	game_left = int((rect.left+rect.right)/2-6.5*31);
	game_right = int((rect.left+rect.right)/2+6.5*31);
	game_top = int((rect.bottom+rect.top)/2-6*34);
	game_bottom = int((rect.bottom+rect.top)/2+6*34);
	for(i = 0;i < row;i++)
	{
		for(j = 0;j < col;j++)
		{
			::ReleaseDC(hwnd,bufdc);
			for(m = 1;m <= 39;m++)
			{
				if(map[i][j] == m)
				{
					::SelectObject(bufdc,pic[m-1]);
					::BitBlt(mdc,game_left+j*31-2*31,game_top+i*34-2*34,31,34,bufdc,0,0,SRCCOPY);
					break;
				}
			}
		}
	}
	::BitBlt(dc,0,0,960,600,mdc,0,0,SRCCOPY);
	::ReleaseDC(hwnd,bufdc);
	::ReleaseDC(hwnd,mdc);
}

void initial()
{
	srand((unsigned)time(NULL));
	int i,j;
	int sort;
	score = 0;
	p1.x = BLANK_STATE;
	p1.y = BLANK_STATE;
	p2.x = BLANK_STATE;
	p2.y = BLANK_STATE;
	pen = ::CreatePen(PS_SOLID,3,RGB(255,0,0));
	fram_sign = false;
	clue_sign = false;
	//清空map二维数组
	for(i = 0;i < row-4;i++)						
	{
		for(j = 0;j < col-4;j++)
			map[i+2][j+2] = -1;
	}	

	//初始化sort_num数组
	for(i = 0;i < 39;i++)							
		sort_num[i] = 0;
	//初始化sort_place二维数组
	for(i = 0;i < 39;i++)							
	{
		for(j = 0;j < 16;j++)
			sort_place[i][j] = -1;
	}

	//初始化map二维数组
	for(i = 0;i < row;i++)							
	{
		for(j = 0;j < col;j++)
		{
			if(map[i][j] == -1)
			{
				while(1)
				{
					sort = rand()%39+1;									//产生随机数

					if(sort_num[sort - 1]<4)
					{
						map[i][j] = sort;								//放进地图中
						sort_num[sort - 1]++;							//该种图片数量加1
						num++;											//方块总个数加1
						SortPlace(sort,sort_num[sort-1],i-2,j-2);		//记录图片放置位置
						break;
					}
				}
			}
		}
	}
}

//记录图片放置位置
void SortPlace(int p_sort,int p_sort_num,int p_row,int p_col)
{	
	if(p_row < 10)
	{
		sort_place[p_sort-1][p_sort_num*4-4] = 0;				//一位数的话将十位补0
		sort_place[p_sort-1][p_sort_num*4-3] = p_row;			//取个位
	}
	else
	{
		sort_place[p_sort-1][p_sort_num*4-4] = p_row/10;		//取十位
		sort_place[p_sort-1][p_sort_num*4-3] = p_row%10;		//取个位
	}

	if(p_col < 10)
	{
		sort_place[p_sort-1][p_sort_num*4-2] = 0;				//一位数的话将十位补0
		sort_place[p_sort-1][p_sort_num*4-1] = p_col;			//取个位
	}
	else
	{
		sort_place[p_sort-1][p_sort_num*4-2] = p_col/10;		//取十位
		sort_place[p_sort-1][p_sort_num*4-1] = p_col%10;		//取个位
	}
}

//判断是否有解
bool IsResult()
{
	int i,j,m,n;
	POINT pp[4];

	//取出对应种类方块的位置
	for(i = 0;i < 39;i++)
	{
		for(j = 0;j < 16;j+=4)				
		{
			pp[j/4].x = sort_place[i][j]*10 + sort_place[i][j+1];
			pp[j/4].y = sort_place[i][j+2]*10 + sort_place[i][j+3];
		}

		//两两比较,判断是否存在能连通的方块
		for(m = 0;m < 3;m++)
		{
			for(n = m+1;n < 4;n++)
			{
				if( IsLink(pp[m].x,pp[m].y,pp[n].x,pp[n].y) )
				{
					clue_x1 = pp[m].x;
					clue_y1 = pp[m].y;
					clue_x2 = pp[n].x;
					clue_y2 = pp[n].y;
					return true;
				}
			}
		}
	}
	::MessageBox(NULL,"无解,将重列","提醒",MB_OK);
	return false;
}

bool IsLink(int x1, int y1, int x2, int y2)
{
	//X直连
	if(x1 == x2)
	{
		if( X1_Link_X2(x1,y1,y2) )
			return true;
	}

	//Y直连
	if( y1 == y2 )
	{
		if( Y1_Link_Y2(x1,x2,y1) )
			return true;
	}

	//一个拐角
	if( OneCornerLink(x1,y1,x2,y2) )
		return true;

	//两个拐角
	if( TwoCornerLink(x1,y1,x2,y2) )
		return true;

	return false;
}

//一个拐角					
bool OneCornerLink(int x1,int y1,int x2,int y2)
{
	if( X_Link(x1,y1,y2) && Y_Link(x2,x1,y2) )			//检测拐点1
		return true;
	else if( X_Link(x2,y2,y1) && Y_Link(x1,x2,y1) )		//检测拐点2
		return true;
	return false;
}
		
//两个拐角						
bool TwoCornerLink(int x1,int y1,int x2,int y2)
{
	int i;
	int aa;
	for(i = y1+1;i <= col-4;i++)			//右检测
	{
		aa=map[x1+2][i+2];
		if(map[x1+2][i+2] > 0)
		{
			break;
		}
		if( OneCornerLink(x1,i,x2,y2) )
			return true;
	}
	for(i = x1+1;i <= row-4;i++)			//下检测
	{
		aa=map[i+2][y1+2];
		if(map[i+2][y1+2] > 0)
		{
			break;
		}
		if( OneCornerLink(i,y1,x2,y2) )
			return true;
	}
	for(i = y1-1;i >= 0;i--)				//左检测
	{
		aa=map[x1+2][i+2];
		if(map[x1+2][i+2] > 0)
		{
			break;
		}
		if( OneCornerLink(x1,i,x2,y2) )
			return true;
	}
	for(i = x1-1;i >= 0;i--)				//上检测
	{
		aa=map[i+2][y1+2];
		if(map[i+2][y1+2] > 0)
		{
			break;
		}
		if( OneCornerLink(i,y1,x2,y2) )
			return true;
	}

	return false;
}

//播放游戏开始音乐
void playStartSound()
{
	PlaySound("./music/start.wav",NULL,SND_ASYNC); 
}

//选择音乐
void setSound(int s_sort)
{
	sound_sort = s_sort;
}

//播放音乐
void playSound(int s_sort)
{
	char ss_sort[20]={0};
	::sprintf(ss_sort,"./music/clear%d.wav",s_sort);
	PlaySound(ss_sort,NULL,SND_ASYNC); 
}

//左键按下
void LButtonDown(int x,int y)
{
	int m;
	POINT pp[4];

	int xx,yy;
	int sort;
	int col_index,row_index;
	
	xx = x - game_left;
	yy = y - game_top;

	if(xx<=0 || yy<=0 || xx>=(col-4)*31 || yy>=(row-4)*34)		//判断是否在游戏区内
		return;
	
	col_index = xx/31;				//转化成列下标
	row_index = yy/34;				//转化成行下标

	if( (map[row_index+2][col_index+2] != -1) && (map[row_index+2][col_index+2] != 0) )
	{
		if(p1.x == BLANK_STATE)				//假设尚未记录第一个方块
		{
			p1.x = row_index;
			p1.y = col_index;
		
			PaintFrame(game_left,game_right,game_top,game_bottom,col_index,row_index);		//方块外框绘制,线条环绕绘制框架
			fram_sign = true;

			g_row_index = row_index;
			g_col_index = col_index;
			return;
		}
		else
		{
			if( p1.x==row_index && p1.y==col_index )	//第二次点击本身
			{
				p1.x = BLANK_STATE;
				fram_sign = false;
				return;
			}
			else		//第二次点击非本身
			{
				if(map[p1.x+2][p1.y+2] == map[row_index+2][col_index+2])	//第一次和第二次点击的两个方块类型一样
				{
					if( IsLink(p1.x,p1.y,row_index,col_index) )				//可以连接,消去连接的2个方块
					{
						sort = map[p1.x+2][p1.y+2];

						score += 100;							//计分							
						game_time += 1;							//游戏时间+1

						map[p1.x+2][p1.y+2] = -1;				//将已消去的位置X置-1
						map[row_index+2][col_index+2] = -1;		//将已消去的位置Y置-1				
						fram_sign = false;
						num-=2;									//方块总数-2
	
						playSound(sound_sort);					//播放消去的声音

						if (end(num) )							//判断游戏是否结束
						{
							g_pGame->setStart(false);
							return;
						}

						sort_num[sort-1]-=1;					//对应种类的方块数量-1

						//写入对应种类方块的位置
						for(m = 0;m < 16;m+=4)				
						{
							//取出相同种类所对应的位置
							pp[m/4].x = sort_place[sort-1][m]*10 + sort_place[sort-1][m+1];
							pp[m/4].y = sort_place[sort-1][m+2]*10 + sort_place[sort-1][m+3];

							//种类相同的话,将其位置置-1
							if( (pp[m/4].x==p1.x) && (pp[m/4].y==p1.y) )
							{
								sort_place[sort-1][m] = -1;
								sort_place[sort-1][m+1] = -1;
								sort_place[sort-1][m+2] = -1;
								sort_place[sort-1][m+3] = -1;
							}
							if( (pp[m/4].x == row_index) && (pp[m/4].y == col_index) )
							{
								sort_place[sort-1][m] = -1;
								sort_place[sort-1][m+1] = -1;
								sort_place[sort-1][m+2] = -1;
								sort_place[sort-1][m+3] = -1;
							}
						}

						p1.x = BLANK_STATE;
						
						clue_sign = false;

						//判断是否有解
						while( !IsResult() )
						{
							ReInitial();
						}
					}
					else		//不可以连接
					{
						p1.x = row_index;
						p1.y = col_index;

						g_row_index = row_index;
						g_col_index = col_index;
					}
					return;
				}
				else			//第一次和第二次点击的两个方块类型不一样
				{
					p1.x = row_index;
					p1.y = col_index;

					g_row_index = row_index;
					g_col_index = col_index;
					return;
				}
			}
		}
	}
}

这样写搞得我也晕了,可能会导致我漏了一些没写出来的未定义函数(因为这是我项目完成后写的博客,如果是边写边做我可以通过调试知道那些函数还没定义),为了方便观察,下面粘贴出函数与函数之间的调用关系.
Winmain:win32游戏开发(2) --连连看游戏制作(vc++版)_第1张图片
wndprc:
win32游戏开发(2) --连连看游戏制作(vc++版)_第2张图片
貌似还有游戏相关算法还没有介绍,有点累了,对连连看游戏算法感兴趣的可以下载我上传的vc++版连连看文件,我有写注释.因为我还要试着用老师给的游戏引擎再写一版vs2010的连连看游戏,下次我会具体介绍游戏算法,至于游戏是怎么运行的,函数调用应该放在哪个地方我就不说了.

你可能感兴趣的:(Win32,application)