俄羅斯方塊游戲(C語言)_第1頁
俄羅斯方塊游戲(C語言)_第2頁
俄羅斯方塊游戲(C語言)_第3頁
俄羅斯方塊游戲(C語言)_第4頁
俄羅斯方塊游戲(C語言)_第5頁
已閱讀5頁,還剩59頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、 PAGE III俄羅斯方塊游戲(C語言)摘要 俄羅斯方塊是一款風(fēng)靡全球的掌上游戲機(jī)和PC機(jī)游戲,它造成的轟動(dòng)與創(chuàng)造的經(jīng)濟(jì)價(jià)值可以說是游戲史上的一件大事。它由俄羅斯人阿列克謝帕基特諾夫發(fā)明,故得此名。俄羅斯方塊的基本規(guī)則是移動(dòng)、旋轉(zhuǎn)和擺放游戲自動(dòng)輸出的各種方塊,使之排列成完整的一行或多行并且消除得分。它看似簡單卻變化無窮,俄羅斯方塊上手極其簡單,但是要熟練地掌握其中的操作與擺放技巧,難度卻不低。作為家喻戶曉老少皆宜的大眾游戲,其普及程度可以說是史上任何一款游戲都無法相比的。相信大多數(shù)人都還記得為它癡迷得茶不思飯不想的那個(gè)俄羅斯方塊時(shí)代。由于俄羅斯方塊具有的數(shù)學(xué)性、動(dòng)態(tài)性與知名度,也經(jīng)常拿來作為

2、游戲HYPERLINK /view/8332.htm程序設(shè)計(jì)的練習(xí)題材。 關(guān)鍵詞:俄羅斯方塊開發(fā) 游戲編程 程序開發(fā)AbstractsTetris is a fashionable global handheld game and PC games,it caused stir and create the economic value of gaming history is a great event.It is invented by the Russian Alexey Pazhitnov.The basic rule of tetris is moving,rotation and

3、put the Game output squares,It arranged in a complete row or a complete multi row,eliminate and score.It seems simple but Full of change.As household the mass games all ages,Its popularity is any games that cannot be compared.Tetris often used for game programming practice subject.Key: Tetris develo

4、pment ,Game programming ,program development目錄TOC o 1-3 h u HYPERLINK l _Toc7206 1. 前言 PAGEREF _Toc7206 1 HYPERLINK l _Toc26609 2.功能描述 PAGEREF _Toc26609 2 HYPERLINK l _Toc7433 3.總體設(shè)計(jì) PAGEREF _Toc7433 3 HYPERLINK l _Toc29317 3.1 功能模塊設(shè)計(jì) PAGEREF _Toc29317 3 HYPERLINK l _Toc6458 3.1.1 游戲執(zhí)行主流程 PAGEREF _T

5、oc6458 3 HYPERLINK l _Toc24400 3.1.2 游戲方塊預(yù)覽 PAGEREF _Toc24400 3 HYPERLINK l _Toc3928 3.1.3 游戲方塊控制 PAGEREF _Toc3928 5 HYPERLINK l _Toc9621 3.1.4 游戲顯示更新 PAGEREF _Toc9621 6 HYPERLINK l _Toc10323 3.1.5 游戲速度分?jǐn)?shù)更新 PAGEREF _Toc10323 7 HYPERLINK l _Toc26214 3.1.6 游戲幫助 PAGEREF _Toc26214 7 HYPERLINK l _Toc2181

6、1 3.2 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì) PAGEREF _Toc21811 7 HYPERLINK l _Toc23022 3.2.1 游戲底板BOARD結(jié)構(gòu)體 PAGEREF _Toc23022 7 HYPERLINK l _Toc13259 3.2.2 游戲方塊SHAPE結(jié)構(gòu)體 PAGEREF _Toc13259 7 HYPERLINK l _Toc7093 3.2.3 SHAPE結(jié)構(gòu)數(shù)組 PAGEREF _Toc7093 8 HYPERLINK l _Toc14949 3.3 函數(shù)功能描述 PAGEREF _Toc14949 11 HYPERLINK l _Toc30270 4.程序?qū)崿F(xiàn) PAGERE

7、F _Toc30270 12 HYPERLINK l _Toc26983 4.1 源碼分析 PAGEREF _Toc26983 12 HYPERLINK l _Toc4220 4.1.1 程序預(yù)處理 PAGEREF _Toc4220 12 HYPERLINK l _Toc31615 4.1.2 主函數(shù)main() PAGEREF _Toc31615 16 HYPERLINK l _Toc13284 4.1.3 初始化界面 PAGEREF _Toc13284 21 HYPERLINK l _Toc4060 4.1.4 時(shí)鐘中斷處理 PAGEREF _Toc4060 22 HYPERLINK l

8、_Toc22573 4.1.5 成績、速度及幫助的顯示 PAGEREF _Toc22573 24 HYPERLINK l _Toc26490 4.1.6 滿行處理 PAGEREF _Toc26490 25 HYPERLINK l _Toc18945 4.1.7 游戲方塊的顯示和清除 PAGEREF _Toc18945 29 HYPERLINK l _Toc21906 4.1.8 游戲方塊操作判斷處理 PAGEREF _Toc21906 34 HYPERLINK l _Toc11297 4.2 運(yùn)行結(jié)果 PAGEREF _Toc11297 40 HYPERLINK l _Toc17567 4.2

