薛 鵬 段華瓊*
(四川大學錦城學院 計算機與軟件學院,四川 成都611371)
俄羅斯方塊最早是由俄羅斯人阿列克謝·帕基特諾夫于1984 年6 月發(fā)明的一款經(jīng)典游戲。俄羅斯方塊游戲是在一個固定邊界的界面中,不同方塊隨機出現(xiàn)在上邊界,玩家通過鍵盤上的asd(左下右)以及空格(形狀變化)操控,通過控制空格鍵來改變方塊的形狀,讓方塊落到邊界的底部。滿行的方塊將會被消除并且獲得相應的分數(shù),如果沒有滿行則方塊的高度會一直往上面疊加,當疊加的方塊到達頂端的時候,判定為游戲的結束。
在實現(xiàn)游戲時,需要先用二維數(shù)組來繪制地圖和顯示下一個將會出現(xiàn)方塊的邊框,并且在這些位置輸出來表示墻體,邊框那個位置坐標的值賦為1。地圖其他位置坐標的初始值賦為0。用一個基類來表示方塊的種類,每一種不同的方塊都繼承該基類。方塊的下落過程用方塊的坐標位置更新來體現(xiàn)(在新的位置來打印出方塊,在原來位置上打印空格,以此實現(xiàn)視覺上方塊的移動)。方塊的移動用遍歷的方式來進行判斷,對方塊的周圍進行遍歷,如果不符合遍歷的條件,則表示方塊不能變形或者移動。玩家通過控制ads 三個鍵位分別控制方塊的左移、右移,使用空格按鍵來對滿足變形條件的方塊進行形狀的改變。當方塊到達最底端的時候將方塊坐標位置的值賦為2(不賦為1是因為墻體所在坐標位置的值是1,被固定了的方塊坐標所在位置的賦為2 將其與墻體產(chǎn)生區(qū)別)。在游戲過程中,玩家通過自己所控制的方塊從底部往上面堆積。如果堆積的方塊填滿了一層,將清除這一層所有的方塊并且這一層上面所有的方塊向下挪動一個單位。在消除該層方塊后將會獲得相應分數(shù)的增加。每消除一層方塊,方塊下落的速度將會增加,隨著消除方塊層數(shù)的增加,方塊的下落速度會越來越快,以此來提升游戲難度。當新產(chǎn)生的方塊下面有堆積的方塊時判定為游戲失敗,游戲失敗后顯示存活秒數(shù)以及獲得的分數(shù)。可以將整個俄羅斯方塊游戲分為以下三個環(huán)節(jié):第一個環(huán)節(jié):初始化游戲界面,繪制游戲邊框,以及在邊框右側顯示第一個將要出現(xiàn)的方塊。第二個環(huán)節(jié):根據(jù)玩家的操作,方塊不停的積累或者消除,隨著消除方塊行數(shù)的增加獲得的分數(shù)也到相應得到增加。每消除一行方塊,方塊下落速度將會變得更快。第三個環(huán)節(jié):隨著沒有被消除方塊的積累,當新出現(xiàn)的方塊下面已經(jīng)有了堆積的方塊時,判定游戲結束。顯示存活秒數(shù)以及獲得分數(shù)。
該種父類中包含方塊的坐標結構體數(shù)組,造型類型函數(shù),運動狀態(tài)檢測函數(shù),能否改變形狀檢測函數(shù),方塊的打印與清除函數(shù),檢測游戲死亡函數(shù)等等。
這個結構體記錄了每一個方塊的x 坐標以及y 坐標,在方塊的基類中用結構體數(shù)組來表示四個方塊。
這是一個虛函數(shù),因為每個方塊的變形方式不同,所以要把這個函數(shù)設置為虛函數(shù),避免繼承中產(chǎn)生的二義性問題。
這個函數(shù)的作用是檢測方塊的狀態(tài),檢測方塊是否應該被固定,如果下面有其他方塊了,那么這個方塊就應該被固定了。具體實現(xiàn)是:使用for 循環(huán)進行遍歷每個方塊下面那個位置的值,當檢測到當前所有方塊中的某一個方格下面的坐標位置處的值不為0 的時候,那么就將這個方塊固定。然后將全局變量CreatFangKuai 賦為1,表示可以產(chǎn)生新的方塊,以達到可以連續(xù)生成新方塊的目的。將state 賦為0,代表方塊不可移動。再把當前這些方塊坐標位置的值修改為2,以便和墻體產(chǎn)生區(qū)別。
bool checkCanLeft()檢測能否左移,bool checkCanRight()檢測右移,bool checkCanDown()檢測是否快速下移。
拿左移舉例,最開始讓bool flag=true,方塊最開始默認為可以左移。然后使用循環(huán)遍歷每個位置的左側,當有一個方塊的左側不為0(即墻體或者出現(xiàn)其他的方塊)時,就不允許左移(if(MapValue[fangKuai[i].x-2][fangKuai[i].y]!=0))。右移與左移類似。注意,此處x+2 的原因是因為每個在x 軸上面占兩個寬度。下移則是if(MapValue[fangKuai[i].x][fangKuai[i].y+1]! =0)。值得關注的是:在電腦的坐標系中,往下移動應該是y 軸方向上加1,最左上角是看作為坐標原點,往下方向設為y 軸的正方向,與常規(guī)的平面直角坐標系稍有區(qū)別。
代表速度的全局變量DownSpeed 的初始值為1,DownSpeed=sumScore/10+1。sumScore 記錄游戲分數(shù),使用這個函數(shù)可以讓方塊下落的速度隨著游戲分數(shù)的提高而提高。從而慢慢的提高游戲的難度。
這個函數(shù)的實現(xiàn)是使用雙重for 循環(huán),在指定位置上打印出空格符號,從而達到清空指定位置上的方格的目的。
用函數(shù)void drawNextFangkuai(int a,int b)實現(xiàn)。需要先使用clearNextFangkuai()函數(shù),清空上一次出現(xiàn)在預測位置的方塊。隨機傳入a,b 兩個值。在這個函數(shù)中有一個switch 語句,這個語句枚舉出每一種可能出現(xiàn)的情況,a 值代表對應方塊的種類,b 值代表該種方塊的朝向,以此來預測并繪制下一次出現(xiàn)的方塊,讓玩家提前做好應對策略。


