俄羅斯方塊實驗報告_第1頁
俄羅斯方塊實驗報告_第2頁
俄羅斯方塊實驗報告_第3頁
俄羅斯方塊實驗報告_第4頁
俄羅斯方塊實驗報告_第5頁
已閱讀5頁,還剩9頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

俄羅斯方塊實驗報告編寫“俄羅斯方塊”游戲1、問題分析。 編寫俄羅斯方塊游戲,首先是界面問題,要有一個相對美觀的游戲界面,可以有很多種解決的方法,可以用DOS的界面,也可以用MFC做。 界面做好后,最重要的就是七個方塊如何存放,翻轉(zhuǎn),顯示等等一系列問題,首先,我們要把這七個方塊用一種數(shù)據(jù)結(jié)構(gòu)存儲起來;其次,在游戲中將這七個方塊隨機挑選出來并顯示在屏幕上,根據(jù)鍵盤事件進行旋轉(zhuǎn);最后,判斷到達底部的方塊是簡單疊加還是引發(fā)消除事件。 普通俄羅斯方塊游戲中,只有七個基本方塊:|,Z,N,L,7,|-,O,方塊都可以畫在一個4*4的方格中。于是就有兩個方法:一個是只存儲七個方塊,在游戲運行的時候計算旋轉(zhuǎn)后的方塊形狀;另一個是將所有的方塊全部存儲起來,在游戲運行的時候計算取其中的哪個方塊。

另外,考慮到4*4是16,而一個int正好是16位(TC2是16位,其他的是32位),所以可以把一個方塊存儲在一個int數(shù)據(jù)中,取出的時候,判斷它的每個bit位,為1處有小方塊,為0處是空白。