9、.1 游戲初始狀態(tài) PAGEREF _Toc17567 40 HYPERLINK l _Toc20178 4.2.2 游戲進(jìn)行狀態(tài) PAGEREF _Toc20178 41 HYPERLINK l _Toc31911 5. 結(jié)論 PAGEREF _Toc31911 42 HYPERLINK l _Toc30603 致謝 PAGEREF _Toc30603 43 HYPERLINK l _Toc31908 參考文獻(xiàn) PAGEREF _Toc31908 44 PAGE 61前言 俄羅斯方塊(Tetris)原本是前蘇聯(lián)科學(xué)家阿列克謝帕吉特洛夫在1984年6月利用空閑時(shí)間所編寫的游戲程序,據(jù)說游戲的作

10、者最喜歡網(wǎng)球(Tennis)運(yùn)動(dòng),于是,它把來源于希臘語的tetra(意為“四”)與其結(jié)合,造了“tetris”一詞,之后開始提供授權(quán)給各個(gè)游戲公司,造成各平臺(tái)上俄羅斯游戲軟件大量發(fā)行的現(xiàn)象。 俄羅斯方塊由于上手簡單、老少皆宜,從而成為了家喻戶曉款風(fēng)靡全球的一款電視游戲機(jī)和掌上游戲機(jī)游戲。 C語言則是目前國際上比較流行的計(jì)算機(jī)高級(jí)編程語言之一,因其簡潔、使用方便且具備強(qiáng)大的功能而受到編程人員的普遍青睞。它既適合作為系統(tǒng)描述語言,也可以用來編寫系統(tǒng)軟件,還可以來編寫應(yīng)用軟件。 用C語言來編寫俄羅斯方塊這個(gè)游戲有較大優(yōu)勢:C語言具有各種各樣的數(shù)據(jù)類型,并引入了指針概念,使得程序效率更高;C語言還包

11、含很廣泛的運(yùn)算符;另外C語言具有強(qiáng)大的圖形功能,支持多種顯示器和驅(qū)動(dòng)器,而且計(jì)算功能、邏輯判斷能力也比較強(qiáng)大。 選擇此論文題是旨在訓(xùn)練基本編程能力和游戲開發(fā)技巧,熟悉C語言圖形模式下的編程。本程序中涉及結(jié)構(gòu)體、數(shù)組、時(shí)鐘中斷及繪圖等方面的知識(shí)。通過本程序的訓(xùn)練,能對(duì)C語言有一個(gè)更深刻的了解,掌握俄羅斯方塊游戲開發(fā)的基本原理,為將來開發(fā)出高質(zhì)量的游戲軟件打下堅(jiān)實(shí)的基礎(chǔ)。2.功能描述如圖2.1所示,本游戲主要實(shí)現(xiàn)一下幾種功能:圖2.1 俄羅斯方塊游戲功能描述圖游戲方塊預(yù)覽功能。在游戲過程中,當(dāng)在游戲底板中出現(xiàn)一個(gè)游戲方塊時(shí),必須在游戲方塊預(yù)覽區(qū)域中出現(xiàn)下一個(gè)游戲方塊,這樣有利于游戲玩家控制游戲的策

12、略。由于在此游戲中存在19種不同的游戲方塊,所以在游戲方塊預(yù)覽區(qū)域中需要顯示隨機(jī)生成的游戲方塊。游戲方塊控制功能。通過各種條件的判斷,實(shí)現(xiàn)對(duì)游戲方塊的左移、右移、快速下移、自由下落、旋轉(zhuǎn)功能,以及行滿消除行的功能。游戲顯示更新功能。當(dāng)游戲方塊左右移動(dòng)、下落、旋轉(zhuǎn)時(shí),要清除先前的游戲方塊,用新坐標(biāo)重繪游戲方塊。當(dāng)消除滿行時(shí),要重繪游戲底板的當(dāng)前狀態(tài)。游戲速度分?jǐn)?shù)更新功能。在游戲玩家進(jìn)行游戲過程中,需要按照一定的游戲規(guī)則給玩家計(jì)算游戲分?jǐn)?shù)。比如,消除一行加10分。當(dāng)游戲分?jǐn)?shù)達(dá)到一定數(shù)量之后,需要給游戲者進(jìn)行等級(jí)的上升,每上升一個(gè)等級(jí),游戲方塊的下落速度將加快,游戲的難度將增加。游戲幫助功能。玩家進(jìn)

13、入游戲后,將有對(duì)本游戲如何操作的友情提示。3.總體設(shè)計(jì)3.1 功能模塊設(shè)計(jì) 3.1.1 游戲執(zhí)行主流程 本俄羅斯方塊游戲執(zhí)行主流程圖3.1所示。在判斷鍵值時(shí),有左移VK_LEFT、右移VK_RIGHT、下移VK_DOWN、變形旋轉(zhuǎn)VK_UP、退出VK_ESC鍵值的判斷。 3.1.2 游戲方塊預(yù)覽 新游戲方塊將在如圖3.2所示的44的正方形小方塊中預(yù)覽。使用隨機(jī)函數(shù)rand()來產(chǎn)生119之間的游戲方塊編號(hào),并作為預(yù)覽的方塊編號(hào)。其中的正方形小方塊的大小為BSIZEBSIZE。BSIZE為設(shè)定的像素大小。圖3.2 游戲方塊預(yù)覽圖圖3.1 游戲執(zhí)行主流程圖 3.1.3 游戲方塊控制 這是此游戲開發(fā)

