c++連連看課程設計_第1頁
c++連連看課程設計_第2頁
c++連連看課程設計_第3頁
c++連連看課程設計_第4頁
c++連連看課程設計_第5頁
已閱讀5頁,還剩44頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

PAGEword文檔可自由復制編輯word文檔可自由復制編輯1.引言1.1游戲介紹連連看來源于街機游戲《四川麻將》和《中國龍》,是給一堆圖案中的相同圖案進行配對的簡單游戲,在2003年,一個叫做朱俊的網(wǎng)友將這種形式搬到了PC上,立刻成為辦公一族的新寵,并迅速傳遍了世界各地。飽受工作壓力的人們沒有太多的時間進行復雜的游戲,而對于這種動動鼠標就能過關(guān)的游戲情有獨鐘。之后村子的連連看風靡版,阿達的連連看奧運版,連連看反恐版,還有敏敏連連看,水晶連連看等遍地開花,造就了一個連連看的新世界。連連看游戲有多種地圖樣式和道具系統(tǒng)、大大加強了游戲的可玩性,是一款老少皆宜的休閑佳品。1.2目的網(wǎng)絡小游戲制作的目的是滿足了人們休閑的需要,在緊張工作之余休閑類的小游戲能夠給人帶來最大程度的放松,也可以增進人們之間的交流,溝通,通過游戲還可以認識更多的朋友,也可以到達跨省、跨市,甚至跨國間人們互相娛樂的目的。另外也通過本程序?qū)⑷陙硭鶎W的專業(yè)知識和其他方面的知識融入到實際應用中。1.3主要問題開始制作游戲時,主要要解決的問題有以下幾個方面:如何設置整個游戲的界面;如何控制連連看游戲中隨機圖片的生成且每種圖片必須為偶數(shù)個;游戲開始后,判斷鼠標兩次點擊的圖片能否消去,即圖片是否相同且圖片之間路徑的判斷.1.4開發(fā)環(huán)境 Intel?Pentium?42.0GHz,512M內(nèi)存,80G硬盤 Microsoft?Windows?2000Professional Microsoft?VisualC++6.02.需求分析關(guān)于連連看的功能描述如下:運行游戲并進行初始化工作,將整個游戲區(qū)域分成縱向和橫向擴展的若干個小方塊,并且這些小方塊是由多種動物圖案成對地分布于游戲區(qū)域的不同位置。玩家可以通過選取相同的兩個物件來對它們進行消除的操作,直到將游戲區(qū)域中的所有方塊對都被消除后為勝利。游戲的整體運行效果如圖1.1。圖1.13.功能模塊的設計3.功能模塊的設計3.1類設計這個游戲的主要類是游戲模式類,類名為CMyDlg。這個類主要對包括圖案方塊的銷毀判斷,游戲勝利判斷以及整個游戲用戶交換功能的實現(xiàn)。它uml圖如下:CMyDlgm_mem3DBkDC:CDCm_mem3DBkBmp:CBitmapm_memAnimalDC:CDC m_memAnimalBmp:CBitmapm_MemDC:CDC m_memBitmap:CBitmapm_map:intm_nRow: int m_nCol:int m_nX1:int m_nY1:int GameDraw(CDC*pDC):voidStartNewGame():voidPreTranslateMessage(MSG*pMsg):BOOLIsLink(intx1,inty1,intx2,inty2):BOOLIsWin(void):BOOLX1_Link_X2(intx,inty1,inty2):BOOLY1_Link_Y2(intx1,intx2,inty):BOOLOneCornerLink(intx1,inty1,intx2,inty2):BOOLTwoCornerLink(intx1,inty1,intx2,inty2):BOOLYThrough(intx,inty,BOOLbAdd):BOOLXThrough(intx,inty,BOOLbAdd):BOOLLineX(intx,inty1,inty2):BOOLLineY(intx1,intx2,inty):BOOL這些成員函數(shù)和成員變量的算法分析與設計以及核心算法中有詳細介紹。3.2.框架的搭建從圖1.1可以看出,整個運行的界面由菜單欄和游戲區(qū)域的圖形顯示組成,因此,需要用對話框模板的方式去搭建整個框架再添加一個菜單欄。首先,創(chuàng)建一個基于對話框模板的項目,如圖1.2所示。圖1.2在創(chuàng)建過程的第一步“MFC應用程序向?qū)А襟E1”中應該選擇“基本對話框”選項,確保應用程序的創(chuàng)建是對話框模板,如圖1.3所示。圖1.3然后添加菜單欄為對話框增加菜單欄并為對話框創(chuàng)建一個菜單資源IDR_MENU1。圖1.4在對話框的屬性對話框中在Menu屬性中選擇剛創(chuàng)建的菜單資源IDR_MENU1。此時保存編譯后,在對話框中就可看到菜單。圖1.5點擊快捷鍵Ctrl+W,在“AddaClass”對話框中選擇已存在的對話框類“Selectanexistingclass”,打開“SelectClass”對話框。圖1.6選擇對話框類,本例中的類名為CMyDlg,選中進入下一步。圖1.7進入MFCClassWizard對話框,在消息映射屬性頁中,為菜單增加消息處理函數(shù),為子菜單增加COMMAND處理函數(shù)函數(shù)名為默認函數(shù)名。如圖1.8所示:圖1.8給各個子菜單添加消息映射,同上所述。然后編輯函數(shù)代碼,實現(xiàn)自己定義的功能,添加的代碼如下:voidCMyDlg::Onexit(){ //TODO:AddyourcommandhandlercodehereCDialog::OnCancel(); }voidCMyDlg::Onnewgame(){ //TODO:AddyourcommandhandlercodehereStartNewGame(); }voidCMyDlg::Onathour(){ //TODO:AddyourcommandhandlercodehereMessageBox("11物41陳曉麗"); } voidCMyDlg::Onabout(){ //TODO:AddyourcommandhandlercodehereMessageBox("本游戲連連由C++MFC設計實現(xiàn),是給一堆圖案中的相同圖案進行配對的簡單游戲"); }編譯運行后,點擊各子菜單,將彈出對話框。4.算法分析與設計在對算法進行分析前,應先抽象出游戲的基本是具結(jié)構(gòu),而對連連看游戲來說,核心的部分應該是整個游戲區(qū)域的地圖數(shù)據(jù)。那么,下面將分析游戲特性,然后設計出標識地圖的數(shù)據(jù)結(jié)構(gòu)。4.1游戲地圖數(shù)據(jù)設計對于整個游戲區(qū)域,可以把它看作一個是由若干個小方塊構(gòu)成的地圖,而且每一個小方塊放置著不同的動物圖案,可將其稱之為圖案小方塊。這些圖案小方塊零散地分布在地圖的不同位置區(qū)域,并且每一個圖案小方塊都有與其對應的完全一樣的另外一個小方塊,如圖1.8所示。圖1.9如圖1.9所示,整個游戲游戲區(qū)域被抽象成一個有坐標位置屬性的平面,平面上零散地分布著若干個小方塊,并且這些小方塊的物種起碼是成對出現(xiàn)的。經(jīng)過前面的描述和分析后,可以把游戲區(qū)域地圖用一個數(shù)組m_map來表示。m_map是把地圖設計成一個動態(tài)分配的int整形一維數(shù)組,對地圖中的行列數(shù)的表達,用一個轉(zhuǎn)換法則即可??梢栽贑MyDlg類對象定義中添加地圖核心數(shù)據(jù)的成員變量,具體如下://地圖位置相關(guān)屬性組 int*m_map;//動態(tài)地圖數(shù)據(jù)頭指針(一維數(shù)組) int m_nRow; //地圖的行數(shù)(虛擬) int m_nCol; //地圖的列數(shù)(虛擬)上面的成員變量中定義了一個整形指針標量m_map,用于記錄動態(tài)分配出來的一維數(shù)組地圖空間的首地址。對于地圖區(qū)域中的某個小方塊的類型,可以用一個整形的ID來進行識別。這里為標識地圖的行列位置分別添加m_nRow和m_nCol變量?,F(xiàn)在,地圖的數(shù)據(jù)結(jié)構(gòu)已經(jīng)設計好。下面對游戲進行初始化。由于方塊需要成對地出現(xiàn),因此在做地圖的初始化時,不僅僅是對動物種類做簡單的隨機取數(shù),然后將該隨機選取出來的物件放到地圖區(qū)域中去就了事,而是需要成對地對物種進行成對選取,就是說地圖中的小方塊必須是偶數(shù)個。前面提到過,把地圖數(shù)組設置成動態(tài)分配方式,目的是讓其數(shù)據(jù)空間可以根據(jù)行列數(shù)的需求動態(tài)地獲取,而對于實際不同大小比例的地圖可以預先定義幾組關(guān)于行列數(shù)的宏來實現(xiàn)。當需要創(chuàng)建時,根據(jù)宏值的不同分配不同大小的地圖空間即可。接下來在CMyDlg類的構(gòu)造函數(shù)對地圖數(shù)據(jù)進行相關(guān)的初始化:#defineROWCOUNT7 //行數(shù)#defineCOLCOUNT12 //列數(shù)CMyDlg::CMyDlg(CWnd*pParent/*=NULL*/) :CDialog(CMyDlg::IDD,pParent){ …… //記錄方塊置為無效狀態(tài) m_nY1=BLANK_STATE; m_nX1=BLANK_STATE; //初始化行列數(shù) m_nRow=ROWCOUNT; m_nCol=COLCOUNT; //根據(jù)行列數(shù)動態(tài)分配內(nèi)核數(shù)據(jù)數(shù)組空間 m_map=newint[m_nRow*m_nCol];}CMyDlg::~CMyDlg(){ //釋放動態(tài)數(shù)組空間 delete[]m_map;}在CMyDlg類對象的實現(xiàn)中,定義了一些關(guān)于地圖行列數(shù)的宏,如ROWCOUNT和COLCOUNT,并且在CMyDlg類對象的構(gòu)造函數(shù)中,進行了行列的真實確認賦值,并根據(jù)當前行列數(shù)的大小對地圖數(shù)據(jù)空間進行動態(tài)創(chuàng)建。因為地圖數(shù)據(jù)是用new在堆棧動態(tài)創(chuàng)建的,所以在銷毀該對象時要將這些內(nèi)存空間釋放,如代碼所示在CMyDlg類對象的析構(gòu)函數(shù)中調(diào)用delete將m_map指向的所有空間都釋放掉。4.2數(shù)據(jù)的初始化工作接下來,再分配好的空間中放上適當?shù)膱D案方塊物件,對數(shù)據(jù)進行初始化。即需要對地圖空間內(nèi)的數(shù)據(jù)進行成對性的隨機布局,因此可以將該功能的實現(xiàn)封裝在StartNewGame()函數(shù)里面,其代碼如下:voidCMyDlg::StartNewGame(){ //初始化地圖,將地圖中所有方塊區(qū)域位置置為空方塊狀態(tài) for(intiNum=0;iNum<(m_nCol*m_nRow);iNum++) { m_map[iNum]=BLANK_STATE; } //部下隨機種子 srand(time(NULL)); //生成隨機地圖 //將所有匹配成對的動物物種放進一個臨時的地圖中 CDWordArraytmpMap; for(inti=0;i<(m_nCol*m_nRow)/6;i++) for(intj=0;j<6;j++) tmpMap.Add(i); //每次從上面的臨時地圖中取走(獲取后并在臨時地圖刪除) //一個動物放到地圖的空方塊上 for(i=0;i<m_nRow*m_nCol;i++) { //隨機挑選一個位置 intnIndex=(int(rand()*0.1+rand()*0.01+rand()))%tmpMap.GetSize(); //獲取該選定物件放到地圖的空方塊 m_map[i]=tmpMap.GetAt(nIndex); //在臨時地圖除去該動物 tmpMap.RemoveAt(nIndex); } //更新顯示 Invalidate(TRUE);}在游戲進行初始化的過程中,應該先對整個地圖中的各個區(qū)域做必要的初始化操作,將它們的狀態(tài)設置為BLANK_START空白方塊狀態(tài)(無動物圖案方塊),關(guān)于BLANK_START空白方塊狀態(tài)的定義,跟其他動物方塊的物種定義表達類似,也是用整數(shù)ID來對它進行標識,不過不同的是,由于他代表該方塊區(qū)域無圖案,所以這里用-1的宏值來表示,具體定義如下:#defineBLANK_STATE-1//空方塊(沒有任何動物)可以看到,對圖案方塊的布局,先用srand()函數(shù)對時間函數(shù)布下隨機種子,然后調(diào)用rand()函數(shù)對具體的圖案方塊的種類進行隨機的獲取。在這里需要引入一個臨時地圖tmpMap,該臨時地圖的大小與內(nèi)核數(shù)據(jù)地圖的大小一致,并且先添置好4組完全一樣的圖案類型ID數(shù)據(jù)(0~(m_nCol*m_nRow)/4),然后再將已經(jīng)安放在tmpMap中的圖案作隨機抽取,并放到內(nèi)核地圖數(shù)據(jù)中去,將取出的元素從tmpMap中除去。4.3快捷方式的創(chuàng)建按Ctrl+W為類添加消息映射PreTranslateMessage,雙擊函數(shù)名為該函數(shù)添加如下代碼BOOLCMyDlg::PreTranslateMessage(MSG*pMsg){ //TODO:Addyourspecializedcodehereand/orcallthebaseclass if(pMsg->message==WM_KEYDOWN) { if(pMsg->wParam==VK_F2) { StartNewGame(); }if(pMsg->wParam==VK_F3) {CDialog::OnCancel(); } }在運行游戲時按下F2便可重新開始新游戲,按F3便可退出游戲。5.核心算法在完成地圖數(shù)據(jù)設計后,就開始展開游戲核心的設計,該部分主要包括圖案方塊的銷毀判斷,游戲勝利判斷以及整個游戲用戶交換功能的實現(xiàn)。5.1圖案方塊的連接判斷對于選中的兩個方塊的銷毀,他們必須符合下面3個條件:(1)選中的兩個方塊圖案相同。(2)選中的兩個方塊之間沒有障礙物阻礙的情況下,可以用若干個垂直的直線線段連接起來。(3)這些將它們連接起來的直線線段的折點不超過兩個(連接線由x軸和y軸的平行線組成)。現(xiàn)在針對(2)和(3)進行分析,同種物件的連接方式大致可以分成以下3種:直接方式有一個折點的垂直線段連接。有兩個折點的垂直線段連接.。1.直接連接方式在直接連接方式中,必須要求所選定的兩個方塊在同一水平直線上(可以為x方向或y方向),并且兩個方塊之間沒有任何其他圖案方塊。2.一個這點連接方式所選定的兩個方塊如果通過折點的方式連接,那么對于折點來說,每個折點必定有且至少有一個坐標(x或y)是和其中一個目標點相同的,即折點必定在兩個目標點所在的x方向或y方向的直線上。此外,對于一個折點連接的情況,折點應該為第一個選中方塊的橫向線或縱向線與第二個選中方塊的縱向線和橫向線相交而得出。3.兩個折點的連接方式這種方式的兩個折點所連成的直線與兩物件的直接連線可以構(gòu)成平行線,因此可以根據(jù)這個規(guī)律,將這條水平線在游戲區(qū)域允許的條件上下移動,然后通過判斷整條帶垂直折線點的曲線之間有無障礙物方式來確定是否可以連同。這種情況可以分為兩種情況:(1)選中的兩圖案方塊在同一直線,兩折點間的直連線可在其這兩個方塊之間的空間位置作移動,其約束是不超過游戲邊界區(qū)域。(2)選中的兩圖案方塊不在同一直線,兩折點間的直連線可在兩個方塊之間的空間位置作移動,其約束是兩方塊之間的區(qū)域。經(jīng)過上面詳細的分析后,可以對選定的兩方塊是否可以作抵消操作可以這樣設計下去。首先,對簡單的直接連情況進行判斷,看其是否符合條件,假如不能,再加深一個級別的復雜度,對一個折點的情況進行判斷,依次類推,如下圖所示。圖1.10圖1.11根據(jù)如圖1.6所示的流程圖,可以對選定的兩個方塊(分別在(x1,y1)以及(x2,y2)兩個區(qū)域位置,其中x,y分別代表行與列的概念)是否可以抵消作以下實現(xiàn)。把該功能封裝在IsLink()函數(shù)里面,其代碼如下所示://判斷選中的兩個方塊是否可以消除BOOLCMyDlg::IsLink(intx1,inty1,intx2,inty2){ //X直連方式 if(x1==x2) { if(X1_Link_X2(x1,y1,y2)) returnTRUE; } //Y直連方式 elseif(y1==y2) { if(Y1_Link_Y2(x1,x2,y1)) returnTRUE; } //一個轉(zhuǎn)彎直角的聯(lián)通方式 if(OneCornerLink(x1,y1,x2,y2)) { returnTRUE; } //兩個轉(zhuǎn)彎直角的聯(lián)通方式 elseif(TwoCornerLink(x1,y1,x2,y2)) { returnTRUE; } returnFALSE;}在上面的實現(xiàn)中,先是對直連方式中的x方向直連Y1_Link_Y2()以及y方向直連X1_Link_X2()這兩種情況進行判斷,如果尚未取得結(jié)果,再通過調(diào)用OneCornerLink()函數(shù)對一個折點的情況進行判斷,或者更糟糕的時候調(diào)用TwoCornerLink()函數(shù)對兩個這點的情況進行判斷,然后得出最終結(jié)果。下面將對上面涉及到的子功能模塊進行實現(xiàn),代碼如下所示://X直接連通BOOLCMyDlg::X1_Link_X2(intx,inty1,inty2){ //保證y1的值小于y2 if(y1>y2) { //數(shù)據(jù)交換 intn=y1; y1=y2; y2=n; } //直通 for(inti=y1+1;i<=y2;i++) { if(i==y2) returnTRUE; if(m_map[i*m_nCol+x]!=BLANK_STATE) break; } //左通 if(XThrough(x-1,y1,FALSE)&&XThrough(x-1,y2,FALSE)) returnTRUE; //右通 if(XThrough(x+1,y1,TRUE)&&XThrough(x+1,y2,TRUE)) returnTRUE; returnFALSE;}//Y直接連通BOOLCMyDlg::Y1_Link_Y2(intx1,intx2,inty){ if(x1>x2) { intx=x1; x1=x2; x2=x; } //直通 for(inti=x1+1;i<=x2;i++) { if(i==x2) returnTRUE; if(m_map[y*m_nCol+i]!=BLANK_STATE) break; } //上通 if(YThrough(x1,y-1,FALSE)&&YThrough(x2,y-1,FALSE)) returnTRUE; //下通 if(YThrough(x1,y+1,TRUE)&&YThrough(x2,y+1,TRUE)) returnTRUE; returnFALSE;}//是否同一直線通//BOOLCMyDlg::LineX(intx,inty1,inty2){ if(y1>y2) { inty=y1; y1=y2; y2=y; } for(inty=y1;y<=y2;y++) { if(m_map[y*m_nCol+x]!=BLANK_STATE) returnFALSE; if(y==y2) returnTRUE; } returnFALSE;}////是否同一直線通//BOOLCMyDlg::LineY(intx1,intx2,inty){ if(x1>x2) { intx=x1; x1=x2; x2=x; } for(intx=x1;x<=x2;x++) { if(m_map[y*m_nCol+x]!=BLANK_STATE) returnFALSE; if(x==x2) returnTRUE; } returnFALSE;}//1直角接口連通BOOLCMyDlg::OneCornerLink(intx1,inty1,intx2,inty2){ if(x1>x2) { intn=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; } if(y2<y1) { if(LineY(x1+1,x2,y1)&&LineX(x2,y1,y2+1)) returnTRUE; if(LineY(x2-1,x1,y2)&&LineX(x1,y2,y1-1)) returnTRUE; returnFALSE; } else { if(LineY(x1+1,x2,y1)&&LineX(x2,y1,y2-1)) returnTRUE; if(LineY(x2-1,x1,y2)&&LineX(x1,y2,y1+1)) returnTRUE; returnFALSE; } returnFALSE;}//2直角接口連通BOOLCMyDlg::TwoCornerLink(intx1,inty1,intx2,inty2){ if(x1>x2) { intn=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; } //右通 if(XThrough(x1+1,y1,TRUE)&&XThrough(x2+1,y2,TRUE)) returnTRUE; //左通 if(XThrough(x1-1,y1,FALSE)&&XThrough(x2-1,y2,FALSE)) returnTRUE; //上通 if(YThrough(x1,y1-1,FALSE)&&YThrough(x2,y2-1,FALSE)) returnTRUE; //下通 if(YThrough(x1,y1+1,TRUE)&&YThrough(x2,y2+1,TRUE)) returnTRUE; //右 for(intx=x1+1;x<m_nCol;x++) { if(m_map[y1*m_nCol+x]>-1) break; if(OneCornerLink(x,y1,x2,y2)) returnTRUE; } //左 for(x=x1-1;x>-1;x--) { if(m_map[y1*m_nCol+x]!=BLANK_STATE) break; if(OneCornerLink(x,y1,x2,y2)) returnTRUE; } //上 for(inty=y1-1;y>-1;y--) { if(m_map[y*m_nCol+x1]!=BLANK_STATE) break; if(OneCornerLink(x1,y,x2,y2)) returnTRUE; } //下 for(y=y1+1;y<m_nRow;y++) { if(m_map[y*m_nCol+x1]!=BLANK_STATE) break; if(OneCornerLink(x1,y,x2,y2)) returnTRUE; } returnFALSE;}BOOLCMyDlg::XThrough(intx,inty,BOOLbAdd){ if(bAdd) { for(inti=x;i<m_nCol;i++) if(m_map[y*m_nCol+i]!=BLANK_STATE) returnFALSE; } else { for(inti=0;i<=x;i++) if(m_map[y*m_nCol+i]!=BLANK_STATE) returnFALSE; } returnTRUE;}BOOLCMyDlg::YThrough(intx,inty,BOOLbAdd){ if(bAdd) { for(inti=y;i<m_nRow;i++) if(m_map[i*m_nCol+x]!=BLANK_STATE) returnFALSE; } else { for(inti=0;i<=y;i++) if(m_map[i*m_nCol+x]!=BLANK_STATE) returnFALSE; } returnTRUE;}這里把直接連接方式分為直通,左通,右通3種情況,如1.12圖所示。下面簡單介紹直通和左通兩種情況(右通與左通類似)(1)直通:直通就是在選定的兩個方塊直連線中,沒有被任何方塊所阻礙。(2)左通:左通就是選定的兩個方塊的直連線之間有其他方塊阻礙,但是通過它的左側(cè)可以將它們無阻礙地連通。直連方式中的此種情況跟前面分析的兩個折點連接方式中的其中一點相當類似,如1.13圖所示。它們之間的區(qū)別就是,左通的連接線直接在其相鄰的位置連通,從而不構(gòu)成垂直折點的效果,而兩個折點連同方式中的其中一個類似的情況是,線的連通起碼要偏移一個方塊的距離來形成連通。圖1.12圖1.13同理,有上通和下通,它們的情況與左通和右通類似。5.2游戲勝利的判斷要判斷游戲的勝利,實現(xiàn)起來比較簡單,只需對地圖中的所有區(qū)域的狀態(tài)進行檢測就可里了,只要檢測到地圖中有一個圖案方塊還沒有被抵消,則證明游戲沒有結(jié)束,完成判斷。其代碼如下所示://檢測是否已經(jīng)贏得了游戲BOOLCMyDlg::IsWin(void){ //檢測所有是否尚有非未被消除的方塊 //(非BLANK_STATE狀態(tài)) for(inti=0;i<m_nRow*m_nCol;i++) { if(m_map[i]!=BLANK_STATE) { returnFALSE; } } returnTRUE;}游戲勝利界面如圖1.14所示圖1.14游戲勝利界面至此,已經(jīng)完成整個游戲基本的內(nèi)部相關(guān)功能模塊的運算,接下來實現(xiàn)用戶的交互部分的功能。5.3鼠標交互功能的實現(xiàn)對于用戶交互的實現(xiàn),這里選擇鼠標交互方式。下面簡單描述一下通過鼠標交互方式實現(xiàn)的功能。鼠標選取兩個圖案方塊后,程序?qū)⒆詣优袛嗨x定的兩個方塊是否能進行抵消操作,能則進行抵消操作。在游戲過程中,我們不斷重復上面描述的功能,直到游戲的勝利結(jié)束。下面將鼠標事件處理工作歸納為如圖1.14所示的流程。圖1.15對于鼠標交互功能的實現(xiàn),可以通過ClassWizard對鼠標左鍵被按下時觸發(fā)的命令消息WM_LBUTTONDOWN進行攔截,并重寫該消息的處理函數(shù)OnLButtonDown(),其程序清單如下所示。voidCMyDlg::OnLButtonDown(UINTnFlags,CPointpoint){ //1.計算鼠標點擊方塊的的位置 intx=point.x/FRONTWIDTH+(point.x%FRONTWIDTH?1:0)-1; inty=point.y/FRONTHEIGHT+(point.y%FRONTHEIGHT?1:0)-1; //2.在游戲區(qū)域內(nèi)并且該區(qū)域還有該區(qū)域不是空的區(qū)域 if(x<m_nCol&&y<m_nRow&&m_map[y*m_nCol+x]!=BLANK_STATE) { //3.假設尚未記錄第一個方塊 if(m_nX1==BLANK_STATE) { //4.記錄第一個方塊的位置 m_nX1=x; m_nY1=y; //獲取程序框架的設備環(huán)境 CDC*pWinDC=GetDC(); //臨時繪制點中的方塊外框 //只繪屏幕不載入內(nèi)存位圖 CPenmyPen; CPen*pOldPen; myPen.CreatePen(PS_SOLID,4,RGB(255,0,0)); pOldPen= pWinDC->SelectObject(&myPen); //方塊外框繪制,線條環(huán)繞繪制框架 pWinDC->MoveTo(x*FRONTWIDTH,y*FRONTHEIGHT); pWinDC->LineTo(x*FRONTWIDTH,(y+1)*FRONTHEIGHT); pWinDC->LineTo((x+1)*FRONTWIDTH,(y+1)*FRONTHEIGHT); pWinDC->LineTo((x+1)*FRONTWIDTH,y*FRONTHEIGHT); pWinDC->LineTo(x*FRONTWIDTH,y*FRONTHEIGHT); //現(xiàn)場恢復 pWinDC->SelectObject(pOldPen); } else { //5.判斷是否點擊的方塊非本身,是否點擊同一種動物 if((m_nX1!=x||m_nY1!=y)&& m_map[m_nY1*m_nCol+m_nX1]==m_map[y*m_nCol+x] ) { //6.檢測是否可以消除 if(IsLink(m_nX1,m_nY1,x,y)) { //7.數(shù)據(jù)清理 m_map[m_nY1*m_nCol+m_nX1]=BLANK_STATE; m_map[y*m_nCol+x]=BLANK_STATE; } } //8.清空記錄方塊的值 m_nX1=BLANK_STATE; m_nY1=BLANK_STATE; //通知重繪 Invalidate(FALSE); } } //察看是否已經(jīng)勝利 if(IsWin()) { MessageBox("恭喜您勝利闖關(guān),即將開始新局"); StartNewGame(); }}按照預先設計出的鼠標事件處理流程,上面已經(jīng)將它轉(zhuǎn)換成具體的實現(xiàn)代碼。下面將按照流程的子功能模塊的劃分方式,對整個功能模塊的具體協(xié)調(diào)和實現(xiàn)過程進行簡單的描述。(1)首先,利用鼠標的當前坐標位置point對每個小單元方塊的寬度FRONTWIDTH和高度FRONTHEIGHT分別取模,獲取當前鼠標落點所在的游戲區(qū)域的具體行列數(shù)(x,y)。(2)判斷出該行列數(shù)(x,y)是否符合條件。保證運算出來的行數(shù)x和列數(shù)y的預定義區(qū)域最大的行數(shù)m_nCol和列數(shù)m_nRow內(nèi),并且點擊的區(qū)域狀態(tài)不是空白方塊區(qū)域BLANK_STATE(3)對判斷此次鼠標書劍的選取是否與第一個方塊的選取一樣,只需通過用于記錄第一個被選中的方塊的行列數(shù)的成員變量m_nX1是否為有效即可。這里將m_nX1以及m_nY1來記錄它所在的行、列數(shù),并且每次經(jīng)過判斷后都會將它們的狀態(tài)恢復為空白無選中狀態(tài)BLANK_STATE。關(guān)于這兩個用作記錄第一個選中圖案方塊行列數(shù)的成員變量,在對話框類中的具體定義如下所示: int m_nX1;//鼠標選中的記錄方塊列數(shù) int m_nY1; //鼠標選中的記錄方塊行數(shù)(4)對于本次選中的方塊為第一選中的情況,先用m_nX1和m_nY1對當前的選中方塊位置做記錄,然后直接在屏幕的該區(qū)域繪制圖像,為該方塊區(qū)域添加一個紅色的矩形外邊框,用以提示用戶當前的第1個圖案方塊選中所在的位置。需要注意的是,對于標記方塊的加亮邊框繪制是通過GetDC()函數(shù)來獲取對話框窗體(屏幕)的設備環(huán)境,對繪制的圖像數(shù)據(jù)沒有作歷史記錄的方式來繪制的。(5)在這一處理中,對該選定方塊作一些判斷,以便更高效地處理。判斷選中的方塊與前一方塊是否為同一圖案方塊,并且此次選擇不與上一次選定的方塊為同一方塊,然后才跳到下一步對兩個選定的方塊是否可以抵消的流程中去。(6)調(diào)用前面已經(jīng)實現(xiàn)的答功能函數(shù)IsLink()來判斷當前所選定的兩個圖案方塊是否可以抵消。(7)如果可以抵消,對選中的兩個方塊在內(nèi)部核心地圖對應的數(shù)據(jù)狀態(tài)作適當?shù)男薷?,將它們的狀態(tài)記作已經(jīng)被銷毀的空方塊狀態(tài)BLANK_STATE。(8)完成第二個圖案的選取與相關(guān)的功能操作后,我們需要前面已經(jīng)選去第1個方塊位置的記錄作清理工作,以便下一個新方塊的選擇。(9)最后,判斷此次的鼠標操作是否已經(jīng)勝利結(jié)束,如果是則給予用戶提示,然后重新開適新的一關(guān)。6.繪圖功能的實現(xiàn)在完成以上所有的交互以及內(nèi)部數(shù)據(jù)關(guān)聯(lián)的運算處理后,最后要將這些數(shù)據(jù)展現(xiàn)到屏幕上。6.1位圖圖像的準備首先,準備好一個帶有不同動物種以及一個3D邊框效果的位圖,如圖1.15所示。通過資源編輯器將它們引入到項目中來,并將它們的ID分別命名為IDB_BMP_ANIMAL和IDB_BITMAP_3DFRAMES。圖1.16word文檔可自由復制編輯6.2繪圖方案的設計對于游戲的繪制實現(xiàn),這里采用內(nèi)存位圖映射的方式,先將整個游戲區(qū)域的圖像繪制到內(nèi)存位圖中,然后再一次性地將它拷貝到屏幕上予以顯示,如圖1.16所示圖1.176.3繪圖資源的載入與初始化根據(jù)圖1.16所示的描述方案,可以在內(nèi)存創(chuàng)建兩個內(nèi)存位圖,并對它們的圖像進行載入。在需要使用的時候,則可以從這些內(nèi)存位圖中直接去拷貝,并繪制到游戲區(qū)域內(nèi)存位圖中去,接下來添加關(guān)于繪圖的成員變量,如下所示。//內(nèi)存位圖屬性組 CDC m_mem3DBkDC;//3D框架的內(nèi)存設備環(huán)境 CBitmapm_mem3DBkBmp;//3D框架的內(nèi)存位圖 CDC m_memAnimalDC;//動物圖像的內(nèi)存設備環(huán)境 CBitmapm_memAnimalBmp;//動物圖像的內(nèi)存位圖 CDC m_MemDC;//游戲區(qū)域內(nèi)存設備環(huán)境 CBitmapm_memBitmap;//游戲區(qū)域內(nèi)存位圖這里,對3D框架位圖以及動物圖案位圖分別創(chuàng)建了對應的設備環(huán)境m_mem3DBkDC和m_memAnimalDC,并且位它們分配了關(guān)聯(lián)的內(nèi)存位圖變量m_mem3DBkBmp和m_memAnimalBmp。而對于游戲區(qū)域的內(nèi)存繪制,亦為它創(chuàng)建了一個內(nèi)存設備環(huán)境m_MemDC以及關(guān)聯(lián)的內(nèi)存位圖m_memBitmap。在完成以上工作后,需要在程序開始運行的時候,一次行對它們進行適當?shù)某跏蓟?。可以將這些繪圖的具體初始化加載在CMyDlg對話框類的初始話函數(shù)OnInitDialog中,代碼如下所示。 //獲取程序框架的設備環(huán)境 CDC*pWinDC=GetDC(); //內(nèi)存設備環(huán)境以及內(nèi)存位圖的創(chuàng)建,初始化,關(guān)聯(lián) //3D方塊邊框圖樣內(nèi)存位圖 m_mem3DBkDC.CreateCompatibleDC(pWinDC); m_mem3DBkBmp.LoadBitmap(IDB_BITMAP_3D_FRAMES); m_mem3DBkDC.SelectObject(&m_mem3DBkBmp); //動物圖樣內(nèi)存位圖 m_memAnimalDC.CreateCompatibleDC(pWinDC); m_memAnimalBmp.LoadBitmap(IDB_BMP_ANIMAL); m_memAnimalDC.SelectObject(&m_memAnimalBmp); //整個游戲區(qū)域內(nèi)存位圖 m_MemDC.CreateCompatibleDC(pWinDC); m_memBitmap.CreateCompatibleBitmap(pWinDC, m_nCol*FRONTWIDTH+5, m_nRow*FRONTHEIGHT+5); m_MemDC.SelectObject(&m_memBitmap); //開始一個新的游戲 StartNewGame(); //放在最桌面的前面顯示 HWNDhWnd=::AfxGetMainWnd()->m_hWnd; ::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); //Settheiconforthisdialog.Theframeworkdoesthisautomatically //whentheapplication'smainwindowisnotadialog SetIcon(m_hIcon,TRUE); //Setbigicon SetIcon(m_hIcon,FALSE); //Setsmallicon //TODO:Addextrainitializationhere returnTRUE;//returnTRUEunlessyousetthefocustoacontrol在上面的代碼中,現(xiàn)獲取該程序的屏幕設備環(huán)境,然后在將前面提到的3個內(nèi)存設備環(huán)境以及關(guān)聯(lián)的內(nèi)存位圖與該屏幕設備環(huán)境兼容,而對于兩個用于存儲外部位圖圖像的內(nèi)存位圖,則調(diào)用LoadBitmap()函數(shù)對他們相應的位圖資源進行載入以及相關(guān)的初始化工作。6.4游戲區(qū)域的繪制在完成繪圖物件的初始化工作后,接下來就可以對整個游戲區(qū)域的繪制進行實現(xiàn),對整個游戲區(qū)域的繪制,可以將封裝在GameDraw()函數(shù)里,其代碼清單如下所示。voidCMyDlg::GameDraw(CDC*pDC){ //繪制背景顏色pDC->FillSolidRect(0,0,m_nCol*FRONTWIDTH+5,m_nRow*FRONTHEIGHT+5,BKCOLOR); for(inti=0;i<m_nRow;i++) { for(intj=0;j<m_nCol;j++) { if(m_map[i*m_nCol+j]==BLANK_STATE) { continue; } //繪制方塊邊框 pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT, BKWIDTH,BKHEIGHT, &m_mem3DBkDC, 0,BKHEIGHT, SRCCOPY); //繪制方塊 //因為要使得效果透明,所以由圖樣的底色以及表面兩部分構(gòu)成 pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT, FRONTWIDTH-2,FRONTHEIGHT-12, &m_memAnimalDC, FRONTWIDTH-2,m_map[i*m_nCol+j]*(FRONTHEIGHT-12), SRCAND); pDC->BitBlt(j*FRONTWIDTH,i*FRONTHEIGHT, FRONTWIDTH-2,FRONTHEIGHT-12, &m_memAnimalDC, 0,m_map[i*m_nCol+j]*(FRONTHEIGHT-12), SRCPAINT); } }}在上面程序中,先調(diào)用FillSolidRect()函數(shù)來繪制整個游戲區(qū)域的背景,在對游戲區(qū)域中有動物圖案的方塊進行3D邊框的繪制,繪制的方法示從3D邊框的內(nèi)存位圖中拷貝,然后在根據(jù)內(nèi)核地圖中每一個方框區(qū)域的圖案物種從動物內(nèi)存位圖m_memAnimalBmp中通過與它關(guān)聯(lián)的m_memAnimalDC進行動物圖案的拷貝。7.背景音樂功能的實現(xiàn)在游戲過程中,播放背景音樂這在一定程度上能夠增加用戶對游戲的沉侵感。對聲音模塊信息的管理在程序中是通過API中的PlaySound函數(shù)來實現(xiàn)的。首先選擇一段.wav音樂在ResourceView界面插入WAVE資源并引入該段音樂,并設置屬性為IDR_WAVE1,在菜單中添加音樂菜單和子菜單播放與暫停。同上所述,給播放菜單添加消息映射,并添加下列代碼:PlaySound(MAKEINTRESOURCE(IDR_WAVE1),AfxGetResourceHandle(),SND_ASYNC|SND_RESOURCE|SND_NODEFAULT|SND_LOOP);給暫停菜單添加消息映射,并添加下列代碼:PlaySound(NULL,NULL,SND_FILENAME);因為PlaySound函數(shù)體被編譯到Winmm.lib庫文件中,點擊工程—設置,選擇連接,在對象/庫模塊填入winmm.lib,這樣就可在點擊播放菜單播放背景音樂,點擊暫停菜單停止背景音樂了。8.總結(jié)經(jīng)過一個學期對《C++實用教程》的學習,我學習到了基本的理論知識,了解到了C++語言程序設計的思想,這些知識都為我的課程實踐和進一步的學習打下了堅實的基礎。在為期近兩周的C++課程設計中,我體會頗多,學到了很多東西。我加強了對C++程序設計這門課程的認識,并且復習了自己以前學習到的知識。這些都使得我對計算機語言的學習有了更深入的認識!總之,通過這次課程設計,我收獲頗豐,相信會為自己以后的學習和工作帶來很大的好處。像小游戲程序設計,經(jīng)歷了平時在課堂和考試中不會出現(xiàn)的問題和考驗。而這些問題,這并不是我們平時只靠課本,就可以輕易解決的。所以,鍛煉了我們挑戰(zhàn)難題,學會用已掌握的知識去解決具體問題的能力,進一步培養(yǎng)了獨思考問題和解決問題的能力。特別是學會了在Visual

C++中如何調(diào)試程序的方法。當然,老師的指導和同學的幫助也是不可忽視的,他們給了我許多提示和幫助,教會了我編譯復雜程序的方法。本文用visualc++來設計與實現(xiàn)簡單的連連看游戲的基本功能,對該游戲的算法以及游戲圖案的繪制進行詳細的介紹,其中核心內(nèi)容包括圖案方塊的銷毀判斷,游戲勝利判斷以及整個游戲用戶交換功能的實現(xiàn)。在制作過程中學會了位圖的引入,對話框背景的設置,背景音樂的播放,對話框顯示菜單的方法等,還加深了對MFC功能的理解,對各個類的函數(shù)功能的理解,對事件的消息映射的理解。此課程設計算法比較簡單,運行速度快。參考文獻1.GeorgeShepherd/DavidKruglinski著,潘愛民譯Microsoft?VisualC++.NET技術(shù)內(nèi)幕(第6版),,清華大學出版社,2.楊永國編,VisualC++6.0實用教程.清華大學出版社,20043.唐俊明編,VisualC++6.0編程實例與技巧.高等教育出版,20024.潘錦平編,軟件系統(tǒng)開發(fā)技術(shù).西安電子科技大學出版社,19975.朱繼滿等譯.,ProgrammingMicrosoftVisualC++技術(shù)內(nèi)幕(第五版),北京希望電子出版社,20016.宋坤等編,VisualC++開發(fā)技術(shù)大全,人民郵電出版社,20077.ErichGamma等著,李英軍等譯,機械工業(yè)出版社,設計模式——可復用面向?qū)ο筌浖幕A8.嚴蔚敏等編,數(shù)據(jù)結(jié)構(gòu),清華大學出版社,20069.JohnE.Swanke著,VisualMFC編程實例,機械工業(yè)出版社,200010.侯俊杰編著,深入淺出MFC,華中科技大學出版社11.ABeginner'sGuidetoPointers,AndrewPeace/cpp/pointers.asp附錄:源代碼//課程設計(連連看)Dlg.cpp:implementationfile//#include"stdafx.h"#include"課程設計(連連看).h"#include"課程設計(連連看)Dlg.h"#include"mmsystem.h"#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endif#defineBKCOLORRGB(128,128,128) //背景顏色#defineFRONTWIDTH (39+2) //前面方塊的寬度#defineFRONTHEIGHT (39+12) //前面方塊的高度#defineBKWIDTH 46 //背景方塊的寬度#defineBKHEIGHT56 //背景方塊的高度#defineROWCOUNT4 //行數(shù)#defineCOLCOUNT6 //列數(shù)#defineBLANK_STATE-1//空方塊(沒有任何動物)///////////////////////////////////////////////////////////////////////////////CAboutDlgdialogusedforAppAboutclassCAboutDlg:publicCDialog{public: CAboutDlg();//DialogData //{{AFX_DATA(CAboutDlg) enum{IDD=IDD_ABOUTBOX}; //}}AFX_DATA //ClassWizardgeneratedvirtualfunctionoverrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport //}}AFX_VIRTUAL//Implementationprotected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg():CDialog(CAboutDlg::IDD){ //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT}voidCAboutDlg::DoDataExchange(CDataExchange*pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CAboutDlg,CDialog) //{{AFX_MSG_MAP(CAboutDlg) //Nomessagehandlers //}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////////CMyDlgdialogCMyDlg::CMyDlg(CWnd*pParent/*=NULL*/) :CDialog(CMyDlg::IDD,pParent){ //{{AFX_DATA_INIT(CMyDlg) //NOTE:theClassWizardwilladdmemberinitializationhere //}}AFX_DATA_INIT //NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32 //記錄方塊置為無效狀態(tài) m_nY1=BLANK_STATE; m_nX1=BLANK_STATE;//初始化行列數(shù) m_nRow=ROWCOUNT; m_nCol=COLCOUNT; //根據(jù)行列數(shù)動態(tài)分配內(nèi)核數(shù)據(jù)數(shù)組空間 m_map=newint[m_nRow*m_nCol]; m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);}voidCMyDlg::DoDataExchange(CDataExchange*pDX){ CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMyDlg) //NOTE:theClassWizardwilladdDDXandDDVcallshere //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP(CMyDlg,CDialog) //{{AFX_MSG_MAP(CMyDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_LBUTTONDOWN() ON_COMMAND(ID_MENUITEM32773,OnMenuitem32773) ON_COMMAND(ID_MENUITEM32774,OnMenuitem32774) ON_COMMAND(ID_MENUITEM32771,OnMenuitem32771) ON_COMMAND(ID_MENUITEM32772,OnMenuitem32772) //}}AFX_MSG_MAPEND_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////////CMyDlgmessagehandlersBOOLCMyDlg::OnInitDialog(){ CDialog::OnInitDialog(); //Settheiconforthisdialog.Theframeworkdoesthisautomatically //whentheapplication'smainwindowisnotadialog SetIcon(m_hIcon,TRUE); //Setbigicon SetIcon(m_hIcon,FALSE); //Setsmallicon //獲取程序框架的設備環(huán)境 CDC*pWinDC=GetDC(); //內(nèi)存設備環(huán)境以及內(nèi)存位圖的創(chuàng)建,初始化,關(guān)聯(lián) //3D方塊邊框圖樣內(nèi)存位圖 m_mem3DBkDC.CreateCompatibleDC(pWinDC); m_mem3DBkBmp.LoadBitmap(IDB_BITMAP_3D_FRAMES); m_mem3DBkDC.SelectObject(&m_mem3DBkBmp); //動物圖樣內(nèi)存位圖 m_memAnimalDC.CreateCompatibleDC(pWinDC); m_memAnimalBmp.LoadBitmap(IDB_BMP_ANIMAL); m_memAnimalDC.SelectObject(&m_memAnimalBmp); //整個游戲區(qū)域內(nèi)存位圖 m_MemDC.CreateCompatibleDC(pWinDC); m_memBitmap.CreateCompatibleBitmap(pWinDC, m_nCol*FRONTWIDTH+5, m_nRow*FRONTHEIGHT+5); m_MemDC.SelectObject(&m_memBitmap); //開始一個新的游戲 StartNewGame(); //放在最桌面的前面顯示 HWNDhWnd=::AfxGetMainWnd()->m_hWnd; ::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); returnTRUE;//returnTRUEunlessyousetthefocustoacontrol}voidCMyDlg::OnSysCommand(UINTnID,LPARAMlParam){ if((nID&0xFFF0)==IDM_ABOUTBOX) { CAboutDlgdlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID,lParam); }}//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,//thisisautomaticallydoneforyoubytheframework.voidCMyDlg::OnPaint(){CPaintDCdc(this);//devicecontextforpainting //先將整個游戲區(qū)域的圖像繪制到內(nèi)存位圖 GameDraw(&m_MemDC); //將內(nèi)存位圖中繪制好的圖像一次性拷貝到屏幕 dc.BitBlt(0,0,m_nCol*FRONTWIDTH,m_nCol*FRONTHEIGHT,&m_MemDC,0,0,SRCCOPY);}//Thesystemcallsthistoobtainthecursortodisplaywhiletheuserdrags//theminimizedwindow.HCURSORCMyDlg::OnQueryDragIcon(){ return(HCURSOR)m_hIcon;}CMyDlg::~CMyDlg(){ //釋放動態(tài)數(shù)組空間 delete[]m_map;}voidCMyDlg::StartNewGame(){ //初始化地圖,將地圖中所有方塊區(qū)域位置置為空方塊狀態(tài) for(intiNum=0;iNum<(m_nCol*m_nRow);iNum++) { m_map[iNum]=BLANK_STATE; } //部下隨機種子 srand(time(NULL)); //生成隨機地圖 //將所有匹配成對的動物物種放進一個臨時的地圖中 CDWordArraytmpMap; for(inti=0;i<(m_nCol*m_nRow)/6;i++) for(intj=0;j<6;j++) tmpMap.Add(i); //每次從上面的臨時地圖中取走(獲取后并在臨時地圖刪除) //一個動物放到地圖的空方塊上 for(i=0;i<m_nRow*m_nCol;i++) { //隨機挑選一個位置 intnIndex=(int(rand()*0.1+rand()*0.01+rand()))%tmpMap.GetSize(); //獲取該選定物件放到地圖的空方塊 m_map[i]=tmpMap.GetAt(nIndex); //在臨時地圖除去該動物 tmpMap.RemoveAt(nIndex); } //更新顯示 Invalidate(TRUE);}BOOLCMyDlg::IsLink(intx1,inty1,intx2,inty2){//X直連方式 if(x1==x2) { if(X1_Link_X2(x1,y1,y2)) returnTRUE; } //Y直連方式 elseif(y1==y2) { if(Y1_Link_Y2(x1,x2,y1)) returnTRUE; } //一個轉(zhuǎn)彎直角的聯(lián)通方式 if(OneCornerLink(x1,y1,x2,y2)) { returnTRUE; } //兩個轉(zhuǎn)彎直角的聯(lián)通方式 elseif(TwoCornerLink(x1,y1,x2,y2)) { returnTRUE; } returnFALSE;}BOOLCMyDlg::X1_Link_X2(intx,inty1,inty2){//保證y1的值小于y2 if(y1>y2) { //數(shù)據(jù)交換 intn=y1; y1=y2; y2=n; } //直通 for(inti=y1+1;i<=y2;i++) { if(i==y2) returnTRUE; if(m_map[i*m_nCol+x]!=BLANK_STATE) break; } //左通 if(XThrough(x-1,y1,FALSE)&&XThrough(x-1,y2,FALSE)) returnTRUE; //右通 if(XThrough(x+1,y1,TRUE)&&XThrough(x+1,y2,TRUE)) returnTRUE; returnFALSE;}//Y直接連通BOOLCMyDlg::LineX(intx,inty1,inty2){if(y1>y2) { inty=y1; y1=y2; y2=y; } for(inty=y1;y<=y2;y++) { if(m_map[y*m_nCol+x]!=BLANK_STATE) returnFALSE; if(y==y2) returnTRUE; } returnFALSE;}BOOLCMyDlg::LineY(intx1,intx2,inty){if(x1>x2) { intx=x1; x1=x2; x2=x; } for(intx=x1;x<=x2;x++) { if(m_map[y*m_nCol+x]!=BLANK_STATE) returnFALSE; if(x==x2) returnTRUE; } returnFALSE;}BOOLCMyDlg::OneCornerLink(intx1,inty1,intx2,inty2){ if(x1>x2) { intn=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; } if(y2<y1) { if(LineY(x1+1,x2,y1)&&LineX(x2,y1,y2+1)) returnTRUE; if(LineY(x2-1,x1,y2)&&LineX(x1,y2,y1-1)) returnTRUE; returnFALSE; } else { if(LineY(x1+1,x2,y1)&&LineX(x2,y1,y2-1)) returnTRUE; if(LineY(x2-1,x1,y2)&&LineX(x1,y2,y1+1)) returnTRUE; returnFALSE; } returnFALSE;}BOOLCMyDlg::TwoCornerLink(intx1,inty1,intx2,inty2){ if(x1>x2) { intn=x1; x1=x2; x2=n; n=y1; y1=y2; y2=n; } //右通 if(XThrough(x1+1,y1,TRUE)&&XThrough(x2+1,y2,TRUE)) returnTRUE; //左通 if(XThrough(x1-1,y1,FALSE)&&XThrough(x2-1,y2,FALSE)) returnTRUE; //上通 if(YThrough(x1,y1-1,FALSE)&&YThrough(x2,y2-1,FALSE)) returnTRUE; //下通 if(YThrough(x1,y1+1,TRUE)&&YThrough(x2,y2+1,TRUE)) returnTRUE; //右 for(intx=x1+1;x<m_nCol;x++) { if(m_map[y1*m_nCol+x]>-1) break; if(OneCornerLink(x,y1,x2,y2)) returnTRUE; } //左 for(x=x1-1;x>-1;x--) { if(m_map[y1*m_nCol+x]!=BLANK_STATE) break; if(OneCornerLink(x,y1,x2,y2)) returnTRUE; } //上 for(inty=y1-1;y>-1;y--) { if(m_map[y*m_nCol+x1]!=BLANK_STATE) break; if(OneCornerLink(x1,y,x2,y2)) returnTRUE; } //下 for(y=y1+1;y<m_nRow;y++) { if(m_map[y*m_nCol+x1]!=BLANK_STATE) break; if(OneCornerLink(x1,y,x2,y2)) returnTRUE; } returnFALSE;}BOOLCMyDlg::XThrough(intx,inty,BOOLbAdd){if(bAdd) { for(inti=x;i<m_nCol;i++) if(m_map[y*m_nCol+i]!=BLANK_STATE) returnFALSE; } else { for(inti=0;i<=x;i++) if(m_map[y*m_nCol+i]!=BLANK_STATE) returnFALSE; } returnTRUE;}BOOLCMyDlg::YThrough(intx,inty,BOOLbAdd){if(bAdd) { for(inti=y;i<m_nRow;i++) if(m_map[i*m_nCol+x]!=BLANK_STATE) returnFALSE; } else { for(inti=0;i<=y;i++) if(m_map[i*m_nCol+x]!=BLANK_STATE) returnFALSE; } returnTRUE;}BOOLCMyDlg::IsWin(){//檢測所有是否尚有非未被消除的方塊 //(非BLANK_STATE狀態(tài)) for(inti=0;i<m_nRow*m_nCol;i++) { if(m_map[i]!=BLANK_STATE) { returnFALSE; } } returnTRUE;}voidCMyDlg::OnLButtonDown(UINTnFlags,CPointpoint){ //TODO:Addyourmessagehandlercodehereand/orcalldefault //○1.計算鼠標點擊方塊的的位置 intx=point.x/FRONTWIDTH+(point.x%FRONTWIDTH?1:0)-1; inty=point.y/FRONTHEIGHT+(point.y%FRONTHEIGHT?1:0)-1; //○2.在游戲區(qū)域內(nèi)并且該區(qū)域還有該區(qū)域不是空的區(qū)域 if(x<m_nCol&&y<m_nRow&&m_map[y*m_nCol+x]!=BLANK_STATE) { //○3.假設尚未記錄第一個方塊 if(m_nX1==BLANK_STATE) { //○4記錄第一個方塊的位置 m_nX1=x; m_nY1=y; //獲取程序框架的設備環(huán)境 CDC*pWinDC=GetDC(); //臨時繪制點中的方塊外框 //只繪屏幕不載入內(nèi)存位圖 CPenmyPen; CPen*pOldPen; myPen.CreatePen(PS_SOLID,4,RGB(255,0,0)); pOldPen= pWinDC->SelectObject(&myPen); //方塊外框繪制,線條環(huán)繞繪制框架 pWinDC->MoveTo(x*FRONTWIDTH,y*FRONTHEIGHT); pWinDC->LineTo(x*FRONTWIDTH,(y+1)*FRONTHEIGHT); pWinDC->

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論