所以可以分別用二維數(shù)組和bit的方法來表示這些方塊。 對于二維數(shù)組而言,其控制旋轉(zhuǎn)的操作會很簡單,就是控制數(shù)組的行列以決定到底該取出哪一種方塊,所以程序中我會采用這種方法。如何控制方塊的下落速度,如何讓實現(xiàn)左移,右移,下落,如何銷行,如何計分,又如何加速等等都是需要考慮的問題。對于控制方塊的下落速度,首先應(yīng)該現(xiàn)弄明白方塊是怎樣下落的,目前最常用的就是每隔一定得時間進行重新繪圖,就像動畫片一樣,當很多副相關(guān)的畫面不斷在人眼前播放,由于人眼的掩蔽效應(yīng)就會形成動著的畫面,看起來就是物體在那里移動,于此原理相同,當改變方塊在畫面上的位置,再以一定得時間間隔進行重新刷圖,其效果看起來就是方塊在移動;也就是說控制方塊下落速度的其實就是控制重新繪圖的時間間隔,控制時間的函數(shù)有以下幾種:調(diào)用函數(shù)SetTimer()設(shè)置定時間隔,如SetTimer(0,200,NULL)即為設(shè)置200毫秒的時間間隔。在應(yīng)用程序中增加定時響應(yīng)函數(shù)OnTimer(),并在該函數(shù)中添加響應(yīng)的處理語句,用來完成時間到時的操作。這種定時方法是非常簡單的,但其定時功能如同Sleep()函數(shù)的延時功能一樣,精度較低,只可以用來實現(xiàn)諸如位圖的動態(tài)顯示等對定時精度要求不高的情況,而在精度要求較高的條件下,這種方法應(yīng)避免采用。精度時控函數(shù),在要求誤差不大于1毫秒的情況下,可以采用GetTickCount()函數(shù),該函數(shù)的返回值是DWORD型,表示以毫秒為單位的計算機啟動后經(jīng)歷的時間間隔。高精度時控函數(shù)對于一般的實時控制,使用GetTickCount()函數(shù)就可以滿足精度要求,但要進一步提高計時精度,就要采用QueryPerformanceFrequency()函數(shù)和QueryPerformanceCounter()函數(shù)。這兩個函數(shù)是VC提供的僅供Windows9X使用的高精度時間函數(shù),并要求計算機從硬件上支持高精度計時器。接下來就應(yīng)該考慮如何實現(xiàn)左移,右移,下移,觸底,其實很簡單就是將屏幕看成一個大的坐標軸,改變坐標的大小,即可控制方塊的位置。銷行,就是當一行中全是方塊時,即這一行中存儲的全是1,就符合銷行條件,將這行刪除,它之上的所有方塊縱坐標下移一格,并且記錄銷行的次數(shù),以此來控制得分情況,根據(jù)所得的分數(shù)制定相應(yīng)的過關(guān)規(guī)則。對于如何決定下一個是怎樣的方塊,可以采用隨機數(shù),用隨機數(shù)來決定的方塊。rand函數(shù)是一個隨機函數(shù),可以產(chǎn)生從0到rand_max(32767)的隨機數(shù),但是每次運行程序產(chǎn)生的隨機數(shù)都是一樣的,這時給隨機數(shù)產(chǎn)生一個隨機種子(seed),函數(shù)原型是srand((unsigned)time(NULL));time的值每時每刻都不同。所以種子不同,所以,產(chǎn)生的隨機數(shù)也不同。所以說,要想產(chǎn)生不同的隨機數(shù),在使用rand之前需要先調(diào)用srandsrand和rand函數(shù)都包含在stdlib.h的頭文件里。由于rand產(chǎn)生的隨機數(shù)是從0到rand_max的,而rand_max(32767)是一個很大的數(shù),那么如何產(chǎn)生從X-Y的數(shù)呢?從X到Y(jié),有Y-X+1個數(shù),所以要產(chǎn)生從X到Y(jié)的數(shù),只需要這樣寫:k=rand()%(Y-X+1)+X;這樣,就可以產(chǎn)生你想要的任何范圍內(nèi)的隨機數(shù)了。設(shè)計方案。定義一個類classConsole來控制窗口的大小,使窗口的大小適合玩家玩游戲。定義三種靜態(tài)顏色變量以控制小格子的顏色,使界面更加美觀。staticconstWORDCOLOR_A; //運動中的顏色staticconstWORDCOLOR_B; //固定不動的顏色 staticconstWORDCOLOR_C; //空白處的顏色這三種靜態(tài)變量用戶可以自己改變顏色來達到所期望的效果。需要引入頭文件:windows.h下面是一些常用的顏色說明:AttributeMeaningFOREGROUND_BLUETextcolorcontainsblue.FOREGROUND_GREENTextcolorcontainsgreen.FOREGROUND_REDTextcolorcontainsred.FOREGROUND_INTENSITYTextcolorisintensified.BACKGROUND_BLUEBackgroundcolorcontainsblue.BACKGROUND_GREENBackgroundcolorcontainsgreen.BACKGROUND_REDBackgroundcolorcontainsred.BACKGROUND_INTENSITYBackgroundcolorisintensified.COLOR_A=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;//這是運動中的顏色是黃色COLOR_B=FOREGROUND_GREEN;//固定不動的方塊顏色是綠色COLOR_C=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE;//空白處的顏色是灰色這是我界面的顏色分布。將屏幕像像素塊一樣分成11*19的格子,灰色底。用4*4共16個格子來表示一個方塊,用一個4*4的數(shù)組來存儲七個方塊,1代表有一個格子,0代表沒有格子,例如:|-,可以用以下數(shù)組直觀來表示:1000010001001110110011101100010010000000010000000000000000000000這些數(shù)組存儲了七種方塊,四個變換,于是我定義了一個4維數(shù)組bk[7][4][4][4]來存儲這些數(shù)據(jù),具體見附錄2,當在游戲中進行一次旋轉(zhuǎn)就是改變數(shù)組最后一維的數(shù)值,旋轉(zhuǎn)是逆時針旋轉(zhuǎn)。以屏幕左上角為原點,從左向右畫x軸;從上向下畫y軸,(x,y)就代表了在屏幕上的位置,通過控制x,y值來實現(xiàn)左移,右移,上移,下移。例如向左移的代碼如下:voidMoveLeft(void) //向左移{if(IsFit(x-1,y,c,z)) //檢查是否碰到墻壁{ //沒有碰壁則繼續(xù)VoiceBeep();Draw(COLOR_C); //先將空白處畫出--x; //將橫坐標減1Draw(COLOR_A); //繪出方塊}}判斷方塊已經(jīng)到達底部或是否碰到墻壁,“將會”指的是方塊如果向左,向右,向下移動后就會碰到障礙物;“障礙物”指的是左右下墻壁和底部已經(jīng)落下未被消除的小方塊。用下列函數(shù):boolIsFit(intx,inty,intc,intz)//給定的x,y,c,z是否可行{for(inti=0;i<4;++i) //用i,j來遍歷16個小格子{for(intj=0;j<4;++j){if(bk[c][z][i][j]==1){if(y+i<0)continue;//方塊還沒有落下來//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;}方塊落下后,就開始檢查是否有滿足消除條件的行了。用chardata[19][11]來記錄有小方塊存在的地方,有為1,沒有事0。銷行的規(guī)則很簡單:只要某行被小方塊全部填充,該行就被消除,上面的小方塊全部下移一行。所以,只要把原來的小方塊全部擦去,計算完新方塊位置后,再全部畫出就可以了,計算的時候,遍歷整個游戲區(qū)域,看有沒有可以消除的行,即遍歷chardata[19][11]看一行中是否全1,如果是,則開始將這行上面的所有行開始下移,并用intline-count來記錄銷行的次數(shù),這與之后的計分和關(guān)數(shù)的計算有關(guān)系,銷一行加100分,如果有連銷行則分數(shù)相應(yīng)增加,每10000分是一個等級,99999封頂。代碼如下:voidRemoveRow(void) //消行函數(shù){constcharFULLLINE[]={1,1,1,1,1,1,1,1,1,1,1};intlinecount=0; //記錄連續(xù)銷行的行數(shù)for(inti=0;i<19;++i) //開始對19*11的格子開始遍歷{ //如果一行中11列均是1則滿足銷行條件if(0==memcmp(data[i],FULLLINE,11)){++linecount;for(intm=0;m<11++m){for(intn=i;n>1;--n){ //對這行以上的行進行下移,//就是銷去了這一行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,既沒有小方塊win.Output(2+m*2,1,COLOR_C,"■",2);}}}chardata[19][11]={0};if(linecount==0)return;int_score=0;switch(linecount) //按照銷行的行數(shù)來給分數(shù){case1:_score=100;break;case2:_score=300;break;case3:_score=700;break;case4:_score=1500;break;}score+=_score;if(score>99999)score=99999;//最高分數(shù)是99999level=score/10000; //設(shè)置等級DrawScoreLevel(); //繪制得分框}用Sleep()函數(shù)來控制刷圖的速度,程序中設(shè)定每55ms刷一次圖,Sleep(55);用簡單Beep(freq,dura)來控制聲音,其中freq是頻率,dura是持續(xù)時間;用隨機函數(shù)srand(time(0));next=rand()%7來控制下一個方塊類型。3、流程圖。開開始顯示界面顯示界面按下結(jié)束按下結(jié)束 是按下開始 否按下開始 否 是開始游戲開始游戲輸入指令輸入指令根據(jù)指令調(diào)用不同的函數(shù)進行操作根據(jù)指令調(diào)用不同的函數(shù)進行操作按下結(jié)束 是按下結(jié)束 否GAMEOVER 否GAMEOVER 是結(jié)結(jié)束4、測試數(shù)據(jù)、測試結(jié)果、結(jié)果分析。 開始游戲右移方塊旋轉(zhuǎn)方塊銷一行得100分連銷4行得1500分達到10000分,升一級游戲結(jié)束PS:由于打印需要,界面呈黑白畫面5、相關(guān)運行界面。6、關(guān)鍵代碼//只有部分代碼,完整代碼就是前面那個俄羅斯方塊代碼classConsole //控制臺{friendclassWindow;public:voidOpen(constchar*title,COORDwl) //title:控制臺標題{ //point:控制臺寬度和高度assert(wl.X>0&&wl.Y>0);verify((hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE))!=INVALID_HANDLE_VALUE); //獲得輸出句柄verify(SetConsoleTitle(title)); //設(shè)置標題CONSOLE_CURSOR_INFOcci={25,FALSE};verify(SetConsoleCursorInfo(hStdOutput,&cci));//去除光標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 //俄羅斯方塊的類{public: //x:左上角坐標,RussiaDiamonds(Console&console,shortx,shorty){ //y:右下角坐標SMALL_RECTwrect={x,y,x+38,y+21};win.Open(console,wrect);}//分別是開始,暫停,聲效,變形,左移,右移,下移,落地鍵的鍵碼,//聲效頻率,延續(xù)時間//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; //分別對各個控制量初始化pause=true;voice=true;score=0,level=0;memset(data,0,sizeof(data));srand(time(0)); //設(shè)置隨機種子數(shù)next=rand()%7; //產(chǎn)生隨機數(shù)來控制下一個方塊的產(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來遍歷16個小格子{for(intj=0;j<4;++j){if(bk[c][z][i][j]==1){if(y+i<0)continue;//方塊還沒有落下來//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ù)銷行的行數(shù)for(inti=0;i<19;++i) //開始對19*11的格子開始遍歷{ //如果一行中11列均是1則滿足銷行條件if(0==memcmp(data[i],FULLLINE,11)){++linecount;for(intm=0;m<11++m){for(intn=i;n>1;--n){ //對這行以上的行進行下移,就是銷去了這一行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,既沒有小方塊win.Output(2+m*2,1,COLOR_C,"■",2);}}}chardata[19][11]={0};if(linecount==0)return;int_score=0;switch(linecount) //按照銷行的行數(shù)來給分數(shù){case1:_score=100;break;case2:_score=300;break;case3:_score=700;break;case4:_score=1500;break;}score+=_score;if(score>99999)score=99999;//最高分數(shù)是99999level=score/10000; //設(shè)置等級DrawScoreLevel(); //繪制得分框} voidMoveTrans(void) //逆時針翻轉(zhuǎn){if(IsFit(x,y,c,(z+1)%4)) //每調(diào)用一次z改變一次{ //通過調(diào)用四維數(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; //運動中的顏色staticconstWORDCOLOR_B; //固定不動的顏色staticconstWORDCOLOR_C; //空白處的顏色private:DWORDfreq,dura; //聲效頻率,延續(xù)時間intkeys[8]; //8個控制鍵chardecs[8][5]; //8個控制鍵的描述boolgameover;boolpause; //暫停boolvoice; //聲效開關(guān)intsc

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論