14、的重點(diǎn)和難點(diǎn)部分。下面分別較少左移、右移、下移、旋轉(zhuǎn)及滿行判斷的實(shí)現(xiàn)。 左移的實(shí)現(xiàn)過程如下: (1) 判斷在當(dāng)前的游戲底板中能否左移。這一判斷必須滿足如下兩條件:游戲方塊整體左移一位后,游戲方塊不能超越游戲底板的左邊線,否則越界;并且在游戲方塊有值(值為1)的位置,游戲底板必須是沒有被占用的(占用時(shí),值為1)。若滿足這兩個(gè)條件,則執(zhí)行下面的左移動(dòng)作。否則不執(zhí)行左移動(dòng)作。 (2) 清除左移前的游戲方塊。 (3) 在左移一位的位置,重新顯示此游戲方塊。 右移的實(shí)現(xiàn)過程如下: (1) 判斷在當(dāng)前游戲底板中能否右移。這一判斷必須滿足如下兩個(gè)條件:游戲方塊整體右移一位后,游戲方塊不能超越游戲底板的右邊線

15、,否則越界;并且在游戲方塊有值(值為1)的位置,游戲底板必須是沒有被占用的(占用時(shí),值為1)。若滿足這兩個(gè)條件,則執(zhí)行下面的右移動(dòng)作。否則不只執(zhí)行右移動(dòng)作。 (2) 清除右移前的游戲方塊。 (3) 在右移一位的位置,重新顯示此游戲方塊。 下移的實(shí)現(xiàn)過程如下: (1) 判斷在當(dāng)前游戲底板中能否下移。這一判斷必須滿足如下兩個(gè)條件:游戲方塊整體下移一位后,游戲方塊不能超越游戲底板的底邊線,否則越界;并且在游戲方塊有值(值為1)的位置,游戲底板必須是沒有被占用的(占用時(shí),值為1)。若滿足這兩個(gè)條件,則執(zhí)行下面的下移動(dòng)作。否則,將flag_newbox標(biāo)志置1,主循環(huán)中會(huì)判斷此標(biāo)志,若為1,則會(huì)生成下一

16、個(gè)游戲方塊,并更新預(yù)覽游戲方塊。 (2) 清除下移前的游戲方塊。 (3) 在下移一位的位置,重新顯示此游戲方塊。 旋轉(zhuǎn)的實(shí)現(xiàn)過程如下: (1) 判斷在當(dāng)前游戲底板中能否旋轉(zhuǎn)。這一判斷必須滿足如下條件:游戲方塊整旋轉(zhuǎn)后,游戲方塊不能超越游戲底板的左邊線、右邊線和底邊線,否則越界;并且在游戲方塊有值(值為1)的位置,游戲底板必須是沒有被占用的(占用時(shí),值為1)。若滿足這些條件,則執(zhí)行下面的旋轉(zhuǎn)動(dòng)作。否則不只執(zhí)行旋轉(zhuǎn)動(dòng)作。 (2) 清除旋轉(zhuǎn)前的游戲方塊。 (3) 在游戲方塊顯示區(qū)域(44)不變的位置,利用保存當(dāng)前游戲方塊的數(shù)據(jù)結(jié)構(gòu)中的next值作為旋轉(zhuǎn)后形成的新游戲方塊的編號(hào),并重新顯示這個(gè)編號(hào)的游

17、戲方塊。 當(dāng)生成新的游戲方塊前,執(zhí)行行滿的檢查,判斷行滿的過程為: 一次從下到上掃描游戲底板中的各行,若某行中1的個(gè)數(shù)等于游戲底板水平方向上的小方塊的個(gè)數(shù),則表示此行是滿的。找到滿行后,立即將游戲底板中的數(shù)據(jù)往下順移一行,直到游戲底板逐行掃描完畢。 3.1.4 游戲顯示更新 當(dāng)游戲方塊左右移動(dòng)、下落、旋轉(zhuǎn)時(shí),要清除先前的游戲方塊,用新坐標(biāo)重繪游戲方塊。當(dāng)消除滿行時(shí),要重繪游戲底板的當(dāng)前狀態(tài)。 清除方塊的過程為:用先畫輪廓再填充的方式,使用背景色填充小方塊,然后使用前景色畫一個(gè)游戲底板中的小方塊。循環(huán)此過程,變化當(dāng)前坐標(biāo),填充及畫出共16個(gè)這樣的小方塊。這樣在游戲底板中,清除了此游戲方塊。 3.

