版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
..連連看游戲的設(shè)計與實現(xiàn)學(xué)生__蔡艷芳指導(dǎo)鄧廣慧摘要本文用VisualC++來設(shè)計與實現(xiàn)簡單的連連看游戲的基本功能,玩家可以在游戲區(qū)域中通過鍵盤控制來選取相同的兩個物件,采用特定的消除規(guī)則對它們進(jìn)行消除的操作,當(dāng)游戲區(qū)域中的所有方塊對都被消除后玩家即可勝利。本次課程設(shè)計對該游戲的算法以及游戲圖案的繪制進(jìn)行詳細(xì)的介紹。運(yùn)用連線相消的方法完成了連連看游戲。關(guān)鍵詞:VisualC++6.0;連連看;游戲;3D繪圖1引言1.1連連看游戲介紹游戲"連連看"顧名思義就是找出相關(guān)聯(lián)的東西,它來源于街機(jī)游戲《XX麻將》和《中國龍》,是給一堆圖案中的相同圖案進(jìn)行配對的簡單游戲,在20XX,一個叫做朱俊的網(wǎng)友將這種形式搬到了PC上,立刻成為辦公一族的新寵,并迅速傳遍了世界各地。飽受工作壓力的人們沒有太多的時間進(jìn)行復(fù)雜的游戲,而對于這種動動鼠標(biāo)就能過關(guān)的游戲情有獨鐘。之后村子的連連看風(fēng)靡版,阿達(dá)的連連看奧運(yùn)版,連連看反恐版,還有敏敏連連看,水晶連連看等遍地開花,造就了一個連連看的新世界。連連看游戲有多種地圖樣式和道具系統(tǒng)、大大加強(qiáng)了游戲的可玩性,是一款老少皆宜的休閑佳品。1.2課程設(shè)計的目的網(wǎng)絡(luò)小游戲制作的目的是滿足了人們休閑的需要,在緊張工作之余休閑類的小游戲能夠給人帶來最大程度的放松,也可以增進(jìn)人們之間的交流,溝通,通過游戲還可以認(rèn)識更多的朋友,也可以到達(dá)跨省、跨市,甚至跨國間人們互相娛樂的目的。另外也想通過本次課程設(shè)計將三年來所學(xué)的專業(yè)知識和其他方面的知識融入到實際應(yīng)用中。1.3主要問題開始制作游戲時,主要要解決的問題有以下幾個方面:如何設(shè)置整個游戲的界面;如何控制連連看游戲中隨機(jī)圖片的生成且每種圖片必須為偶數(shù)個;游戲開始后,判斷鼠標(biāo)兩次點擊的圖片能否消去,即圖片是否相同且圖片之間路徑的判斷。1.4課題實現(xiàn)技術(shù)的簡要說明VisualC++是一個功能強(qiáng)大的可視化軟件開發(fā)工具,VisualC++6.0不僅是一個C++編譯器,而且是一個基于Windows操作系統(tǒng)的可視化集成開發(fā)環(huán)境〔integrateddevelopmentenvironment,IDE。VisualC++6.0由許多組件組成,包括編輯器、調(diào)試器以及程序向?qū)ppWizard、類向?qū)lassWizard等開發(fā)工具。這些組件通過一個名為DeveloperStudio的組件集成為和諧的開發(fā)環(huán)境。VisualC++一直被認(rèn)為是目前最好的軟件開發(fā)工具之一,其在界面開發(fā)、執(zhí)行速度、代碼的移植性方面都有很強(qiáng)的優(yōu)勢。所以,實現(xiàn)本系統(tǒng),VC++是一個相對較好的選擇。2系統(tǒng)需求分析整個游戲程序包括了進(jìn)入記錄,圖片消去和過關(guān)結(jié)果三個階段,在處理鼠標(biāo)響應(yīng)事件中伴隨著3D繪圖。程序通過調(diào)試運(yùn)行,實現(xiàn)了設(shè)計目標(biāo),能夠滿足連連看游戲玩家的需要。2.1可行性分析〔1技術(shù)可行性分析技術(shù)上的可行性分析主要分析現(xiàn)有技術(shù)條件能否順利完成開發(fā)工作,硬件、軟件配置能否滿足開發(fā)者的需要,各類技術(shù)人員的數(shù)量,水平,來源等。連連看系統(tǒng)的工作主要是在開發(fā)者和玩家之間架起一座橋梁,能相互溝通信息和處理信息。這一特點非常適合計算機(jī)特點,通過網(wǎng)絡(luò)Internet技術(shù),發(fā)揮計算機(jī)的信息傳輸速度快、準(zhǔn)確度高的優(yōu)勢。計算機(jī)硬件和軟件技術(shù)的飛速發(fā)展,為系統(tǒng)的建設(shè)提供了技術(shù)條件?!?社會可行性分析社會可行性有時也稱為操作可行性,主要論證新系統(tǒng)在玩家在游戲過程中的感受與反饋信息。在當(dāng)前信息技術(shù)飛速發(fā)展的大環(huán)境下,計算機(jī)技術(shù)和軟件技術(shù)的更新使得游戲更加的易掌握。2.2功能需求分析關(guān)于連連看的功能描述如下:運(yùn)行游戲并進(jìn)行初始化工作,將整個游戲區(qū)域分成縱向和橫向擴(kuò)展的若干個小方塊,并且這些小方塊是由多種動物圖案成對地分布于游戲區(qū)域的不同位置。玩家可以通過選取相同的兩個物件來對它們進(jìn)行消除的操作,直到將游戲區(qū)域中的所有方塊對都被消除后為勝利。2.3性能需求分析<1>硬件環(huán)境處理器:InterCR300或是更高。內(nèi)存:128MB〔建議196MB。硬盤空間:20MB。<2>軟件環(huán)境操作系統(tǒng):Windows98或是Windows2000/WindowsNTServer4.0。3系統(tǒng)設(shè)計3.1系統(tǒng)功能設(shè)計連連看系統(tǒng)的設(shè)計流程圖如圖3.1所示。游戲框架的搭建游戲框架的搭建菜單的制作連線相消算法的設(shè)計與實現(xiàn)繪圖界面的設(shè)計連連看系統(tǒng)圖3.1連連看游戲的設(shè)計流程圖3.2系統(tǒng)功能模塊總設(shè)計這個游戲的主要類是游戲模式類,類名為CLinkToLinkDlg。這個類主要對包括圖案方塊的銷毀判斷,游戲勝利判斷以及整個游戲用戶交換功能的實現(xiàn)。它的圖如圖3.2所示。CLinkToLinkDlgm_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<>:voidIsLink<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圖3.2游戲模式類圖4系統(tǒng)詳細(xì)設(shè)計與實現(xiàn)4.1游戲地圖設(shè)計對于整個游戲區(qū)域,可以把它看作一個是由若干個小方塊構(gòu)成的地圖,而且每一個小方塊放置著不同的動物圖案,可將其稱之為圖案小方塊。這些圖案小方塊零散地分布在地圖的不同位置區(qū)域,并且每一個圖案小方塊都有與其對應(yīng)的完全一樣的另外一個小方塊,如圖4.1所示。圖4.1游戲地圖設(shè)計圖如圖4.1所示,整個游戲游戲區(qū)域被抽象成一個有坐標(biāo)位置屬性的平面,平面上零散地分布著若干個小方塊,并且這些小方塊的物種起碼是成對出現(xiàn)的。經(jīng)過前面的描述和分析后,可以把游戲區(qū)域地圖用一個數(shù)組m_map來表示。m_map是把地圖設(shè)計成一個動態(tài)分配的int整形一維數(shù)組,對地圖中的行列數(shù)的表達(dá),用一個轉(zhuǎn)換法則即可??梢栽贚inkToLinkDlg類對象定義中添加地圖核心數(shù)據(jù)的成員變量,具體如下://地圖位置相關(guān)屬性組 int* m_map;//動態(tài)地圖數(shù)據(jù)頭指針<一維數(shù)組> int m_nRow; //地圖的行數(shù)<虛擬> int m_nCol; //地圖的列數(shù)<虛擬>上面的成員變量中定義了一個整形指針標(biāo)量m_map,用于記錄動態(tài)分配出來的一維數(shù)組地圖空間的首地址。對于地圖區(qū)域中的某個小方塊的類型,可以用一個整形的ID來進(jìn)行識別。這里為標(biāo)識地圖的行列位置分別添加m_nRow和m_nCol變量?,F(xiàn)在,地圖的數(shù)據(jù)結(jié)構(gòu)已經(jīng)設(shè)計好。下面對游戲進(jìn)行初始化。由于方塊需要成對地出現(xiàn),因此在做地圖的初始化時,不僅僅是對動物種類做簡單的隨機(jī)取數(shù),然后將該隨機(jī)選取出來的物件放到地圖區(qū)域中去就了事,而是需要成對地對物種進(jìn)行成對選取,就是說地圖中的小方塊必須是偶數(shù)個。前面提到過,把地圖數(shù)組設(shè)置成動態(tài)分配方式,目的是讓其數(shù)據(jù)空間可以根據(jù)行列數(shù)的需求動態(tài)地獲取,而對于實際不同大小比例的地圖可以預(yù)先定義幾組關(guān)于行列數(shù)的宏來實現(xiàn)。當(dāng)需要創(chuàng)建時,根據(jù)宏值的不同分配不同大小的地圖空間即可。接下來在LinkToLinkDlg類的構(gòu)造函數(shù)對地圖數(shù)據(jù)進(jìn)行相關(guān)的初始化:#defineROWCOUNT8 //行數(shù)#defineCOLCOUNT12 //列數(shù)CLinkToLinkDlg::CLinkToLinkDlg<CWnd*pParent/*=NULL*/> :CDialog<CLinkToLinkDlg::IDD,pParent>{……//初始化行列數(shù) m_nRow=ROWCOUNT; m_nCol=COLCOUNT; //根據(jù)行列數(shù)動態(tài)分配內(nèi)核數(shù)據(jù)數(shù)組空間 m_map=newint[m_nRow*m_nCol];}CLinkToLinkDlg::~CLinkToLinkDlg<>{ //釋放動態(tài)數(shù)組空間 delete[]m_map;}在LinkToLinkDlg類對象的實現(xiàn)中,定義了一些關(guān)于地圖行列數(shù)的宏,如ROWCOUNT和COLCOUNT,并且在LinkToLinkDlg類對象的構(gòu)造函數(shù)中,進(jìn)行了行列的真實確認(rèn)賦值,并根據(jù)當(dāng)前行列數(shù)的大小對地圖數(shù)據(jù)空間進(jìn)行動態(tài)創(chuàng)建。因為地圖數(shù)據(jù)是用new在堆棧動態(tài)創(chuàng)建的,所以在銷毀該對象時要將這些內(nèi)存空間釋放,如代碼所示在LinkToLinkDlg類對象的析構(gòu)函數(shù)中調(diào)用delete將m_map指向的所有空間都釋放掉。4.2初始化工作接下來,再分配好的空間中放上適當(dāng)?shù)膱D案方塊物件,對數(shù)據(jù)進(jìn)行初始化。即需要對地圖空間內(nèi)的數(shù)據(jù)進(jìn)行成對性的隨機(jī)布局,因此可以將該功能的實現(xiàn)封裝在StartNewGame<>函數(shù)里面,其代碼如下:voidCLinkToLinkDlg::StartNewGame<>{ //初始化地圖,將地圖中所有方塊區(qū)域位置置為空方塊狀態(tài) for<intiNum=0;iNum<<m_nCol*m_nRow>;iNum++> { m_map[iNum]=BLANK_STATE; } //部下隨機(jī)種子 srand<time<NULL>>; //生成隨機(jī)地圖 //將所有匹配成對的動物物種放進(jìn)一個臨時的地圖中 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++> { //隨機(jī)挑選一個位置 intnIndex=<int<rand<>*0.1+rand<>*0.01+rand<>>>%tmpMap.GetSize<>; //獲取該選定物件放到地圖的空方塊 m_map[i]=tmpMap.GetAt<nIndex>; //在臨時地圖除去該動物 tmpMap.RemoveAt<nIndex>; } //更新顯示 Invalidate<TRUE>;}在游戲進(jìn)行初始化的過程中,應(yīng)該先對整個地圖中的各個區(qū)域做必要的初始化操作,將它們的狀態(tài)設(shè)置為BLANK_START空白方塊狀態(tài)〔無動物圖案方塊,關(guān)于BLANK_START空白方塊狀態(tài)的定義,跟其他動物方塊的物種定義表達(dá)類似,也是用整數(shù)ID來對它進(jìn)行標(biāo)識,不過不同的是,由于他代表該方塊區(qū)域無圖案,所以這里用-1的宏值來表示,具體定義如下:#defineBLANK_STATE-1//空方塊<沒有任何動物>可以看到,對圖案方塊的布局,先用srand〔函數(shù)對時間函數(shù)布下隨機(jī)種子,然后調(diào)用rand〔函數(shù)對具體的圖案方塊的種類進(jìn)行隨機(jī)的獲取。在這里需要引入一個臨時地圖tmpMap,該臨時地圖的大小與內(nèi)核數(shù)據(jù)地圖的大小一致,并且先添置好4組完全一樣的圖案類型ID數(shù)據(jù)〔0~〔m_nCol*m_nRow/4,然后再將已經(jīng)安放在tmpMap中的圖案作隨機(jī)抽取,并放到內(nèi)核地圖數(shù)據(jù)中去,將取出的元素從tmpMap中除去。4.3圖案方塊的連接判斷對于選中的兩個方塊的銷毀,他們必須符合下面3個條件:〔1選中的兩個方塊圖案相同?!?選中的兩個方塊之間沒有障礙物阻礙的情況下,可以用若干個垂直的直線線段連接起來?!?這些將它們連接起來的直線線段的折點不超過兩個〔連接線由x軸和軸的平行線組成?,F(xiàn)在針對〔2和〔3進(jìn)行分析,如圖4-3。圖4-2所示可知道,同種物件的連接方式大致可以分成以下3種:〔1直接方式?!?有一個折點的垂直線段連接。〔3有兩個折點的垂直線段連接.。=1\*GB3①直接連接方式在直接連接方式中,必須要求所選定的兩個方塊在同一水平直線上〔可以為x方向或y方向,并且兩個方塊之間沒有任何其他圖案方塊。=2\*GB3②一個這點連接方式所選定的兩個方塊如果通過折點的方式連接,那么對于折點來說,每個折點必定有且至少有一個坐標(biāo)〔x或y是和其中一個目標(biāo)點相同的,即折點必定在兩個目標(biāo)點所在的x方向或y方向的直線上。此外,對于一個折點連接的情況,折點應(yīng)該為第一個選中方塊的橫向線或縱向線與第二個選中方塊的縱向線和橫向線相交而得出。=3\*GB3③兩個折點的連接方式這種方式的兩個折點所連成的直線與兩物件的直接連線可以構(gòu)成平行線,因此可以根據(jù)這個規(guī)律,將這條水平線在游戲區(qū)域允許的條件上下移動,然后通過判斷整條帶垂直折線點的曲線之間有無障礙物方式來確定是否可以連同。這種情況可以分為兩種情況:1選中的兩圖案方塊在同一直線,兩折點間的直連線可在其這兩個方塊之間的空間位置作移動,其約束是不超過游戲邊界區(qū)域。2選中的兩圖案方塊不在同一直線,兩折點間的直連線可在兩個方塊之間的空間位置作移動,其約束是兩方塊之間的區(qū)域。經(jīng)過上面詳細(xì)的分析后,可以對選定的兩方塊是否可以作抵消操作可以這樣設(shè)計下去。首先,對簡單的直接連情況進(jìn)行判斷,看其是否符合條件,假如不能,再加深一個級別的復(fù)雜度,對一個折點的情況進(jìn)行判斷,依次類推,如下圖4.2所示。圖4.2連線規(guī)則圖連線流程圖如圖4.3所示。圖4.3連線流程圖根據(jù)如圖4.3所示的流程圖,可以對選定的兩個方塊〔分別在〔x1,y1以及〔x2,y2兩個區(qū)域位置,其中x,y分別代表行與列的概念是否可以抵消作以下實現(xiàn)。把該功能封裝在IsLink〔函數(shù)里面,其代碼如下所示://判斷選中的兩個方塊是否可以消除BOOLCLinkToLinkDlg::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<>這兩種情況進(jìn)行判斷,如果尚未取得結(jié)果,再通過調(diào)用OneCornerLink〔函數(shù)對一個折點的情況進(jìn)行判斷,或者更糟糕的時候調(diào)用TwoCornerLink〔函數(shù)對兩個這點的情況進(jìn)行判斷,然后得出最終結(jié)果。下面將對上面涉及到的子功能模塊進(jìn)行實現(xiàn),代碼如下所示://X直接連通BOOLCLinkToLinkDlg::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直接連通BOOLCLinkToLinkDlg::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;}//是否同一直線通//BOOLCLinkToLinkDlg::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;}////是否同一直線通//BOOLCLinkToLinkDlg::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;}//eq\o\ac<○,1>直角接口連通BOOLCLinkToLinkDlg::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;}//eq\o\ac<○,2>直角接口連通BOOLCLinkToLinkDlg::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;}BOOLCLinkToLinkDlg::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;}BOOLCLinkToLinkDlg::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種情況,如4.4圖所示。圖4.4連接方式圖下面簡單介紹直通和左通兩種情況〔右通與左通類似〔1直通:直通就是在選定的兩個方塊直連線中,沒有被任何方塊所阻礙?!?左通:左通就是選定的兩個方塊的直連線之間有其他方塊阻礙,但是通過它的左側(cè)可以將它們無阻礙地連通。直連方式中的此種情況跟前面分析的兩個折點連接方式中的其中一點相當(dāng)類似,如4-5圖所示。圖4.5兩折通道圖它們之間的區(qū)別就是,左通的連接線直接在其相鄰的位置連通,從而不構(gòu)成垂直折點的效果,而兩個折點連同方式中的其中一個類似的情況是,線的連通起碼要偏移一個方塊的距離來形成連通。同理,有上通和下通,它們的情況與左通和右通類似。4.4游戲勝利的判斷要判斷游戲的勝利,實現(xiàn)起來比較簡單,只需對地圖中的所有區(qū)域的狀態(tài)進(jìn)行檢測就可里了,只要檢測到地圖中有一個圖案方塊還沒有被抵消,則證明游戲沒有結(jié)束,完成判斷。其代碼如下所示://檢測是否已經(jīng)贏得了游戲BOOLCLinkToLinkDlg::IsWin<void>{ //檢測所有是否尚有非未被消除的方塊 //<非BLANK_STATE狀態(tài)> for<inti=0;i<m_nRow*m_nCol;i++> { if<m_map[i]!=BLANK_STATE> { returnFALSE; } } returnTRUE;}游戲勝利界面如圖4.6所示。圖4.6通關(guān)圖至此,已經(jīng)完成整個游戲基本的內(nèi)部相關(guān)功能模塊的運(yùn)算,接下來實現(xiàn)用戶的交互部分的功能。4.5鼠標(biāo)交互功能的實現(xiàn)對于用戶交互的實現(xiàn),這里選擇鼠標(biāo)交互方式。下面簡單描述一下通過鼠標(biāo)交互方式實現(xiàn)的功能。鼠標(biāo)選取兩個圖案方塊后,程序?qū)⒆詣优袛嗨x定的兩個方塊是否能進(jìn)行抵消操作,能則進(jìn)行抵消操作。在游戲過程中,我們不斷重復(fù)上面描述的功能,直到游戲的勝利結(jié)束。下面將鼠標(biāo)事件處理工作歸納為如圖4.7所示的流程。圖4.7鼠標(biāo)交互流程圖對于鼠標(biāo)交互功能的實現(xiàn),可以通過ClassWizard對鼠標(biāo)左鍵被按下時觸發(fā)的命令消息WM_LBUTTONDOWN進(jìn)行攔截,并重寫該消息的處理函數(shù)OnLButtonDown〔,其程序清單如下所示:voidCLinkToLinkDlg::OnLButtonDown<UINTnFlags,CPointpoint>{ //eq\o\ac<○,1.>計算鼠標(biāo)點擊方塊的的位置 intx=point.x/FRONTWIDTH+<point.x%FRONTWIDTH?1:0>-1; inty=point.y/FRONTHEIGHT+<point.y%FRONTHEIGHT?1:0>-1; //eq\o\ac<○,2.>在游戲區(qū)域內(nèi)并且該區(qū)域還有該區(qū)域不是空的區(qū)域 if<x<m_nCol&&y<m_nRow&&m_map[y*m_nCol+x]!=BLANK_STATE> {//eq\o\ac<○,3.>假設(shè)尚未記錄第一個方塊 if<m_nX1==BLANK_STATE> {//eq\o\ac<○,4>記錄第一個方塊的位置 m_nX1=x; m_nY1=y;//獲取程序框架的設(shè)備環(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)場恢復(fù) pWinDC->SelectObject<pOldPen>; } else { //eq\o\ac<○,5.>判斷是否點擊的方塊非本身,是否點擊同一種動物 if<<m_nX1!=x||m_nY1!=y>&& m_map[m_nY1*m_nCol+m_nX1]==m_map[y*m_nCol+x] > {//eq\o\ac<○,6.>檢測是否可以消除 if<IsLink<m_nX1,m_nY1,x,y>> {//eq\o\ac<○,7.>數(shù)據(jù)清理 m_map[m_nY1*m_nCol+m_nX1]=BLANK_STATE; m_map[y*m_nCol+x]=BLANK_STATE; } }//eq\o\ac<○,8.>清空記錄方塊的值 m_nX1=BLANK_STATE; m_nY1=BLANK_STATE; //通知重繪 Invalidate<FALSE>; } } //察看是否已經(jīng)勝利 if<IsWin<>> { MessageBox<"恭喜您勝利闖關(guān),即將開始新局">; StartNewGame<>; }}按照預(yù)先設(shè)計出的鼠標(biāo)事件處理流程,上面已經(jīng)將它轉(zhuǎn)換成具體的實現(xiàn)代碼。下面將按照流程的子功能模塊的劃分方式,對整個功能模塊的具體協(xié)調(diào)和實現(xiàn)過程進(jìn)行簡單的描述?!?首先,利用鼠標(biāo)的當(dāng)前坐標(biāo)位置point對每個小單元方塊的寬度FRONTWIDTH和高度FRONTHEIGHT分別取模,獲取當(dāng)前鼠標(biāo)落點所在的游戲區(qū)域的具體行列數(shù)〔x,y?!?判斷出該行列數(shù)〔x,y是否符合條件。保證運(yùn)算出來的行數(shù)x和列數(shù)y的預(yù)定義區(qū)域最大的行數(shù)m_nCol和列數(shù)m_nRow內(nèi),并且點擊的區(qū)域狀態(tài)不是空白方塊區(qū)域BLANK_STATE〔3對判斷此次鼠標(biāo)書劍的選取是否與第一個方塊的選取一樣,只需通過用于記錄第一個被選中的方塊的行列數(shù)的成員變量m_nX1是否為有效即可。這里將m_nX1以及m_nY1來記錄它所在的行、列數(shù),并且每次經(jīng)過判斷后都會將它們的狀態(tài)恢復(fù)為空白無選中狀態(tài)BLANK_STATE。關(guān)于這兩個用作記錄第一個選中圖案方塊行列數(shù)的成員變量,在對話框類中的具體定義如下所示: int m_nX1;//鼠標(biāo)選中的記錄方塊列數(shù) int m_nY1; //鼠標(biāo)選中的記錄方塊行數(shù)〔4對于本次選中的方塊為第一選中的情況,先用m_nX1和m_nY1對當(dāng)前的選中方塊位置做記錄,然后直接在屏幕的該區(qū)域繪制圖像,為該方塊區(qū)域添加一個紅色的矩形外邊框,用以提示用戶當(dāng)前的第1個圖案方塊選中所在的位置。需要注意的是,對于標(biāo)記方塊的加亮邊框繪制是通過GetDC〔函數(shù)來獲取對話框窗體〔屏幕的設(shè)備環(huán)境,對繪制的圖像數(shù)據(jù)沒有作歷史記錄的方式來繪制的?!?在這一處理中,對該選定方塊作一些判斷,以便更高效地處理。判斷選中的方塊與前一方塊是否為同一圖案方塊,并且此次選擇不與上一次選定的方塊為同一方塊,然后才跳到下一步對兩個選定的方塊是否可以抵消的流程中去?!?調(diào)用前面已經(jīng)實現(xiàn)的答功能函數(shù)IsLink〔來判斷當(dāng)前所選定的兩個圖案方塊是否可以抵消?!?如果可以抵消,對選中的兩個方塊在內(nèi)部核心地圖對應(yīng)的數(shù)據(jù)狀態(tài)作適當(dāng)?shù)男薷?將它們的狀態(tài)記作已經(jīng)被銷毀的空方塊狀態(tài)BLANK_STATE。〔8完成第二個圖案的選取與相關(guān)的功能操作后,我們需要前面已經(jīng)選去第1個方塊位置的記錄作清理工作,以便下一個新方塊的選擇?!?最后,判斷此次的鼠標(biāo)操作是否已經(jīng)勝利結(jié)束,如果是則給予用戶提示,然后重新開適新的一關(guān)。4.6連連看新紀(jì)錄的實現(xiàn)首先創(chuàng)建兩個對話框模板,一個用作當(dāng)用戶勝利結(jié)束游戲并打破歷史記錄后彈出的簽名記錄對話框模板IDD_DLG_NEWRECORD,另外一個是用以顯示以往最高的游戲記錄的對話框模板IDD_DLG_HERO。分別如圖4.8和圖4.9所示。圖4.8添加新記錄圖圖4.9積分記錄圖4.7繪圖功能的實現(xiàn)在完成以上所有的交互以及內(nèi)部數(shù)據(jù)關(guān)聯(lián)的運(yùn)算處理后,最后要將這些數(shù)據(jù)展現(xiàn)到屏幕上。<1>位圖圖像的準(zhǔn)備首先,準(zhǔn)備好一個帶有不同動物種類的位圖,以及一個3D邊框效果的位圖,如圖4.10所示。通過資源編輯器將它們引入到項目中來,并將他媽的ID分別命名為IDB_BMP_ANIMAL和IDB_BITMAP_3DFRAMES。圖4.10繪圖圖像<2>繪圖方案的設(shè)計對于游戲的繪制實現(xiàn),這里采用內(nèi)存位圖映射的方式,先將整個游戲區(qū)域的圖像繪制到內(nèi)存位圖中,然后再一次性地將它拷貝到屏幕上予以顯示,如圖4.11所示。圖4.11繪圖方案設(shè)計流程圖<3>繪圖資源的載入與初始化根據(jù)圖3-1.所示的描述方案,可以在內(nèi)存創(chuàng)建兩個內(nèi)存位圖,并對它們的圖像進(jìn)行載入。在需要使用的時候,則可以從這些內(nèi)存位圖中直接去拷貝,并繪制到游戲區(qū)域內(nèi)存位圖中去,接下來添加關(guān)于繪圖的成員變量,如下所示。//內(nèi)存位圖屬性組 CDC m_mem3DBkDC;//3D框架的內(nèi)存設(shè)備環(huán)境 CBitmapm_mem3DBkBmp;//3D框架的內(nèi)存位圖 CDC m_memAnimalDC;//動物圖像的內(nèi)存設(shè)備環(huán)境 CBitmapm_memAnimalBmp;//動物圖像的內(nèi)存位圖 CDC m_MemDC;//游戲區(qū)域內(nèi)存設(shè)備環(huán)境 CBitmapm_memBitmap;//游戲區(qū)域內(nèi)存位圖這里,對3D框架位圖以及動物圖案位圖分別創(chuàng)建了對應(yīng)的設(shè)備環(huán)境m_mem3DBkDC和m_memAnimalDC,并且位它們分配了關(guān)聯(lián)的內(nèi)存位圖變量m_mem3DBkBmp和m_memAnimalBmp。而對于游戲區(qū)域的內(nèi)存繪制,亦為它創(chuàng)建了一個內(nèi)存設(shè)備環(huán)境m_MemDC以及關(guān)聯(lián)的內(nèi)存位圖m_memBitmap。在完成以上工作后,需要在程序開始運(yùn)行的時候,一次行對它們進(jìn)行適當(dāng)?shù)某跏蓟???梢詫⑦@些繪圖的具體初始化加載在CLinkToLinkDlg對話框類的初始話函數(shù)OnInitDialog中,代碼如下所示。 //獲取程序框架的設(shè)備環(huán)境 CDC*pWinDC=GetDC<>; //內(nèi)存設(shè)備環(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)獲取該程序的屏幕設(shè)備環(huán)境,然后在將前面提到的3個內(nèi)存設(shè)備環(huán)境以及關(guān)聯(lián)的內(nèi)存位圖與該屏幕設(shè)備環(huán)境兼容,而對于兩個用于存儲外部位圖圖像的內(nèi)存位圖,則調(diào)用LoadBitmap<>函數(shù)對他們相應(yīng)的位圖資源進(jìn)行載入以及相關(guān)的初始化工作。<4>游戲區(qū)域的繪制在完成繪圖物件的初始化工作后,接下來就可以對整個游戲區(qū)域的繪制進(jìn)行實現(xiàn),對整個游戲區(qū)域的繪制,可以將風(fēng)卷在GameDraw<>函數(shù)里,其代碼清單如下所示。voidCLinkToLinkDlg::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ū)域中有動物圖案的方塊進(jìn)行3D邊框的繪制,繪制的方法示從3D邊框的內(nèi)存位圖中拷貝,然后在根據(jù)內(nèi)核地圖中每一個方框區(qū)域的圖案物種從動物內(nèi)存位圖m_memAnimalBmp中通過與它關(guān)聯(lián)的m_memAnimalDC進(jìn)行動物圖案的拷貝。5系統(tǒng)測試游戲的整個運(yùn)行界面很簡單,沒有菜單欄,只有游戲區(qū)域的圖形顯示,因此,只需要用對話框模板的方式去搭建整個框架即可。首先,創(chuàng)建一個基于對話框模板的項目LinkToLink,如圖5.1所示。圖5.1創(chuàng)建工程LinkToLink在創(chuàng)建過程的第一步"MFC應(yīng)用程序向?qū)А襟E1"中應(yīng)該選擇"基本對話框"選項,確保應(yīng)用程序的創(chuàng)建是對話框模板,如圖5.2所示。圖5.2創(chuàng)建對話框游戲的整體運(yùn)行效果如圖5.3所示。圖5.3連連看游戲運(yùn)行界面圖結(jié)束語本次課程設(shè)計是用VC++來設(shè)計與實現(xiàn)簡單的連連看游戲的基本功能,對該游戲的算法以及游戲圖案的繪制進(jìn)行詳細(xì)的介紹,其中核心內(nèi)容包括圖案方塊的銷毀判斷,游戲勝利判斷以及整個游戲用戶交換功能的實現(xiàn)。算法比較簡單,運(yùn)行速度快。但是,游戲?qū)崿F(xiàn)的功能單一化及界面較簡單,可以考慮不同難度系數(shù)的游戲,設(shè)置多種級別。此外,還可以為游戲設(shè)計外掛。這次除了在鄧?yán)蠋煹木薮髱椭?班上同學(xué)也給予了很大的幫助,我們在一起探討,共同解決遇到的問題,這讓我在開發(fā)中少走了許多彎路。在此,我由衷地表示感謝!參考文獻(xiàn)[1]楊永國.VisualC++6.0實用教程.清華大學(xué)出版社,2004[2]唐俊明.VisualC++6.0編程實例與技巧.高等教育出版,2002[3]潘錦平.軟件系統(tǒng)開發(fā)技術(shù).XX電子科技大學(xué)出版社,1997[4]張海藩.軟件工程導(dǎo)論.清華大學(xué)出版社.2008附件//LinkToLinkDlg.cpp:implementationfile#include"stdafx.h"#include"LinkToLink.h"#include"LinkToLinkDlg.h"#ifdef_DEBUG#definenewDEBUG_NEW#undefTHIS_FILEstaticcharTHIS_FILE[]=__FILE__;#endif#defineBKCOLORRGB<128,128,128> //背景顏色#defineFRONTWIDTH <39+2> //前面方塊的寬度#defineFRONTHEIGHT <39+12> //前面方塊的高度#defineBKWIDTH 46 //背景方塊的寬度#defineBKHEIGHT56 //背景方塊的高度#defineROWCOUNT8 //行數(shù)#defineCOLCOUNT12 //列數(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 //NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32}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<>///////////////////////////////////////////////////////////////////////////////CLinkToLinkDlgdialogCLinkToLinkDlg::CLinkToLinkDlg<CWnd*pParent/*=NULL*/> :CDialog<CLinkToLinkDlg::IDD,pParent>{ //{{AFX_DATA_INIT<CLinkToLinkDlg> //NOTE:theClassWizardwilladdmemberinitializationhere //}}AFX_DATA_INIT //NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32 m_hIcon=AfxGetApp<>->LoadIcon<IDR_MAINFRAME>; //記錄方塊置為無效狀態(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];}CLinkToLinkDlg::~CLinkToLinkDlg<>{ //釋放動態(tài)數(shù)組空間 delete[]m_map;}voidCLinkToLinkDlg::DoDataExchange<CDataExchange*pDX>{ CDialog::DoDataExchange<pDX>; //{{AFX_DATA_MAP<CLinkToLinkDlg> //NOTE:theClassWizardwilladdDDXandDDVcallshere //}}AFX_DATA_MAP}BEGIN_MESSAGE_MAP<CLinkToLinkDlg,CDialog> //{{AFX_MSG_MAP<CLinkToLinkDlg> ON_WM_SYSCOMMAND<> ON_WM_PAINT<> ON_WM_QUERYDRAGICON<> ON_WM_LBUTTONDOWN<> //}}AFX_MSG_MAPEND_MESSAGE_MAP<>///////////////////////////////////////////////////////////////////////////////CLinkToLinkDlgmessagehandlersBOOLCLinkToLinkDlg::OnInitDialog<>{ CDialog::OnInitDialog<>; //Add"About..."menuitemtosystemmenu. //IDM_ABOUTBOXmustbeinthesystemcommandrange. ASSERT<<IDM_ABOUTBOX&0xFFF0>==IDM_ABOUTBOX>; ASSERT<IDM_ABOUTBOX<0xF000>; CMenu*pSysMenu=GetSystemMenu<FALSE>; if<pSysMenu!=NULL> { CStringstrAboutMenu; strAboutMenu.LoadString<IDS_ABOUTBOX>; if<!strAboutMenu.IsEmpty<>> { pSysMenu->AppendMenu<MF_SEPARATOR>; pSysMenu->AppendMenu<MF_STRING,IDM_ABOUTBOX,strAboutMenu>; } } //獲取程序框架的設(shè)備環(huán)境 CDC*pWinDC=GetDC<>; //內(nèi)存設(shè)備環(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}voidCLinkToLinkDlg::OnSysCommand<UINTnID,LPARAMlParam>{ if<<nID&0xFFF0>==IDM_ABOUTBOX> { CAboutDlgdlgAbout; dlgAbout.DoModal<>; } else { CDialog::OnSysCommand<nID,lParam>; }}//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,//thisisautomaticallydoneforyoubytheframework.voidCLinkToLinkDlg::StartNewGame<>{ //初始化地圖,將地圖中所有方塊區(qū)域位置置為空方塊狀態(tài) for<intiNum=0;iNum<<m_nCol*m_nRow>;iNum++> { m_map[iNum]=BLANK_STATE; } //部下隨機(jī)種子 srand<time<NULL>>; //生成隨機(jī)地圖 //將所有匹配成對的動物物種放進(jìn)一個臨時的地圖中 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++> { //隨機(jī)挑選一個位置 intnIndex=<int<rand<>*0.1+rand<>*0.01+rand<>>>%tmpMap.GetSize<>; //獲取該選定物件放到地圖的空方塊 m_map[i]=tmpMap.GetAt<nIndex>; //在臨時地圖除去該動物 tmpMap.RemoveAt<nIndex>; } //更新顯示 Invalidate<TRUE>;}////游戲區(qū)域的繪制//voidCLinkToLinkDlg::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>; } }}voidCLinkToLinkDlg::OnPaint<>{/* if<IsIconic<>> { CPaintDCdc<this>;//devicecontextforpainting SendMessage<WM_ICONERASEBKGND,<WPARAM>dc.GetSafeHdc<>,0>; //Centericoninclientrectangle intcxIcon=GetSystemMetrics<SM_CXICON>; intcyIcon=GetSystemMetrics<SM_CYICON>; CRectrect; GetClientRect<&rect>; intx=<rect.Width<>-cxIcon+1>/2; inty=<rect.Height<>-cyIcon+1>/2; //Drawtheicon dc.DrawIcon<x,y,m_hIcon>; } else { CDialog::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.HCURSORCLinkToLinkDlg::OnQueryDragIcon<>{ return<HCURSOR>m_hIcon;}voidCLinkToLinkDlg::OnLButtonDown<UINTnFlags,CPointpoint>{ //1.計算鼠標(biāo)點擊方塊的的位置 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.假設(shè)尚未記錄第一個方塊 if<m_nX1==BLANK_STATE> { //4.記錄第一個方塊的位置 m_nX1=x; m_nY1=y; //獲取程序框架的設(shè)備環(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)場恢復(fù) 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<>; }}BOOLCLinkToLinkDlg::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直接連通//BOOLCLinkToLinkDlg::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;}////是否同一直線通//BOOLCLinkToLinkDlg::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;}////是否同一直線通//BOOLCLinkToLinkDlg::LineY<intx1,intx2,inty>{ if<x1>
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 菏澤學(xué)院《篆書技法》2021-2022學(xué)年第一學(xué)期期末試卷
- 菏澤學(xué)院《體育科學(xué)研究方法》2023-2024學(xué)年第一學(xué)期期末試卷
- 菏澤學(xué)院《全球氣候變化對人類活動的影響》2022-2023學(xué)年第一學(xué)期期末試卷
- 菏澤學(xué)院《常微分方程》2021-2022學(xué)年第一學(xué)期期末試卷
- 河南師范大學(xué)《學(xué)校社會工作》2023-2024學(xué)年第一學(xué)期期末試卷
- 河南師范大學(xué)《社會研究方法》2022-2023學(xué)年第一學(xué)期期末試卷
- 河南師范大學(xué)《行政法與行政訴訟法》2021-2022學(xué)年第一學(xué)期期末試卷
- 河南師范大學(xué)《法國文化賞析》2021-2022學(xué)年第一學(xué)期期末試卷
- 2019年魯教版物理九年級上冊知識點練習(xí)第九十三篇
- 讀《教育大未來》有感
- 人教版2024新版七年級上冊數(shù)學(xué)期中模擬測試卷(含答案解析)
- 專題25 圓的基本性質(zhì)(分層精練)(解析版)
- GB/T 18029.8-2024輪椅車第8部分:靜態(tài)強(qiáng)度、沖擊強(qiáng)度及疲勞強(qiáng)度的要求和測試方法
- 中華民族共同體概論課件專家版9第九講 混一南北和中華民族大統(tǒng)合(元朝時期)
- 電梯日管控、周排查、月調(diào)度內(nèi)容表格
- 《戰(zhàn)爭與和平法》讀書筆記思維導(dǎo)圖
- 電力系統(tǒng)的故障類型及原因分析
- 如何實現(xiàn)深部找礦新突破
- 產(chǎn)品總監(jiān)績效考核表
- 新能源充電樁項目風(fēng)險投資報告(范文)
- 防火墻在企業(yè)局域網(wǎng)中的架設(shè)及配置方法
評論
0/150
提交評論