效果圖

用C語言實現俄羅斯方塊,需要先解決下面幾個問題:
**1、如何用C語言繪制圖形界面**
EasyX圖形庫(http://www.easyx.cn)即TC的圖形庫在VC下的移植。
包含庫#include <graphics.h>
先初始化圖形窗口
initgraph(WINDOW_WIDTH, WINDOW_HIGH) ;WINDOW_WIDTH為窗口的寬帶,WINDOW_HIGH為窗口的高度。
清空繪圖設備
cleardevice();
設置畫筆顏色
setcolor(RED) ;
設置線條風格
setlinestyle(PS_SOLID, NULL, 0);
畫矩形
rectangle
還有畫線、顯示文字等函數,可以參照其幫助文檔。
注意:由于我們用的是EasyX圖形庫,故源文件后綴要為.cpp,但其中內容都是C的語法。
**2、如何存儲表示出俄羅斯方塊的形狀**
在計算機中如何讓一串的01數字,代表俄羅斯方塊?
一、我們可以用編號,不同的編號代表不同的俄羅斯方塊,根據編號把不同方塊的畫法寫在代碼中,這樣19種
方塊就得有19種相應的代碼來描繪。而且這樣擴展性不好,若以后設計了新的方塊,則需要更改大量源代碼。
二、我們很自然的想到可用字模點陣的形式來表示,即設置一個4行4列的數組,元素置1即代表這個位置有小
方塊,元素置0即代表這個位置無小方塊,這個整個的4*4的數組組成俄羅斯方塊的形狀。
1000
1000
1100
0000

這個方法挺靠譜,但我們還可以優化一下:不用4*4的數組,而是用16個bit位來表示這個點陣。這樣存儲起來比較方便,故我們用unsigned int 的低16位來表示方塊的點陣。
我們可以用掩碼與表示俄羅斯方塊的位進行操作,來識別并在屏幕上畫出方塊。
詳情見GUI.cpp中的DrawRock函數。
~~~
//逐位掃描由unsigned int的低2字節
//16個位組成的俄羅斯方塊形狀點陣(其代表4*4的方塊形狀)
mask = (unsigned int)1 << 15 ;
for (i=1; i<=16; i++)
{
//與掩碼相與為1的 即為方塊上的點
if ((rockArray[rockIndex].rockShapeBits & mask) != 0)
{
//在屏幕上畫出此方塊
rectangle(rockX+2,
rockY+2,
rockX+ROCK_SQUARE_WIDTH-2,
rockY+ROCK_SQUARE_WIDTH-2) ;
}
//每4次 換行 轉到下一行繼續畫
i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left)
: rockX += ROCK_SQUARE_WIDTH ;
mask >>= 1 ;
}
~~~
我們把俄羅斯方塊點陣的數位存在rockArray中,我們可以事先把這19種方塊的字模點陣自己轉化成十六進制,然后在rockArray數組的初始化時賦值進去。
但這樣做未免有點太費力,且擴展性也不太好,若以后設計的新方塊種類加入,要改變數組rockArray中的值。
我們可以考慮把所有俄羅斯方塊的點陣**存儲在配置文件中**,在程序初始化時讀取文件,把這些點陣轉換成unsigned int的變量存儲在rockArray中。
這樣,以后我們增添新的方塊形狀只需要在配置文件中增加新的點陣即可。
@###
@###
@@##
####?? (為使得看起來更醒目,我們用@表示1,用#表示0)
**3、如何讓圖形動起來**
若沒有按鍵的情況下,方塊是自動下落的。
如何實現自動下落?在某位置處用函數DrawRock在屏幕上畫出俄羅斯方塊,然后再擦除掉(即用背景色在原位置處重繪一次方塊),最后在下落的下一個位置處用函數DrawRock在屏幕上畫出俄羅斯方塊,如此循環,中間用計時器間隔一段時間以控制下落的速度。
同理,按下屏幕的左右鍵也是如此,只是在按下鍵盤時把方塊的位置重新計算了。
那么按下上方向鍵時,如何讓方塊翻轉呢?
我們在配置文件中就把方塊的順時針翻轉形態放在了一起:
@###
@###
@@##
####
@@@#
@###
####
####
@@##
#@##
#@##
####
?##@#
@@@#
####
####
我們每按一次上方向鍵改變一次方塊的形狀即可。若一直按上鍵,形狀應該是循環地翻滾。
我們想到了循環鏈表的數據結構可實現這個效果。
可是我們若把這些一種類的方塊的各種形態串成循環鏈表形式,那么每次重新生成方塊時我們就難以隨機地生成方塊了。
故還是得用數組來存儲,但又要有循環鏈表的功能,于是我們想到了**靜態循環鏈表**。
我們用結構體來作為一個方塊在rockArray中的元素
typedef struct ROCK
{? //用來表示方塊的形狀(每一個字節是8位,用每4位表示方塊中的一行)
?? unsigned int rockShapeBits ;?
?? int????????? nextRockIndex ;? //下一個方塊,在數組中的下標
} RockType ;

這樣,當我們按下上方向鍵時,把傳入函數DrawRock中的rockIndex變為當前方塊結構體中的nextRockIndex即可。
詳情見play.cpp中的ProccessUserHit函數。
**4、如何判斷方塊什么時候停止什么時候滿行得分**
方塊一直下落,最終是要停下來的,我們要設置一個邊界來約束方塊的移動范圍。我們把當前游戲界面劃分成以俄羅斯方塊中的小方格為單位的格子,用一個二維數組g_gameBoard來表示這些小方格的狀態,1表示此位置有方塊,0表示此位置為空。
我們按照界面的大小和方格的大小來計算此二維數組時,再多設置一圈“圍墻”,即多加兩行兩列,并把它們的值初始化為1。
當方塊準備下落或是左右移動的時候,前提前檢查其即將落下的位置是否為空,若不為空,則停止下落,并把當前俄羅斯方塊占用的方格都設置為1。
詳情見play.cpp中的moveAbled函數。
判斷滿行:
從最后一行開始往上檢查g_gameBoard,若有一行全為1,則說明此行滿行,將此行擦出,把此行上面的所有行向下移動一個單位。
詳情見play.cpp中的ProcessFullRow函數
**5、其他細節問題:**
如何快速下落
詳情見play.cpp中的FastFall函數
如何暫停
詳情見play.cpp中的ProccessUserHit函數
此游戲程序的主要邏輯在play.cpp中的PlayGame函數
[**源代碼點擊這里**](http://blog.csdn.net/yang_yulei/article/details/17651961)