18、1.5 游戲速度分?jǐn)?shù)更新 當(dāng)判斷出一行滿時(shí),score變量一固定值(如10),可以吧等級(jí)level看作是速度speed,因?yàn)樗俣萻peed是根據(jù)計(jì)分score值不斷上升的,所以我們定義level=speed=score/speed_step,其中speed_step是每升一級(jí)所需要的分?jǐn)?shù)。方塊下落速度加快,這是不斷修改了定時(shí)計(jì)數(shù)器變量TimerCounter判斷條件的結(jié)果。速度越快,時(shí)間中斷的間隔就越短。 3.1.6 游戲幫助 實(shí)現(xiàn)比較簡單,使用outtextxy()函數(shù)實(shí)現(xiàn)。3.2 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì) 3.2.1 游戲底板BOARD結(jié)構(gòu)體 Struct BOARD Int var; Int col

19、or; Table_boardVertical_boxsHorizontal_boxs; BOARD結(jié)構(gòu)體表示游戲底板中每個(gè)小方塊所具有的屬性。其中var表示小方塊當(dāng)前狀態(tài),只有0與1兩個(gè)值,表示此小方塊已被占用,0表示未被占用。Color表示小方塊的顏色,游戲底板的每個(gè)小方塊可以擁有不同的顏色,以增強(qiáng)美觀。Vertical_boxs為游戲底板上垂直的方向上小方塊的個(gè)數(shù),Horizontal_boxs為游戲底板上水平的方向上小方塊的個(gè)數(shù)。 3.2.2 游戲方塊SHAPE結(jié)構(gòu)體 struct SHAPE char box2; int color; /*每個(gè)方塊的顏色*/ int next; /*

20、下個(gè)方塊的編號(hào)*/ ; SHAPE結(jié)構(gòu)體表示某個(gè)游戲方塊具有的屬性。其中,char box2表示用2個(gè)字節(jié)來表示這個(gè)游戲方塊的形狀。每4位來表示一個(gè)游戲方塊的一行。Color表示每個(gè)游戲方塊的顏色,顏色可設(shè)為BLACK、BLUE、GREEN、CYAN、RE、MAGENTA、BROWN、LIGHTGRAY、DARKGRAY、LIGHTBLUE、LIGHTCYAN、LIGHTRED、LIGHTMAGENTA、YELLOW和WHITE。 next表示下個(gè)游戲方塊的編號(hào),在旋轉(zhuǎn)時(shí)需要用到此編號(hào)。 如box0=0 x88,box1=0 xc0,其中0 x88和0 xc0為十六進(jìn)制表示形式,具體表現(xiàn)的含義

21、如圖3.3所示。圖3.3 SHAPE結(jié)構(gòu)示意圖 3.2.3 SHAPE結(jié)構(gòu)數(shù)組 初始化游戲方塊內(nèi)容,即定義 MAX_BOX個(gè)SHAPE類型的結(jié)構(gòu)數(shù)組,并初始化。MAX_BOX為19。應(yīng)為一共有19種不同形狀的俄羅斯方塊。struct SHAPE shapesMAX_BOX=/* * 口 口口口 口口 口 * 口 口 口 口口口 * 口口 口 */ 0 x88, 0 xc0, CYAN, 1, 0 xe8, 0 x0, CYAN, 2, 0 xc4, 0 x40, CYAN, 3, 0 x2e, 0 x0, CYAN, 0,/* * 口 口口 口口口 * 口 口 口 口 * 口口 口口口 口 *

22、/ 0 x44, 0 xc0, MAGENTA, 5, 0 x8e, 0 x0, MAGENTA, 6, 0 xc8, 0 x80, MAGENTA, 7, 0 xe2, 0 x0, MAGENTA, 4,/* * 口 * 口口 口口 * 口 口口 */ 0 x8c, 0 x40, YELLOW, 9, 0 x6c, 0 x0, YELLOW, 8,/* * 口 口口 * 口口 口口 * 口 */ 0 x4c, 0 x80, BROWN, 11, 0 xc6, 0 x0, BROWN, 10,/* * 口 口 口 * 口口口 口口 口口口 口口 * 口 口 口 */ 0 x4e, 0 x0,

23、WHITE, 13, 0 x8c, 0 x80, WHITE, 14, 0 xe4, 0 x0, WHITE, 15, 0 x4c, 0 x40, WHITE, 12,/* 口 * 口 * 口 口口口口 * 口 */ 0 x88, 0 x88, RED, 17, 0 xf0, 0 x0, RED, 16,/* * 口口 * 口口 */ 0 xcc, 0 x0, BLUE, 183.3 函數(shù)功能描述 (1) newtimer() 函數(shù)原型:void interrupt newtimer(void) Newtimer()函數(shù)用于為新的時(shí)鐘中斷處理函數(shù)。 (2) SetTimer() 函數(shù)原型:vo

24、id SetTimer(void interrupt(*IntProc)(void) SetTimer()函數(shù)用于設(shè)置新的時(shí)鐘中斷處理過程。 (3) KillTimer() 函數(shù)原型:void KillTimer() KillTimer()函數(shù)用于恢復(fù)原有的時(shí)鐘中斷處理過程。 (4) initialize() 函數(shù)原型:void initialize( int x,int y,int m,int n) Initialize()函數(shù)用于初始化界面,具體為在傳入?yún)?shù)x、y指明位置上畫m行n列小方塊,并顯示積分、等級(jí)、幫助及預(yù)覽游戲方塊等。 (5) DelFullRow() 函數(shù)原型:int Del