由函數(shù)int keydown()實現(xiàn)。這個函數(shù)用于接收asd 以及空格四個按鍵的信息。該函數(shù)的作用是:當按鍵被按下時,發(fā)生keydown 事件(或者發(fā)生keydown 事件時調用相應的函數(shù))。為了防止有多次無效的輸入,所以設計了一個循環(huán),當里面有數(shù)據(jù)的時候,循環(huán)取出,只使用最后一次的輸入,具體代碼如下:

由函數(shù)void gotoXY(int x,int y)實現(xiàn)。傳入光標需要移動的目標位置的x 坐標和y 軸坐標即可將光標的位置發(fā)生改變。在該程序中光標移動函數(shù)的作用非常的大,可以將光標移動到指定的位置處去,需要注意的是,使用這個函數(shù)必須包含頭文件windows.h。使用這個函數(shù)可以很大程度上方便地圖的打印工作。
int getRandRange(int min,int max)是一個自定義的函數(shù),內容是return rand()%(max-min+1)+min;可以用這個函數(shù)返回一個min 到max 之間的隨機整數(shù),以此來模擬下一次隨機出現(xiàn)的方塊類型。
由函數(shù)checkDeath()實現(xiàn)。這個函數(shù)用在各個方塊類的構造函數(shù)里面。具體是實現(xiàn)代碼是:if (MapValue [fangKuai[i].x][fangKuai[i].y]! = 0)。如果新的方塊剛剛生成時下面就有其他方塊則判定游戲失敗。它的原理是:將所有積累的方塊的坐標處那個位置的值賦為2,待新方塊生成后判斷新生成方塊的位置處的值是否為0,如果不為0 則結束游戲。

論文基于C++語言提供了俄羅斯方塊游戲的設計思路和實現(xiàn)方法。程序每個功能都由一個函數(shù)具體實現(xiàn),設置了方塊的基類,充分展現(xiàn)了程序的模塊化設計和C++中面相對象編程的兩種編程思想。通過實踐俄羅斯方塊游戲的設計與實踐,能充分鍛煉模塊化編程的思想以及加深對C++的理解與掌握。