版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
俄羅斯方塊實(shí)驗(yàn)報(bào)告編寫(xiě)“俄羅斯方塊”游戲1、問(wèn)題分析。 編寫(xiě)俄羅斯方塊游戲,首先是界面問(wèn)題,要有一個(gè)相對(duì)美觀的游戲界面,可以有很多種解決的方法,可以用DOS的界面,也可以用MFC做。 界面做好后,最重要的就是七個(gè)方塊如何存放,翻轉(zhuǎn),顯示等等一系列問(wèn)題,首先,我們要把這七個(gè)方塊用一種數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)起來(lái);其次,在游戲中將這七個(gè)方塊隨機(jī)挑選出來(lái)并顯示在屏幕上,根據(jù)鍵盤(pán)事件進(jìn)行旋轉(zhuǎn);最后,判斷到達(dá)底部的方塊是簡(jiǎn)單疊加還是引發(fā)消除事件。 普通俄羅斯方塊游戲中,只有七個(gè)基本方塊:|,Z,N,L,7,|-,O,方塊都可以畫(huà)在一個(gè)4*4的方格中。于是就有兩個(gè)方法:一個(gè)是只存儲(chǔ)七個(gè)方塊,在游戲運(yùn)行的時(shí)候計(jì)算旋轉(zhuǎn)后的方塊形狀;另一個(gè)是將所有的方塊全部存儲(chǔ)起來(lái),在游戲運(yùn)行的時(shí)候計(jì)算取其中的哪個(gè)方塊。
另外,考慮到4*4是16,而一個(gè)int正好是16位(TC2是16位,其他的是32位),所以可以把一個(gè)方塊存儲(chǔ)在一個(gè)int數(shù)據(jù)中,取出的時(shí)候,判斷它的每個(gè)bit位,為1處有小方塊,為0處是空白。
所以可以分別用二維數(shù)組和bit的方法來(lái)表示這些方塊。 對(duì)于二維數(shù)組而言,其控制旋轉(zhuǎn)的操作會(huì)很簡(jiǎn)單,就是控制數(shù)組的行列以決定到底該取出哪一種方塊,所以程序中我會(huì)采用這種方法。如何控制方塊的下落速度,如何讓實(shí)現(xiàn)左移,右移,下落,如何銷(xiāo)行,如何計(jì)分,又如何加速等等都是需要考慮的問(wèn)題。對(duì)于控制方塊的下落速度,首先應(yīng)該現(xiàn)弄明白方塊是怎樣下落的,目前最常用的就是每隔一定得時(shí)間進(jìn)行重新繪圖,就像動(dòng)畫(huà)片一樣,當(dāng)很多副相關(guān)的畫(huà)面不斷在人眼前播放,由于人眼的掩蔽效應(yīng)就會(huì)形成動(dòng)著的畫(huà)面,看起來(lái)就是物體在那里移動(dòng),于此原理相同,當(dāng)改變方塊在畫(huà)面上的位置,再以一定得時(shí)間間隔進(jìn)行重新刷圖,其效果看起來(lái)就是方塊在移動(dòng);也就是說(shuō)控制方塊下落速度的其實(shí)就是控制重新繪圖的時(shí)間間隔,控制時(shí)間的函數(shù)有以下幾種:調(diào)用函數(shù)SetTimer()設(shè)置定時(shí)間隔,如SetTimer(0,200,NULL)即為設(shè)置200毫秒的時(shí)間間隔。在應(yīng)用程序中增加定時(shí)響應(yīng)函數(shù)OnTimer(),并在該函數(shù)中添加響應(yīng)的處理語(yǔ)句,用來(lái)完成時(shí)間到時(shí)的操作。這種定時(shí)方法是非常簡(jiǎn)單的,但其定時(shí)功能如同Sleep()函數(shù)的延時(shí)功能一樣,精度較低,只可以用來(lái)實(shí)現(xiàn)諸如位圖的動(dòng)態(tài)顯示等對(duì)定時(shí)精度要求不高的情況,而在精度要求較高的條件下,這種方法應(yīng)避免采用。精度時(shí)控函數(shù),在要求誤差不大于1毫秒的情況下,可以采用GetTickCount()函數(shù),該函數(shù)的返回值是DWORD型,表示以毫秒為單位的計(jì)算機(jī)啟動(dòng)后經(jīng)歷的時(shí)間間隔。高精度時(shí)控函數(shù)對(duì)于一般的實(shí)時(shí)控制,使用GetTickCount()函數(shù)就可以滿(mǎn)足精度要求,但要進(jìn)一步提高計(jì)時(shí)精度,就要采用QueryPerformanceFrequency()函數(shù)和QueryPerformanceCounter()函數(shù)。這兩個(gè)函數(shù)是VC提供的僅供Windows9X使用的高精度時(shí)間函數(shù),并要求計(jì)算機(jī)從硬件上支持高精度計(jì)時(shí)器。接下來(lái)就應(yīng)該考慮如何實(shí)現(xiàn)左移,右移,下移,觸底,其實(shí)很簡(jiǎn)單就是將屏幕看成一個(gè)大的坐標(biāo)軸,改變坐標(biāo)的大小,即可控制方塊的位置。銷(xiāo)行,就是當(dāng)一行中全是方塊時(shí),即這一行中存儲(chǔ)的全是1,就符合銷(xiāo)行條件,將這行刪除,它之上的所有方塊縱坐標(biāo)下移一格,并且記錄銷(xiāo)行的次數(shù),以此來(lái)控制得分情況,根據(jù)所得的分?jǐn)?shù)制定相應(yīng)的過(guò)關(guān)規(guī)則。對(duì)于如何決定下一個(gè)是怎樣的方塊,可以采用隨機(jī)數(shù),用隨機(jī)數(shù)來(lái)決定的方塊。rand函數(shù)是一個(gè)隨機(jī)函數(shù),可以產(chǎn)生從0到rand_max(32767)的隨機(jī)數(shù),但是每次運(yùn)行程序產(chǎn)生的隨機(jī)數(shù)都是一樣的,這時(shí)給隨機(jī)數(shù)產(chǎn)生一個(gè)隨機(jī)種子(seed),函數(shù)原型是srand((unsigned)time(NULL));time的值每時(shí)每刻都不同。所以種子不同,所以,產(chǎn)生的隨機(jī)數(shù)也不同。所以說(shuō),要想產(chǎn)生不同的隨機(jī)數(shù),在使用rand之前需要先調(diào)用srandsrand和rand函數(shù)都包含在stdlib.h的頭文件里。由于rand產(chǎn)生的隨機(jī)數(shù)是從0到rand_max的,而rand_max(32767)是一個(gè)很大的數(shù),那么如何產(chǎn)生從X-Y的數(shù)呢?從X到Y(jié),有Y-X+1個(gè)數(shù),所以要產(chǎn)生從X到Y(jié)的數(shù),只需要這樣寫(xiě):k=rand()%(Y-X+1)+X;這樣,就可以產(chǎn)生你想要的任何范圍內(nèi)的隨機(jī)數(shù)了。設(shè)計(jì)方案。定義一個(gè)類(lèi)classConsole來(lái)控制窗口的大小,使窗口的大小適合玩家玩游戲。定義三種靜態(tài)顏色變量以控制小格子的顏色,使界面更加美觀。staticconstWORDCOLOR_A; //運(yùn)動(dòng)中的顏色staticconstWORDCOLOR_B; //固定不動(dòng)的顏色 staticconstWORDCOLOR_C; //空白處的顏色這三種靜態(tài)變量用戶(hù)可以自己改變顏色來(lái)達(dá)到所期望的效果。需要引入頭文件:windows.h下面是一些常用的顏色說(shuō)明:AttributeMeaningFOREGROUND_BLUETextcolorcontainsblue.FOREGROUND_GREENTextcolorcontainsgreen.FOREGROUND_REDTextcolorcontainsred.FOREGROUND_INTENSITYTextcolorisintensified.BACKGROUND_BLUEBackgroundcolorcontainsblue.BACKGROUND_GREENBackgroundcolorcontainsgreen.BACKGROUND_REDBackgroundcolorcontainsred.BACKGROUND_INTENSITYBackgroundcolorisintensified.COLOR_A=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;//這是運(yùn)動(dòng)中的顏色是黃色COLOR_B=FOREGROUND_GREEN;//固定不動(dòng)的方塊顏色是綠色COLOR_C=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;//空白處的顏色是灰色這是我界面的顏色分布。將屏幕像像素塊一樣分成11*19的格子,灰色底。用4*4共16個(gè)格子來(lái)表示一個(gè)方塊,用一個(gè)4*4的數(shù)組來(lái)存儲(chǔ)七個(gè)方塊,1代表有一個(gè)格子,0代表沒(méi)有格子,例如:|-,可以用以下數(shù)組直觀來(lái)表示:1000010001001110110011101100010010000000010000000000000000000000這些數(shù)組存儲(chǔ)了七種方塊,四個(gè)變換,于是我定義了一個(gè)4維數(shù)組bk[7][4][4][4]來(lái)存儲(chǔ)這些數(shù)據(jù),具體見(jiàn)附錄2,當(dāng)在游戲中進(jìn)行一次旋轉(zhuǎn)就是改變數(shù)組最后一維的數(shù)值,旋轉(zhuǎn)是逆時(shí)針旋轉(zhuǎn)。以屏幕左上角為原點(diǎn),從左向右畫(huà)x軸;從上向下畫(huà)y軸,(x,y)就代表了在屏幕上的位置,通過(guò)控制x,y值來(lái)實(shí)現(xiàn)左移,右移,上移,下移。例如向左移的代碼如下:voidMoveLeft(void) //向左移{if(IsFit(x-1,y,c,z)) //檢查是否碰到墻壁{ //沒(méi)有碰壁則繼續(xù)VoiceBeep();Draw(COLOR_C); //先將空白處畫(huà)出--x; //將橫坐標(biāo)減1Draw(COLOR_A); //繪出方塊}}判斷方塊已經(jīng)到達(dá)底部或是否碰到墻壁,“將會(huì)”指的是方塊如果向左,向右,向下移動(dòng)后就會(huì)碰到障礙物;“障礙物”指的是左右下墻壁和底部已經(jīng)落下未被消除的小方塊。用下列函數(shù):boolIsFit(intx,inty,intc,intz)//給定的x,y,c,z是否可行{for(inti=0;i<4;++i) //用i,j來(lái)遍歷16個(gè)小格子{for(intj=0;j<4;++j){if(bk[c][z][i][j]==1){if(y+i<0)continue;//方塊還沒(méi)有落下來(lái)//y+i>=19表示已經(jīng)觸底了,x+j<0表示觸了最左邊的墻,//x+j>=11表示觸了最右邊的墻,//data[y+i][x+j]==1表示底部已經(jīng)存在了方塊if(y+i>=19||x+j<0||x+j>=11||data[y+i][x+j]==1)returnfalse;} } } returntrue;}方塊落下后,就開(kāi)始檢查是否有滿(mǎn)足消除條件的行了。用chardata[19][11]來(lái)記錄有小方塊存在的地方,有為1,沒(méi)有事0。銷(xiāo)行的規(guī)則很簡(jiǎn)單:只要某行被小方塊全部填充,該行就被消除,上面的小方塊全部下移一行。所以,只要把原來(lái)的小方塊全部擦去,計(jì)算完新方塊位置后,再全部畫(huà)出就可以了,計(jì)算的時(shí)候,遍歷整個(gè)游戲區(qū)域,看有沒(méi)有可以消除的行,即遍歷chardata[19][11]看一行中是否全1,如果是,則開(kāi)始將這行上面的所有行開(kāi)始下移,并用intline-count來(lái)記錄銷(xiāo)行的次數(shù),這與之后的計(jì)分和關(guān)數(shù)的計(jì)算有關(guān)系,銷(xiāo)一行加100分,如果有連銷(xiāo)行則分?jǐn)?shù)相應(yīng)增加,每10000分是一個(gè)等級(jí),99999封頂。代碼如下:voidRemoveRow(void) //消行函數(shù){constcharFULLLINE[]={1,1,1,1,1,1,1,1,1,1,1};intlinecount=0; //記錄連續(xù)銷(xiāo)行的行數(shù)for(inti=0;i<19;++i) //開(kāi)始對(duì)19*11的格子開(kāi)始遍歷{ //如果一行中11列均是1則滿(mǎn)足銷(xiāo)行條件if(0==memcmp(data[i],FULLLINE,11)){++linecount;for(intm=0;m<11++m){for(intn=i;n>1;--n){ //對(duì)這行以上的行進(jìn)行下移,//就是銷(xiāo)去了這一行data[n][m]=data[n-1][m]; win.Output(2+m*2,1+n,data[n][m]==1?COLOR_B:COLOR_C,"■",2);}data[0][m]=0; //最頂部賦值為0,既沒(méi)有小方塊win.Output(2+m*2,1,COLOR_C,"■",2);}}}chardata[19][11]={0};if(linecount==0)return;int_score=0;switch(linecount) //按照銷(xiāo)行的行數(shù)來(lái)給分?jǐn)?shù){case1:_score=100;break;case2:_score=300;break;case3:_score=700;break;case4:_score=1500;break;}score+=_score;if(score>99999)score=99999;//最高分?jǐn)?shù)是99999level=score/10000; //設(shè)置等級(jí)DrawScoreLevel(); //繪制得分框}用Sleep()函數(shù)來(lái)控制刷圖的速度,程序中設(shè)定每55ms刷一次圖,Sleep(55);用簡(jiǎn)單Beep(freq,dura)來(lái)控制聲音,其中freq是頻率,dura是持續(xù)時(shí)間;用隨機(jī)函數(shù)srand(time(0));next=rand()%7來(lái)控制下一個(gè)方塊類(lèi)型。3、流程圖。開(kāi)開(kāi)始顯示界面顯示界面按下結(jié)束按下結(jié)束 是按下開(kāi)始 否按下開(kāi)始 否 是開(kāi)始游戲開(kāi)始游戲輸入指令輸入指令根據(jù)指令調(diào)用不同的函數(shù)進(jìn)行操作根據(jù)指令調(diào)用不同的函數(shù)進(jìn)行操作按下結(jié)束 是按下結(jié)束 否GAMEOVER 否GAMEOVER 是結(jié)結(jié)束4、測(cè)試數(shù)據(jù)、測(cè)試結(jié)果、結(jié)果分析。 開(kāi)始游戲右移方塊旋轉(zhuǎn)方塊銷(xiāo)一行得100分連銷(xiāo)4行得1500分達(dá)到10000分,升一級(jí)游戲結(jié)束PS:由于打印需要,界面呈黑白畫(huà)面5、相關(guān)運(yùn)行界面。6、關(guān)鍵代碼//只有部分代碼,完整代碼就是前面那個(gè)俄羅斯方塊代碼classConsole //控制臺(tái){friendclassWindow;public:voidOpen(constchar*title,COORDwl) //title:控制臺(tái)標(biāo)題{ //point:控制臺(tái)寬度和高度assert(wl.X>0&&wl.Y>0);verify((hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE))!=INVALID_HANDLE_VALUE); //獲得輸出句柄verify(SetConsoleTitle(title)); //設(shè)置標(biāo)題CONSOLE_CURSOR_INFOcci={25,FALSE};verify(SetConsoleCursorInfo(hStdOutput,&cci));//去除光標(biāo)SMALL_RECTwrt={0,0,wl.X-1,wl.Y-1};//設(shè)置窗體尺寸verify(SetConsoleWindowInfo(hStdOutput,TRUE,&wrt));coord=wl; //設(shè)置緩沖尺寸verify(SetConsoleScreenBufferSize(hStdOutput,coord));}private:HANDLEhStdOutput;COORDcoord;};classRussiaDiamonds //俄羅斯方塊的類(lèi){public: //x:左上角坐標(biāo),RussiaDiamonds(Console&console,shortx,shorty){ //y:右下角坐標(biāo)SMALL_RECTwrect={x,y,x+38,y+21};win.Open(console,wrect);}//分別是開(kāi)始,暫停,聲效,變形,左移,右移,下移,落地鍵的鍵碼,//聲效頻率,延續(xù)時(shí)間//Example://A鍵為0x41,用0x00000041表示//F1鍵為0x00,0x3B,用0x00003800表示//F11鍵為0xE0,0x85,用0x000085E0表示voidOpen(intctrlkeys[8],charctrlkeydecs[8][5],DWORDfrequency,DWORDduration){memcpy(keys,ctrlkeys,sizeof(keys));memcpy(decs,ctrlkeydecs,sizeof(decs));freq=frequency,dura=duration; gameover=false; //分別對(duì)各個(gè)控制量初始化pause=true;voice=true;score=0,level=0;memset(data,0,sizeof(data));srand(time(0)); //設(shè)置隨機(jī)種子數(shù)next=rand()%7; //產(chǎn)生隨機(jī)數(shù)來(lái)控制下一個(gè)方塊的產(chǎn)生x=4,y=-2,c=-1,z=0;} boolIsFit(intx,inty,intc,intz) //給定的x,y,c,z是否可行{for(inti=0;i<4;++i) //用i,j來(lái)遍歷16個(gè)小格子{for(intj=0;j<4;++j){if(bk[c][z][i][j]==1){if(y+i<0)continue;//方塊還沒(méi)有落下來(lái)//y+i>=19表示已經(jīng)觸底了,x+j<0表示觸了最左邊的墻,//x+j>=11表示觸了最右邊的墻,//data[y+i][x+j]==1表示底部已經(jīng)存在了方塊if(y+i>=19||x+j<0||x+j>=11||data[y+i][x+j]==1)returnfalse;}}}returntrue;}voidRemoveRow(void) //消行函數(shù){constcharFULLLINE[]={1,1,1,1,1,1,1,1,1,1,1};intlinecount=0; //記錄連續(xù)銷(xiāo)行的行數(shù)for(inti=0;i<19;++i) //開(kāi)始對(duì)19*11的格子開(kāi)始遍歷{ //如果一行中11列均是1則滿(mǎn)足銷(xiāo)行條件if(0==memcmp(data[i],FULLLINE,11)){++linecount;for(intm=0;m<11++m){for(intn=i;n>1;--n){ //對(duì)這行以上的行進(jìn)行下移,就是銷(xiāo)去了這一行data[n][m]=data[n-1][m]; win.Output(2+m*2,1+n,data[n][m]==1?COLOR_B:COLOR_C,"■",2);}data[0][m]=0;//最頂部賦值為0,既沒(méi)有小方塊win.Output(2+m*2,1,COLOR_C,"■",2);}}}chardata[19][11]={0};if(linecount==0)return;int_score=0;switch(linecount) //按照銷(xiāo)行的行數(shù)來(lái)給分?jǐn)?shù){case1:_score=100;break;case2:_score=300;break;case3:_score=700;break;case4:_score=1500;break;}score+=_score;if(score>99999)score=99999;//最高分?jǐn)?shù)是99999level=score/10000; //設(shè)置等級(jí)DrawScoreLevel(); //繪制得分框} voidMoveTrans(void) //逆時(shí)針?lè)D(zhuǎn){if(IsFit(x,y,c,(z+1)%4)) //每調(diào)用一次z改變一次{ //通過(guò)調(diào)用四維數(shù)組中//不同的矩陣來(lái)實(shí)現(xiàn)變換VoiceBeep();Draw(COLOR_C);z=(z+1)%4;Draw(COLOR_A);}}//部分代碼省略private:staticconstcharbg[21*38+1];staticconstcharbk[7][4][4][4];staticconstWORDCOLOR_A; //運(yùn)動(dòng)中的顏色staticconstWORDCOLOR_B; //固定不動(dòng)的顏色staticconstWORDCOLOR_C; //空白處的顏色private:DWORDfreq,dura; //聲效頻率,延續(xù)時(shí)間intkeys[8]; //8個(gè)控制鍵chardecs[8][5]; //8個(gè)控制鍵的描述boolgameover;boolpause; //暫停boolvoice; //聲效開(kāi)關(guān)intsc
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度鋼材行業(yè)投資分析與風(fēng)險(xiǎn)評(píng)估合同
- 2025版學(xué)校體育器材租賃與維護(hù)服務(wù)協(xié)議3篇
- 教育科技在心理健康領(lǐng)域的創(chuàng)新應(yīng)用
- 二零二五年度打字員與出版社合同:圖書(shū)編輯與排版服務(wù)協(xié)議2篇
- 社交媒體在小學(xué)數(shù)學(xué)教學(xué)中的作用與影響
- 教育信息化背景下的探究式學(xué)習(xí)法研究
- 2025年度能源管理創(chuàng)業(yè)合伙人共同投資協(xié)議4篇
- 二零二五年度成都離婚協(xié)議公證辦理材料審核及處理合同4篇
- 企業(yè)可持續(xù)發(fā)展與創(chuàng)新型組織架構(gòu)的關(guān)系
- 小學(xué)階段數(shù)學(xué)與信息技術(shù)課程的資源整合
- T型引流管常見(jiàn)并發(fā)癥的預(yù)防及處理
- JJG 1204-2025電子計(jì)價(jià)秤檢定規(guī)程(試行)
- 2024年計(jì)算機(jī)二級(jí)WPS考試題庫(kù)(共380題含答案)
- 中建集團(tuán)面試自我介紹
- 2024年江蘇農(nóng)牧科技職業(yè)學(xué)院?jiǎn)握新殬I(yè)適應(yīng)性測(cè)試題庫(kù)參考答案
- 2024版《53天天練單元?dú)w類(lèi)復(fù)習(xí)》3年級(jí)語(yǔ)文下冊(cè)(統(tǒng)編RJ)附參考答案
- 知識(shí)圖譜與大模型融合實(shí)踐研究報(bào)告
- 0-9任意四位數(shù)手機(jī)密碼排列組合全部數(shù)據(jù)列表
- 碳排放管理員 (碳排放核查員)技能考核內(nèi)容結(jié)構(gòu)表四級(jí)、技能考核要素細(xì)目表四級(jí)
- 物業(yè)五級(jí)三類(lèi)服務(wù)統(tǒng)一標(biāo)準(zhǔn)
- 分期還款協(xié)議書(shū)范本
評(píng)論
0/150
提交評(píng)論