25、FullRow(int y) DelFullRow()函數(shù)用于處理刪除一滿行的情況。Y指明具體哪一行為滿行。 (6) setFullRow() 函數(shù)原型:void setFullRow(int t_boardy) setFullRow()函數(shù)用于找到滿行,并調(diào)用DelFullRow()函數(shù)來處理滿行。t_boardy為在游戲底板中的垂直方向的坐標(biāo)值。 (7) MkNextBox() 函數(shù)原型:int MkNextBox(int box_numb) MkNextBox()函數(shù)用于生成下一個(gè)游戲方塊,并返回方塊號(hào)。Box_numb表示當(dāng)前的游戲方塊號(hào)。 (8) EraseBox() 函數(shù)原型:vo

26、id EraseBox(int x,int y,int box_numb) EraseBox()函數(shù)用于清除(x,y)位置開始的編號(hào)為box_numb的游戲方塊。 (9) show_box() 函數(shù)原型:void show_box(int x,int y,int box_numb,int color) show_box()函數(shù)用于顯示(x,y)位置開始的編號(hào)為box_numb的、顏色值為color的游戲方塊。 (10) MoveAble() 函數(shù)原型:int MoveAble(int x,int y,int box_numb,int direction) MoveAble()函數(shù)判斷是否可以移

27、動(dòng)。(x,y)為當(dāng)前方塊位置,box_numb為方塊號(hào),direction為方向標(biāo)志,返回true和false。 (11) 主函數(shù)main() 整個(gè)游戲的主控部分。4.程序?qū)崿F(xiàn)4.1 源碼分析 4.1.1 程序預(yù)處理 包括加載頭文件,定義結(jié)構(gòu)體、常量和變量,并對(duì)它們進(jìn)行初始化工作。/*加載頭文件*/#include #include #include #include /*圖形函數(shù)庫*/*定義按鍵碼*/#define VK_LEFT 0 x4b00#define VK_RIGHT 0 x4d00#define VK_DOWN 0 x5000#define VK_UP 0 x4800#defin

28、e VK_ESC 0 x011b#define TIMER 0 x1c /*設(shè)置中斷號(hào)*/*定義常量*/#define MAX_BOX 19 /*總共有19種各形態(tài)的方塊*/#define BSIZE 20 /*方塊的邊長是20個(gè)象素*/#define Sys_x 160 /*顯示方塊界面的左上角x座標(biāo)*/#define Sys_y 25 /*顯示方塊界面的左上角y座標(biāo)*/#define Horizontal_boxs 10 /*水平的方向以方塊為單位的長度*/#define Vertical_boxs 15 /*垂直的方向以方塊為單位的長度*/#define Begin_boxs_x Hor

29、izontal_boxs/2 /*產(chǎn)生第一個(gè)方塊時(shí)出現(xiàn)的起始位置*/#define FgColor 3 /*前景顏色,如文字.2-green*/#define BgColor 0 /*背景顏色.0-blac*/#define LeftWin_x Sys_x+Horizontal_boxs*BSIZE+46 /*右邊狀態(tài)欄的x座標(biāo)*/#define false 0#define true 1/*移動(dòng)的方向*/#define MoveLeft 1#define MoveRight 2#define MoveDown 3#define MoveRoll 4/*以后坐標(biāo)的每個(gè)方塊可以看作是像素點(diǎn)是BS

30、IZE*BSIZE的正方形*/*定義全局變量*/int current_box_numb; /*保存當(dāng)前方塊編號(hào)*/int Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y; /*x,y是保存方塊的當(dāng)前坐標(biāo)的*/int flag_newbox=false; /*是否要產(chǎn)生新方塊的標(biāo)記0*/int speed=0; /*下落速度*/int score=0; /*總分*/int speed_step=30; /*每等級(jí)所需要分?jǐn)?shù)*/void interrupt (*oldtimer)(void); /* 指向原來時(shí)鐘中斷處理過程入口的中斷處理函數(shù)指針

31、 */struct BOARD /*游戲底板結(jié)構(gòu),表示每個(gè)點(diǎn)所具有的屬性*/ int var; /*當(dāng)前狀態(tài) 只有0和1,1表示此點(diǎn)已被占用*/ int color; /*顏色,游戲底板的每個(gè)點(diǎn)可以擁有不同的顏色.增強(qiáng)美觀*/Table_boardVertical_boxsHorizontal_boxs;/*方塊結(jié)構(gòu)*/struct SHAPE char box2; /*一個(gè)字節(jié)等于8位,每4位來表示一個(gè)方塊的一行 如:box0=0 x88,box1=0 xc0表示的是: 1000 1000 1100 0000*/ int color; /*每個(gè)方塊的顏色*/ int next; /*下個(gè)方塊

32、的編號(hào)*/;/*初始化方塊內(nèi)容.即定義MAX_BOX個(gè)SHAPE類型的結(jié)構(gòu)數(shù)組,并初始化*/struct SHAPE shapesMAX_BOX=/* * 口 口口口 口口 口 * 口 口 口 口口口 * 口口 口 */ 0 x88, 0 xc0, CYAN, 1, 0 xe8, 0 x0, CYAN, 2, 0 xc4, 0 x40, CYAN, 3, 0 x2e, 0 x0, CYAN, 0,/* * 口 口口 口口口 * 口 口 口 口 * 口口 口口口 口 */ 0 x44, 0 xc0, MAGENTA, 5, 0 x8e, 0 x0, MAGENTA, 6, 0 xc8, 0 x8

