下面是頭文件head.h
/************************ (C) COPYRIGHT 2013 yang_yulei ************************ * File Name : head.h * Author : yang_yulei * Date First Issued : 12/18/2013 * Description : * * *******************************************************************************/ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef _HEAD_H_ #define _HEAD_H_ /* Includes ------------------------------------------------------------------*/ #include#include #include #include #include /* Macro ---------------------------------------------------------------------*/ #define TRUE 1 #define FALSE 0 //GUI游戲界面相關的參數 #define GUI_WALL_SQUARE_WIDTH 10 //外圍圍牆小方格的寬度(單位:像素) #define GUI_xWALL_SQUARE_NUM 30 //橫向(x軸方向)圍牆小方格的數量(必須是偶數) #define GUI_yWALL_SQUARE_NUM 46 //縱向(y軸方向)圍牆小方格的數量(必須是偶數) #define GUI_WALL_WIDTH_PIX (GUI_WALL_SQUARE_WIDTH*GUI_xWALL_SQUARE_NUM) #define GUI_WALL_HIGH_PIX (GUI_WALL_SQUARE_WIDTH*GUI_yWALL_SQUARE_NUM) #define WINDOW_WIDTH 480 //窗口的寬度 #define WINDOW_HIGH GUI_WALL_HIGH_PIX //窗口高度 //俄羅斯方塊相關的參數 //移動的方向 #define DIRECT_UP 3 #define DIRECT_DOWN 2 #define DIRECT_LEFT -1 #define DIRECT_RIGHT 1 //每一個小方塊的大小(是圍牆小方格寬度的2倍) #define ROCK_SQUARE_WIDTH (2*GUI_WALL_SQUARE_WIDTH) //橫向能容納小方格的數量 #define X_ROCK_SQUARE_NUM ((GUI_xWALL_SQUARE_NUM-2)/2) //縱向能容納小方格的數量 #define Y_ROCK_SQUARE_NUM ((GUI_yWALL_SQUARE_NUM-2)/2) /* Exported types ------------------------------------------------------------*/ typedef int BOOL ; //布爾值類型 /*數據結構-線性表(結構體數組)*/ typedef struct ROCK { //用來表示方塊的形狀(每一個字節是8位,用每4位表示方塊中的一行) unsigned int rockShapeBits ; int nextRockIndex ; //下一個方塊,在數組中的下標 } RockType ; //方塊在圖形窗口中的位置(即定位4*4大塊的左上角坐標) typedef struct LOCATE { int left ; int top ; } RockLocation_t ; /* Function prototypes -------------------------------------------------------*/ //源文件play.c中 void PlayGame(void) ; //源文件init.c中 int InitProcParameters(void) ; //源文件GUI.c中 void DrawRock(int, const struct LOCATE *, BOOL) ; void DrawGameGUI(void) ; void UpdataScore(void) ; void UpdataGrade(int) ; #endif /* _HEAD_H_ */ /*********************** (C) COPYRIGHT 2013 yang_yulei *********END OF FILE****/
下面是源文件main.cpp
/************************ (C) COPYRIGHT 2013 yang_yulei ************************ * File Name : main.cpp * Author : yang_yulei * Date First Issued : 1/16/2012 * Description : 開發環境 VC++ 6.0 含EasyX圖形庫(http://www.easyx.cn) * 俄羅斯方塊 * * ******************************************************************************** * History: * 1/16/2012 : V0.1 * 12/18/2013 : V0.2 ******************************************************************************** * *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include head.h #include下面是源文件init.cpp---游戲運行前 初始化的一些方法#include /* Typedef -------------------------------------------------------------------*/ /* Variables -----------------------------------------------------------------*/ //全局變量-游戲板的狀態描述(即表示當前界面哪些位置有方塊) //0表示沒有,1表示有(多加了兩行和兩列,形成一個圍牆,便於判斷方塊是否能夠移動) char g_gameBoard[Y_ROCK_SQUARE_NUM+2][X_ROCK_SQUARE_NUM+2] = {0} ; //統計分數 int g_score = 0 ; //等級 int g_grade = 0 ; int g_rockTypeNum = 0 ; //共有多少種俄羅斯方塊 RockType rockArray[50] = {(0,0)} ; /******************************************************************************* * Function Name : main * Description : Main program * Input : None * Output : None * Return : None *******************************************************************************/ int main(void) { //畫出游戲界面 initgraph(WINDOW_WIDTH, WINDOW_HIGH) ; //初始化圖形窗口 cleardevice() ; DrawGameGUI() ; //使用 API 函數修改窗口名稱 HWND hWnd = GetHWnd(); SetWindowText(hWnd, 俄羅斯方塊); //初始化參數 InitProcParameters() ; //游戲過程 PlayGame() ; closegraph() ; return 0 ; }
/************************ (C) COPYRIGHT 2013 yang_yulei ************************ * File Name : init.cpp * Author : yang_yulei * Date First Issued : 12/18/2013 * Description : * ******************************************************************************** * *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include head.h /* Variables -----------------------------------------------------------------*/ extern char g_gameBoard[][X_ROCK_SQUARE_NUM+2] ; extern int g_rockTypeNum ; extern RockType rockArray[] ; /* Function prototypes -------------------------------------------------------*/ static int ReadRockShape(void) ; static unsigned int ShapeStr2uInt(char* const); /******************************************************************************* * Function Name : InitProcParameters * Description : 在正式開始運行游戲前,初始化一些參數:g_gameBoard 從配置文件中讀取系統中俄羅斯方塊的形狀 * Be called : main * Input : None * Output : g_gameBoard rockArray * Return : None *******************************************************************************/ //初始化程序參數 int InitProcParameters(void) { int i ; //初始化游戲板(把這個二維數組的四周置1,當作圍牆,用於判斷邊界) for (i = 0; i < X_ROCK_SQUARE_NUM+2; i++) { g_gameBoard[0][i] = 1 ; g_gameBoard[Y_ROCK_SQUARE_NUM+1][i]= 1 ; } for (i = 0; i < Y_ROCK_SQUARE_NUM+2; i++) { g_gameBoard[i][0] = 1 ; g_gameBoard[i][X_ROCK_SQUARE_NUM+1]= 1 ; } //從配置文件中讀取游戲中所有方塊的形狀點陣 ReadRockShape() ; return 0 ; } /******************************************************************************* * Function Name : ReadRockShape * Description : 從配置文件中讀取系統中俄羅斯方塊的形狀 把它記錄在rockArray中 * Be called : InitProcParameters * Input : rockshape.ini * Output : rockArray * Return : 成功返回0 失敗返回1 *******************************************************************************/ int ReadRockShape(void) { FILE* fp ; int i = 0 ; int len = 0 ; int rockArrayIdx = 0 ; int shapeNumPerRock = 0 ; //一種方塊的形態數目(用於計算方塊的nextRockIndex) char rdBuf[128] ; char rockShapeBitsStr[128] = {0}; unsigned int shapeBits = 0 ; g_rockTypeNum = 0 ; //打開配置文件 從中讀取方塊的形狀 fp = fopen(.\rockshape.ini, r) ; if (fp == NULL) { perror(open file error! ) ; return 1 ; } while (fgets(rdBuf, 128, fp) != NULL) { len = strlen(rdBuf) ; rdBuf[len-1] = '' ; switch (rdBuf[0]) { case '@': case '#': strcat(rockShapeBitsStr, rdBuf) ; break ; case 0 : //一個方塊讀取結束 shapeBits = ShapeStr2uInt(rockShapeBitsStr) ; rockShapeBitsStr[0] = 0 ; shapeNumPerRock++ ; rockArray[rockArrayIdx].rockShapeBits = shapeBits ; rockArray[rockArrayIdx].nextRockIndex = rockArrayIdx + 1 ; rockArrayIdx++ ; g_rockTypeNum++ ; //記錄方塊數量的全局變量+1 break ; case '-'://一種方塊讀取結束(更新其nextRockIndex值) rockArray[rockArrayIdx-1].nextRockIndex = rockArrayIdx - shapeNumPerRock ; shapeNumPerRock = 0 ; break ; default : break ; } }//while() return 0 ; } /******************************************************************************* * Function Name : ShapeStr2uInt * Description : 把配置文件中的描述方塊形狀的字符串 轉化為 unsigned int型 * Be called : * Input : shapeStr 描述方塊形狀的字符串(從文件中讀取的) * Output : None * Return : unsigned int型的方塊形狀點陣(用其低16位表示) *******************************************************************************/ unsigned int ShapeStr2uInt(char* const shapeStr) { unsigned int shapeBitsRet = 0 ; char* p = shapeStr ; for (p += 15; p >= shapeStr; p--) { if (*p == '@') { shapeBitsRet |= ((unsigned int)1 << (&shapeStr[15]-p)) ; } } return shapeBitsRet ; }下面是源文件GUI.cpp---一些關於在界面上畫出界面的一些方法
/************************ (C) COPYRIGHT 2013 yang_yulei ************************ * File Name : GUI.cpp * Author : yang_yulei * Date First Issued : 12/18/2013 * Description : * ******************************************************************************** * *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include head.h /* Variables -----------------------------------------------------------------*/ //預覽區位置 RockLocation_t previewLocation = {GUI_WALL_SQUARE_WIDTH*GUI_xWALL_SQUARE_NUM+70, 50} ; extern RockType rockArray[] ; /******************************************************************************* * Function Name : DrawRock * Description : 在游戲區畫出編號為rockIndex的方塊 * Be called : PlayGame() * Input : rockIndex : currentLocatePtr: 此方塊的位置 displayed : 此方塊是否顯示 * Output : None * Return : None *******************************************************************************/ void DrawRock(int rockIndex, const struct LOCATE * currentLocatePtr, BOOL displayed) { int i ; int mask ; int rockX ; //俄羅斯方塊的4*4模型的左上角點x軸的坐標 int rockY ; //俄羅斯方塊的4*4模型的左上角點y軸的坐標 int spaceFlag ; //占位標記(用於g_gameBoard,1表示某處有方塊 0表示此處無方塊) int color ; //畫出的方塊的顏色 //若此方塊是用於顯示的,則設置其顏色為白色,其占位標記設為1 //否則設置其顏色為黑色(背景色),占位標記設為0 displayed ? (color = WHITE,spaceFlag = 1) : (color = BLACK,spaceFlag = 0) ; setcolor(color) ; //設置畫筆顏色 setlinestyle(PS_SOLID, NULL, 2) ; //設置線形為1像素的實線 rockX = currentLocatePtr->left ; rockY = currentLocatePtr->top ; //逐位掃描由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 ; } } /******************************************************************************* * Function Name : DrawGameGUI * Description : 畫出游戲界面 * Be called : main() * Input : None * Output : None * Return : None *******************************************************************************/ void DrawGameGUI(void) { int i = 0 ; int wallHigh = GUI_yWALL_SQUARE_NUM * GUI_WALL_SQUARE_WIDTH ;//圍牆的高度(像素) setcolor(RED) ; //設置圍牆的顏色 setlinestyle(PS_SOLID, NULL, 0) ; //設置圍牆方格的線形(1像素的實線) //畫出圍牆(畫矩形是 先確定左上頂點的坐標,再確定右下頂點坐標) //先畫出上下牆 for (i = GUI_WALL_SQUARE_WIDTH; i <= GUI_WALL_WIDTH_PIX; i += GUI_WALL_SQUARE_WIDTH) { rectangle(i-GUI_WALL_SQUARE_WIDTH, 0, i, GUI_WALL_SQUARE_WIDTH) ; //上牆 rectangle(i-GUI_WALL_SQUARE_WIDTH, wallHigh-GUI_WALL_SQUARE_WIDTH, i, wallHigh) ; //下牆 } //再畫出左右牆 for (i = 2*GUI_WALL_SQUARE_WIDTH; i <= wallHigh-GUI_WALL_SQUARE_WIDTH; i += GUI_WALL_SQUARE_WIDTH) { rectangle(0, i-GUI_WALL_SQUARE_WIDTH, GUI_WALL_SQUARE_WIDTH, i) ; //左牆 rectangle(GUI_WALL_WIDTH_PIX-GUI_WALL_SQUARE_WIDTH, i-GUI_WALL_SQUARE_WIDTH, GUI_WALL_WIDTH_PIX, i) ; //右牆 } //畫分隔線 setcolor(WHITE) ; //設置畫筆顏色 setlinestyle(PS_DASH, NULL, 2) ; //設置線形為2像素的虛線 line(GUI_WALL_WIDTH_PIX+20,0,GUI_WALL_WIDTH_PIX+20,wallHigh) ; //在偏移右圍牆的20處畫線 //畫右邊統計分數及版權信息欄 //先設置字體 LOGFONT f ; //定義字體屬性結構體 getfont(&f) ; //獲得當前字體 f.lfHeight = 18 ; //設置字體高度為 38(包含行距) strcpy(f.lfFaceName, 黑體) ; //設置字體為“黑體” f.lfQuality = ANTIALIASED_QUALITY ; //設置輸出效果為抗鋸齒 setfont(&f) ; //設置字體樣式 //1,顯示預覽 outtextxy(GUI_WALL_WIDTH_PIX+80 , 20 , 預覽) ; //2,顯示等級欄 outtextxy(GUI_WALL_WIDTH_PIX+80 , 140 , 等級) ; //3,顯示得分欄 outtextxy(GUI_WALL_WIDTH_PIX+80 , 190 , 得分) ; //4,顯示操作說明 outtextxy(GUI_WALL_WIDTH_PIX+65 , 255 , 操作說明) ; getfont(&f) ; strcpy(f.lfFaceName, 宋體) ; f.lfHeight = 15 ; setfont(&f) ; outtextxy(GUI_WALL_WIDTH_PIX+45 , 290 , w.a.s.d控制方向) ; outtextxy(GUI_WALL_WIDTH_PIX+45 , 313 , 回車鍵 暫停) ; outtextxy(GUI_WALL_WIDTH_PIX+45 , 336 , 空格鍵 快速下落) ; //5.版權信息 line(GUI_WALL_WIDTH_PIX+20 , wallHigh-65 , WINDOW_WIDTH , wallHigh-65) ; outtextxy(GUI_WALL_WIDTH_PIX+40 , wallHigh-50 , 楊溢之 作品) ; outtextxy(GUI_WALL_WIDTH_PIX+40 , wallHigh-30 , QQ:702080167) ; //顯示等級,得分信息 setcolor(RED) ; outtextxy(GUI_WALL_WIDTH_PIX+90 , 163 , 1) ; outtextxy(GUI_WALL_WIDTH_PIX+90 , 223 , 0) ; } /******************************************************************************* * Function Name : UpdataScore * Description : 增加一次得分,並把游戲界面的得分區顯示 更新 * Be called : ProcessFullRow() * Input : None * Output : None * Return : None *******************************************************************************/ void UpdataScore(void) { char scoreStr[5] ; //用字符串的形式存儲得分 extern int g_score ; extern int g_grade ; //分數的增長的單位是10 g_score += 10 ; //得分是100的倍數,則等級加1 (等級在5級以上的就 保持不變) if (g_score == (g_score/100)*100 && g_grade < 5) UpdataGrade(++g_grade) ; //刪除原先信息 setfillstyle(BLACK) ; bar(GUI_WALL_WIDTH_PIX+90,220,GUI_WALL_WIDTH_PIX+99,229) ; //顯示信息 setcolor(RED) ; sprintf(scoreStr , %d , g_score) ; outtextxy(GUI_WALL_WIDTH_PIX+90 , 223 , scoreStr) ; } /******************************************************************************* * Function Name : UpdataGrade * Description : 增加一次等級,並把游戲界面的等級區顯示 更新 * Be called : * Input : grade :新的等級值 * Output : None * Return : None *******************************************************************************/ void UpdataGrade(int grade) { char gradeStr[5] ; //刪除原先信息 setfillstyle(BLACK) ; bar(GUI_WALL_WIDTH_PIX+90,160,GUI_WALL_WIDTH_PIX+99,169) ; //顯示信息 setcolor(RED) ; sprintf(gradeStr , %d , grade) ; outtextxy(GUI_WALL_WIDTH_PIX+90 , 163 , gradeStr) ; }下面是源文件play.cpp---控制游戲的重要方法
/************************ (C) COPYRIGHT 2013 yang_yulei ************************ * File Name : play.cpp * Author : yang_yulei * Date First Issued : 12/18/2013 * Description : * ******************************************************************************** * *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #include head.h /* Variables -----------------------------------------------------------------*/ extern char g_gameBoard[][X_ROCK_SQUARE_NUM+2] ; extern int g_rockTypeNum ; extern RockType rockArray[] ; /* Function prototypes -------------------------------------------------------*/ static BOOL MoveAble(int, const struct LOCATE *, int) ; static void SetOccupyFlag(int, const struct LOCATE *) ; static void ProcessFullRow(void) ; static BOOL isGameOver() ; static void ProccessUserHit(int, int*, struct LOCATE*) ; static void FastFall(int, struct LOCATE *, struct LOCATE *) ; static void DelFullRow(int f_row) ; /******************************************************************************* * Function Name : PlayGame * Description : 此程序的主要設計邏輯 * Be called : main * Input : None * Output : None * Return : None *******************************************************************************/ void PlayGame(void) { int userHitChar ; //用戶敲擊鍵盤的字符 int currentRockIndex ; //當前方塊在rockArray數組中下標 int nextRockIndex ; //准備的下個方塊的下標 BOOL moveAbled = FALSE ;//記錄方塊能否落下 DWORD oldtime = 0; extern int g_grade ; //當前方塊位置 RockLocation_t currentRockLocation ; //初始方塊位置(由當中開始下落) RockLocation_t initRockLocation = {(GUI_xWALL_SQUARE_NUM/2-4)*GUI_WALL_SQUARE_WIDTH, GUI_WALL_SQUARE_WIDTH}; //預覽區位置 extern RockLocation_t previewLocation ; //為第一次下落,初始化參數 //隨機選擇當前的俄羅斯方塊形狀 和下一個俄羅斯方塊形狀 srand(time(NULL)) ; currentRockIndex = rand()%g_rockTypeNum ; nextRockIndex = rand()%g_rockTypeNum ; currentRockLocation.left = initRockLocation.left ; currentRockLocation.top = initRockLocation.top ; while(1) { DrawRock(currentRockIndex, ¤tRockLocation, TRUE) ; FlushBatchDraw(); //用批繪圖功能,可以消除閃爍 //判斷能否下落 moveAbled = MoveAble(currentRockIndex, ¤tRockLocation, DIRECT_DOWN) ; //如果不能下落則生成新的方塊 if (!moveAbled) { //設置占位符(此時方塊已落定) SetOccupyFlag(currentRockIndex, ¤tRockLocation) ; //擦除預覽 DrawRock( nextRockIndex, &previewLocation, FALSE) ; //生成新的方塊 currentRockIndex = nextRockIndex ; nextRockIndex = rand()%g_rockTypeNum ; currentRockLocation.left = initRockLocation.left ; currentRockLocation.top = initRockLocation.top ; } //顯示預覽 DrawRock(nextRockIndex, &previewLocation, TRUE) ; //如果超時(且能下落),自動下落一格 // 這個超時時間400-80*g_grade 是本人根據實驗自己得出的 // 一個速度比較適中的一個公式(g_grade不會大於等於5) DWORD newtime = GetTickCount(); if (newtime - oldtime >= (unsigned int)(400-80*g_grade) && moveAbled == TRUE) { oldtime = newtime ; DrawRock(currentRockIndex, ¤tRockLocation, FALSE) ; //擦除原先位置 currentRockLocation.top += ROCK_SQUARE_WIDTH ; //下落一格 } //根據當前游戲板的狀況判斷是否滿行,並進行滿行處理 ProcessFullRow() ; //判斷是否游戲結束 if (isGameOver()) { MessageBox( NULL,游戲結束, GAME OVER, MB_OK ) ; exit(0) ; } //測試鍵盤是否被敲擊 if (kbhit()) { userHitChar = getch() ; ProccessUserHit(userHitChar, ¤tRockIndex, ¤tRockLocation) ; } Sleep(20) ; //降低CPU使用率 }//結束外層while(1) } /******************************************************************************* * Function Name : ProccessUserHit * Description : 處理用戶敲擊鍵盤 * Be called : PlayGame() * Input : userHitChar 用戶敲擊鍵盤的ASCII碼 rockIndexPtr 當前俄羅斯方塊在rockArray中的下標 rockLocationPtr 當前方塊在游戲界面中的位置 * Output : rockIndexPtr 響應用戶敲擊後 新方塊的下標 rockLocationPtr 響應用戶敲擊後 新方塊的位置 * Return : None *******************************************************************************/ void ProccessUserHit(int userHitChar, int* rockIndexPtr, struct LOCATE* rockLocationPtr) { switch (userHitChar) { case 'w' : case 'W' : //“上”鍵 //檢查是否能改變方塊形狀 if (MoveAble(rockArray[*rockIndexPtr].nextRockIndex, rockLocationPtr, DIRECT_UP)) { DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; *rockIndexPtr = rockArray[*rockIndexPtr].nextRockIndex ; } break ; case 's' : case 'S' : //“下”鍵 DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; //擦除原先位置 rockLocationPtr->top += ROCK_SQUARE_WIDTH ; break ; case 'a' : case 'A' : //“左”鍵 if (MoveAble(*rockIndexPtr, rockLocationPtr, DIRECT_LEFT)) { DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; rockLocationPtr->left -= ROCK_SQUARE_WIDTH ; } break ; case 'd' : case 'D' : //“右”鍵 if (MoveAble(*rockIndexPtr, rockLocationPtr, DIRECT_RIGHT)) { DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; rockLocationPtr->left += ROCK_SQUARE_WIDTH ; } break ; case ' ' : //空格(快速下落) DrawRock(*rockIndexPtr, rockLocationPtr, FALSE) ; FastFall(*rockIndexPtr, rockLocationPtr, rockLocationPtr) ; break ; case 13 : //回車鍵(暫停) while(1) { userHitChar = getch() ; if (userHitChar==13) break ; } break ; default : break ; } } /******************************************************************************* * Function Name : MoveAble * Description : 判斷編號為rockIndex 在位置currentLocatePtr的方塊 能否向direction移動 * Be called : * Input : None * Output : None * Return : TRUE 可以移動 FALSE 不可以移動 *******************************************************************************/ BOOL MoveAble(int rockIndex, const struct LOCATE* currentLocatePtr, int f_direction) { int i ; int mask ; int rockX ; int rockY ; rockX = currentLocatePtr->left ; rockY = currentLocatePtr->top ; mask = (unsigned int)1 << 15 ; for (i=1; i<=16; i++) { //與掩碼相與為1的 即為方塊上的點 if ((rockArray[rockIndex].rockShapeBits & mask) != 0) { //判斷能否移動(即掃描即將移動的位置 是否與設置的圍牆有重疊) //若是向上(即翻滾變形) if( f_direction == DIRECT_UP ) { //因為此情況下傳入的是下一個方塊的形狀,故我們直接判斷此方塊的位置是否已經被占 if (g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] [(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] == 1) return FALSE ; } //如果是向下方向移動 else if( f_direction == DIRECT_DOWN ) { if (g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+2] [(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] ==1) return FALSE ; } else //如果是左右方向移動 { //f_direction的DIRECT_LEFT為-1,DIRECT_RIGHT為1,故直接加f_direction即可判斷。 if (g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] [(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1+f_direction] ==1) return FALSE ; } } //每4次 換行 轉到下一行繼續 i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left) : rockX += ROCK_SQUARE_WIDTH ; mask >>= 1 ; } return TRUE ; } /******************************************************************************* * Function Name : SetOccupyFlag * Description : 更新游戲板狀態(把一些位置設置為已占用) * Be called : * Input : rockIndex 方塊的下標(定位了方塊的形狀) currentLocatePtr 方塊的位置(用來設定已占用標識) * Output : None * Return : None *******************************************************************************/ void SetOccupyFlag(int rockIndex, const struct LOCATE * currentLocatePtr) { int i ; int mask ; int rockX ; int rockY ; rockX = currentLocatePtr->left ; rockY = currentLocatePtr->top ; mask = (unsigned int)1 << 15 ; for (i=1; i<=16; i++) { //與掩碼相與為1的 即為方塊上的點 if ((rockArray[rockIndex].rockShapeBits & mask) != 0) { g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] [(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] = 1 ; } //每4次 換行 轉到下一行繼續畫 i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left) : rockX += ROCK_SQUARE_WIDTH ; mask >>= 1 ; } } /******************************************************************************* * Function Name : ProcessFullRow * Description : 檢查是否有滿行,若有,則刪除滿行(並更新得分信息) * Be called : * Input : g_gameBoard * Output : None * Return : None *******************************************************************************/ void ProcessFullRow(void) { int i = 1 ; int cnt = 0 ; BOOL rowFulled = TRUE ; int rowIdx = Y_ROCK_SQUARE_NUM ; //從最後一行開始往上檢查 while (cnt != X_ROCK_SQUARE_NUM) //直到遇到是空行的為止 { rowFulled = TRUE ; cnt = 0 ; //判斷是否有滿行 並消除滿行 for (i = 1; i <= X_ROCK_SQUARE_NUM; i++) { if( g_gameBoard[rowIdx][i] == 0 ) { rowFulled = FALSE ; cnt++ ; } } if (rowFulled) //有滿行 (並更新得分信息) { DelFullRow(rowIdx) ; //更新得分信息 UpdataScore() ; rowIdx++ ; } rowIdx-- ; } } /******************************************************************************* * Function Name : DelFullRow * Description : 刪除游戲板的第rowIdx行 * Be called : * Input : g_gameBoard rowIdx 要刪除的行 在g_gameBoard中的下標 * Output : None * Return : None *******************************************************************************/ void DelFullRow(int rowIdx) { int cnt = 0 ; int i ; //把此行擦除 setcolor(BLACK) ; for (i=1; i<=X_ROCK_SQUARE_NUM; i++) { rectangle(GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-2) ; } //把此行之上的游戲板方塊全向下移動一個單位 while (cnt != X_ROCK_SQUARE_NUM) //直到遇到是空行的為止 { cnt =0 ; for (i=1; i<=X_ROCK_SQUARE_NUM; i++) { g_gameBoard[rowIdx][i] = g_gameBoard[rowIdx-1][i] ; //擦除上面的一行 setcolor(BLACK) ; rectangle( GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*(rowIdx-1)-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*(rowIdx-1)-2 ) ; //顯示下面的一行 if (g_gameBoard[rowIdx][i] ==1) { setcolor(WHITE) ; rectangle( GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-ROCK_SQUARE_WIDTH+2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*i-2, GUI_WALL_SQUARE_WIDTH+ROCK_SQUARE_WIDTH*rowIdx-2 ) ; } if (g_gameBoard[rowIdx][i] == 0) cnt++ ; //統計一行是不是 都是空格 }//for rowIdx-- ; } } /******************************************************************************* * Function Name : FastFall * Description : 讓編號為rockIndex 且初始位置在currentLocatePtr的方塊 快速下落到底部 * Be called : * Input : rockIndex currentLocatePtr * Output : endLocatePtr 下落後方塊的位置 * Return : None *******************************************************************************/ void FastFall (int rockIndex, struct LOCATE * currentLocatePtr, struct LOCATE * endLocatePtr) { int i ; int mask ; //掩碼,用於判斷方塊的形狀 int rockX ; //方塊的坐標(4*4方格的左上角點的x軸坐標) int rockY ; //方塊的坐標(4*4方格的左上角點的y軸坐標) while (currentLocatePtr->top <= GUI_WALL_SQUARE_WIDTH+Y_ROCK_SQUARE_NUM*ROCK_SQUARE_WIDTH) { rockX = currentLocatePtr->left ; rockY = currentLocatePtr->top ; mask = (unsigned int)1 << 15 ; for (i=1; i<=16; i++) { //與掩碼相與為1的 即為方塊上的點 if ((rockArray[rockIndex].rockShapeBits & mask) != 0) { if(g_gameBoard[(rockY-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] [(rockX-GUI_WALL_SQUARE_WIDTH)/ROCK_SQUARE_WIDTH+1] == 1) //遇到底部 { endLocatePtr->top = currentLocatePtr->top-ROCK_SQUARE_WIDTH ; return ; } } //每4次 換行 轉到下一行繼續畫 i%4 == 0 ? (rockY += ROCK_SQUARE_WIDTH, rockX = currentLocatePtr->left) : rockX += ROCK_SQUARE_WIDTH ; mask >>= 1 ; } currentLocatePtr->top += ROCK_SQUARE_WIDTH ; }//while() } /******************************************************************************* * Function Name : isGameOver * Description : 判斷是否游戲結束 * Be called : * Input : None * Output : None * Return : TRUE 游戲結束 FALSE 游戲繼續 *******************************************************************************/ BOOL isGameOver() { int i ; BOOL topLineHaveRock = FALSE ; //在界面的最高行有方塊的標記 BOOL bottomLineHaveRock = FALSE ; //在界面的最低行有方塊的標記 for (i=1; i<=X_ROCK_SQUARE_NUM; i++) { if( g_gameBoard[1][i] == 1 ) topLineHaveRock = TRUE ; if( g_gameBoard[Y_ROCK_SQUARE_NUM][i] == 1 ) bottomLineHaveRock = TRUE ; } //若底層行和頂層行都有方塊 則說明在所有行都有方塊,游戲結束 if (topLineHaveRock && bottomLineHaveRock) return TRUE ; else return FALSE ; }
@### @### @@## #### @@@# @### #### #### @@## #@## #@## #### ##@# @@@# #### #### ----- #@## #@## @@## #### @### @@@# #### #### @@## @### @### #### @@@# ##@# #### #### ----- @### @@## #@## #### #@@# @@## #### #### ----- #@## @@## @### #### @@## #@@# #### #### ----- #@## @@@# #### #### @### @@## @### #### @@@# #@## #### #### #@## @@## #@## #### ----- #@## #@## #@## #@## @@@@ #### #### #### ----- #### @@## @@## #### -----