win32遊戲開發(2) --連連看遊戲製作(vc++版)
阿新 • • 發佈:2018-12-15
工程目錄一覽
檔案功能及關係圖: 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: wndprc: 貌似還有遊戲相關演算法還沒有介紹,有點累了,對連連看遊戲演算法感興趣的可以下載我上傳的vc++版連連看檔案,我有寫註釋.因為我還要試著用老師給的遊戲引擎再寫一版vs2010的連連看遊戲,下次我會具體介紹遊戲演算法,至於遊戲是怎麼執行的,函式呼叫應該放在哪個地方我就不說了. 附上下載連結:連連看vc++版原始碼