33、0, MAGENTA, 7, 0 xe2, 0 x0, MAGENTA, 4,/* * 口 * 口口 口口 * 口 口口 */ 0 x8c, 0 x40, YELLOW, 9, 0 x6c, 0 x0, YELLOW, 8,/* * 口 口口 * 口口 口口 * 口 */ 0 x4c, 0 x80, BROWN, 11, 0 xc6, 0 x0, BROWN, 10,/* * 口 口 口 * 口口口 口口 口口口 口口 * 口 口 口 */ 0 x4e, 0 x0, WHITE, 13, 0 x8c, 0 x80, WHITE, 14, 0 xe4, 0 x0, WHITE, 15, 0 x4

34、c, 0 x40, WHITE, 12,/* 口 * 口 * 口 口口口口 * 口 */ 0 x88, 0 x88, RED, 17, 0 xf0, 0 x0, RED, 16,/* * 口口 * 口口 */ 0 xcc, 0 x0, BLUE, 18;unsigned int TimerCounter=0; /*定時(shí)計(jì)數(shù)器變量*/ 4.1.2 主函數(shù)main() Main()函數(shù)主要是實(shí)現(xiàn)了對(duì)整個(gè)程序的運(yùn)行控制,以及相關(guān)功能模塊的調(diào)用。void main() int GameOver=0; int key,nextbox; int Currentaction=0;/*標(biāo)記當(dāng)前動(dòng)作狀態(tài)*/ i

35、nt gd=VGA,gm=VGAHI,errorcode; initgraph(&gd,&gm,); errorcode = graphresult(); if (errorcode != grOk) printf(nNotice:Graphics error: %sn, grapherrormsg(errorcode); printf(Press any key to quit!); getch(); exit(1); setbkcolor(BgColor); setcolor(FgColor); randomize(); SetTimer(newtimer); initialize(Sys

36、_x,Sys_y,Horizontal_boxs,Vertical_boxs);/*初始化*/ nextbox=MkNextBox(-1); show_box(Curbox_x,Curbox_y,current_box_numb,shapescurrent_box_numb.color); show_box(LeftWin_x,Curbox_y+200,nextbox,shapesnextbox.color); show_intro(Sys_x,Curbox_y+320); getch(); while(1) /* Currentaction=0; flag_newbox=false; 檢測是

37、否有按鍵*/ if (bioskey(1)key=bioskey(0); else key=0; switch(key) case VK_LEFT: if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveLeft) EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x-=BSIZE;Currentaction=MoveLeft; break; case VK_RIGHT: if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveRight) Era

38、seBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x+=BSIZE;Currentaction=MoveRight; break; case VK_DOWN: if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown) EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;Currentaction=MoveDown; else flag_newbox=true; break; case VK_UP:/*旋轉(zhuǎn)方塊*/ if(M

39、oveAble(Curbox_x,Curbox_y,shapescurrent_box_numb.next,MoveRoll) EraseBox(Curbox_x,Curbox_y,current_box_numb);current_box_numb=shapescurrent_box_numb.next; Currentaction=MoveRoll; break; case VK_ESC: GameOver=1; break; default: break; if(Currentaction) /*表示當(dāng)前有動(dòng)作,移動(dòng)或轉(zhuǎn)動(dòng)*/ show_box(Curbox_x,Curbox_y,cur

40、rent_box_numb,shapescurrent_box_numb.color); Currentaction=0; /*按了往下鍵,但不能下移,就產(chǎn)生新方塊*/ if(flag_newbox) /*這時(shí)相當(dāng)于方塊到底部了,把其中出現(xiàn)點(diǎn)滿一行的清去,置0*/ ErasePreBox(LeftWin_x,Sys_y+200,nextbox); nextbox=MkNextBox(nextbox); show_box(LeftWin_x,Curbox_y+200,nextbox,shapesnextbox.color); if(!MoveAble(Curbox_x,Curbox_y,curr

41、ent_box_numb,MoveDown)/*剛一開始,游戲結(jié)束*/ show_box(Curbox_x,Curbox_y,current_box_numb,shapescurrent_box_numb.color); GameOver=1; else flag_newbox=false; Currentaction=0; else /*自由下落*/ if (Currentaction=MoveDown | TimerCounter (20-speed*2) if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown) EraseBox(C

42、urbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE; show_box(Curbox_x,Curbox_y,current_box_numb,shapescurrent_box_numb.color); TimerCounter=0; if(GameOver )/*| flag_newbox=-1*/ printf(game over,thank you! your score is %d,score); getch(); break; getch(); KillTimer(); closegraph(); 4.1.3 初始化界面 玩家進(jìn)行游戲

43、時(shí),需要對(duì)游戲界面進(jìn)行初始化工作。此代碼被main()函數(shù)調(diào)用。主要進(jìn)行的工作如下: (1) 循環(huán)調(diào)用line()函數(shù)繪制當(dāng)前游戲板。 (2) 調(diào)用ShowScore()函數(shù)顯示初始的成績,初始成績?yōu)?。 (3) 調(diào)用ShowSpeed()函數(shù)顯示初始的速度(等級(jí)),初始速度1。/*初始化界面* *參數(shù)說明: * x,y為左上角坐標(biāo) * m,n對(duì)應(yīng)于Vertical_boxs,Horizontal_boxs * 分別表示縱橫方向上方塊的個(gè)數(shù)(以方塊為單位) * BSIZE Sys_x Sys_y */void initialize(int x,int y,int m,int n) int i,

44、j,oldx; oldx=x; for(j=0;jn;j+) for(i=0;i=t_boardy;n-) if(n=Vertical_boxs )continue; /*超過低線了*/ for(m=0;mHorizontal_boxs;m+) /*水平的方向*/ if(!Table_boardn+full_numbm.var)break; /*發(fā)現(xiàn)有一個(gè)是空就跳過該行*/ if(m=Horizontal_boxs) /*找到滿行了*/ if(n=t_boardy+3) /*第一次獻(xiàn)給了n,最高的*/ top=DelFullRow(n+full_numb); /*清除游戲板里的該行,并下移數(shù)據(jù)

45、*/ else DelFullRow(n+full_numb); full_numb+; /*統(tǒng)計(jì)找到的行數(shù)*/ if(full_numb) int oldx,x=Sys_x,y=BSIZE*top+Sys_y; oldx=x; score=score+full_numb*10; /*加分?jǐn)?shù)*/ /*這里相當(dāng)于重顯調(diào)色板*/ for(n=top;n=Vertical_boxs)continue; /*超過低線了*/ for(m=0;m=0;n-)/*從當(dāng)前行往上看*/ totoal=0; for(m=0;mHorizontal_boxs;m+) if(!Table_boardnm.var)to

46、toal+; /*沒占有方格+1*/ if(Table_boardnm.var!=Table_boardn-1m.var) /*上行不等于下行就把上行傳給下行 xor關(guān)系*/ Table_boardnm.var=Table_boardn-1m.var; Table_boardnm.color=Table_boardn-1m.color; if(totoal=Horizontal_boxs) /*發(fā)現(xiàn)上面有連續(xù)的空行提前結(jié)束*/ top=n; break; return(top); /*返回最高點(diǎn)*/ 4.1.7 游戲方塊的顯示和清除 游戲方塊的顯示和清除是游戲中經(jīng)常出現(xiàn)的操作。主要進(jìn)行的過程如

47、下: (1) 調(diào)用show_box(int x,int y,int box_numb,int color)函數(shù),在(x,y)位置開始,用指定顏色color顯示編號(hào)為box_numb的游戲方塊。 (2) 調(diào)用EraseBox(int x,int y,int box_numb) 函數(shù),清除在(x,y)位置開始的方塊編號(hào)為box_numb的游戲方塊。/* *顯示指定的方塊 */void show_box(int x,int y,int box_numb,int color) int i,ii,ls_x=x; if(box_numb=MAX_BOX)/*指定的方塊不存在*/ box_numb=MAX_

48、BOX/2; setfillstyle(SOLID_FILL,color);/* * 移位來判斷第哪一位是1 * 方塊是每1行用半個(gè)字節(jié)來表示 * 128d=1000 0000b */ for(ii=0;ii2;ii+) int mask=128; for(i=0;i8;i+) if(i%4=0 & i!=0) /*表示轉(zhuǎn)到方塊的下一行了*/ y+=BSIZE; x=ls_x; if(shapesbox_numb.boxii)&mask) bar(x,y,x+BSIZE,y+BSIZE); line(x,y,x+BSIZE,y); line(x,y,x,y+BSIZE); line(x,y+B

49、SIZE,x+BSIZE,y+BSIZE); line(x+BSIZE,y,x+BSIZE,y+BSIZE); x+=BSIZE; mask/=2; y+=BSIZE; x=ls_x; /* * 擦除(x,y)位置開始的編號(hào)為box_numb的box. */void EraseBox(int x,int y,int box_numb) int mask=128,t_boardx,t_boardy,n,m; setfillstyle(SOLID_FILL,BgColor); for(n=0;n4;n+) for(m=0;m4;m+) /*看最左邊四個(gè)單元*/ if( (shapesbox_num

50、b.boxn/2) & mask) )/*最左邊有方塊并且當(dāng)前游戲板也有方塊*/ bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE); line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE); line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE,y+n*BSIZE+BSIZE); line(x+m*BSIZE,y+n*BSIZE+BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE); line(x+m*BSIZE+BSIZE,y+n*BSIZE

51、,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE); mask=mask/(2); if(mask=0)mask=128; void ErasePreBox(int x,int y,int box_numb) int mask=128,t_boardx,t_boardy,n,m; setfillstyle(SOLID_FILL,BgColor); for(n=0;n4;n+) for(m=0;m4;m+) /*看最左邊四個(gè)單元*/ if( (shapesbox_numb.boxn/2) & mask) )/*最左邊有方塊并且當(dāng)前游戲板也有方塊*/ bar(x+m*BSIZE,y

52、+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE); mask=mask/(2); if(mask=0)mask=128; /* * 將新形狀的方塊放置在游戲板上,并返回此方塊號(hào) */int MkNextBox(int box_numb) int mask=128,t_boardx,t_boardy,n,m; t_boardx=(Curbox_x-Sys_x)/BSIZE; t_boardy=(Curbox_y-Sys_y)/BSIZE; for(n=0;n4;n+) for(m=0;m4;m+) if( (shapescurrent_box_numb.boxn

53、/2) & mask) ) Table_boardt_boardy+nt_boardx+m.var=1;/*這里設(shè)置游戲板*/ Table_boardt_boardy+nt_boardx+m.color=shapescurrent_box_numb.color;/*這里設(shè)置游戲板*/ mask=mask/(2); if(mask=0)mask=128; setFullRow(t_boardy); Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*再次初始化座標(biāo)*/ if(box_numb=-1) box_numb=rand()%MAX_BOX

54、; current_box_numb=box_numb; flag_newbox=false; return(rand()%MAX_BOX); 4.1.8 游戲方塊操作判斷處理 游戲方塊操作判斷處理主要執(zhí)行對(duì)當(dāng)前操作進(jìn)行條件判斷,若滿足相關(guān)條件,則返回true,即允許執(zhí)行此操作。此判斷由MoveAble(int x,int y,int box_numb,int direction)函數(shù)來實(shí)現(xiàn),其中(x,y)為當(dāng)前游戲方塊位置,box_numb為游戲方塊號(hào),direction為左移、右移、下移或自由下落、旋轉(zhuǎn)的標(biāo)志。對(duì)這些動(dòng)作判斷的實(shí)現(xiàn)基本相同,因此,下面以對(duì)左移操作的判斷為例講述其實(shí)現(xiàn)過程。

55、(1) 計(jì)算出游戲方塊左移一個(gè)方塊后的新的相對(duì)坐標(biāo)(t_boardx,t_boardy),并初始化mask=128(10000000)。Mask用來對(duì)當(dāng)前游戲方塊的box值進(jìn)行按位于操作,逐位判斷box0的值,box在結(jié)構(gòu)體中定義為int box2,即有兩個(gè)元素的數(shù)組。若box0&mask=1,則表示box0的最高位是1,在游戲方塊中表示此位置不為空。 (2) 逐行逐列進(jìn)行判斷,共4行4列,即游戲方塊的大小。對(duì)每個(gè)小方塊一次進(jìn)行判斷,若小方塊的值是1,左移一位后其橫坐標(biāo)沒有超過游戲主板的最左邊,并且在此位置游戲主板的值Table_boardt_boardy+nt_boardx+m.var為0,

56、即表示是空的,則可以執(zhí)行左移操作。任意小方塊不滿足上述任意條件,都不能執(zhí)行此左移操作。/* 判斷是否可以移動(dòng) * x,y為當(dāng)前方塊位置 * box_numb為方塊號(hào) * direction 方向標(biāo)志 * 返回true 和false #define MoveLeft -1 #define MoveRight 1 #define MoveDown 0 */int MoveAble(int x,int y,int box_numb,int direction) int n,m,t_boardx,t_boardy; /*t_boardx 當(dāng)前方塊最左邊在游戲板的位置*/ int mask; if(di

57、rection=MoveLeft) /*如果向左移*/ mask=128; x-=BSIZE; t_boardx=(x-Sys_x)/BSIZE; t_boardy=(y-Sys_y)/BSIZE; for(n=0;n4;n+) for(m=0;m4;m+) /*看最左邊四個(gè)單元*/ if(shapesbox_numb.boxn/2) & mask)/*最左邊有方塊并且當(dāng)前游戲板也有方塊*/ if(x+BSIZE*m)Sys_x)return(false);/*碰到最左邊了*/ else if(Table_boardt_boardy+nt_boardx+m.var) /*左移一個(gè)方塊后,此4*

58、4的區(qū)域與游戲板有沖突*/ return(false); mask=mask/(2); if(mask=0)mask=128; return(true); else if(direction=MoveRight) /*如果向右移*/ x+=BSIZE; t_boardx=(x-Sys_x)/BSIZE; t_boardy=(y-Sys_y)/BSIZE; mask=128; for(n=0;n4;n+) for(m=0;m=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最右邊了*/ else if( Table_boardt_boardy+n

59、t_boardx+m.var) return(false); mask=mask/(2); if(mask=0)mask=128; return(true); else if(direction=MoveDown) /*如果向下移*/ y+=BSIZE; t_boardx=(x-Sys_x)/BSIZE; t_boardy=(y-Sys_y)/BSIZE; mask=128; for(n=0;n4;n+) for(m=0;m=(Sys_y+BSIZE*Vertical_boxs) | Table_boardt_boardy+nt_boardx+m.var) flag_newbox=true;

60、break; mask=mask/(2); /*mask依次為:10000000,01000000,00100000,00010000 00001000,00000100,00000010/00000001 */ if(mask=0)mask=128; if(flag_newbox) return(false); else return(true); else if(direction=MoveRoll) /*轉(zhuǎn)動(dòng)*/ t_boardx=(x-Sys_x)/BSIZE; t_boardy=(y-Sys_y)/BSIZE; mask=128; for(n=0;n4;n+) for(m=0;m=(

溫馨提示

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

評(píng)論

0/150

提交評(píng)論