EasyX实现俄罗斯方块游戏
生活随笔
收集整理的這篇文章主要介紹了
EasyX实现俄罗斯方块游戏
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1 啟動頁面
- 1.1 啟動頁面分析
- 1.2 啟動界面代碼實現
- 2 初始化游戲環境
- 2.1 界面效果及分析
- 2.2 代碼實現
- 3 新方塊
- 3.1 顯示效果
- 3.2 分析
- 3.3 代碼實現
- 4 降落方塊
- 4.1 使用訪問數組確定是否有方塊
- 4.2 設計游戲循環
- 5 全部代碼實現
1 啟動頁面
1.1 啟動頁面分析
啟動頁面:
啟動頁面分析:
啟動界面的大小為:550 X 660(像素)。
1.2 啟動界面代碼實現
# include <stdio.h> # include <graphics.h> void welcome(void) {initgraph(550, 660);// 設置窗口標題HWND hwnd = GetHWnd();SetWindowText(hwnd, "俄羅斯方塊");//Sleep(2000);// 游戲標題setfont(40, 0, "微軟雅黑");setcolor(WHITE);outtextxy(205, 200, "俄羅斯方塊!");// 游戲副標題setfont(22, 0, "楷體");outtextxy(175, 300, "編程,從俄羅斯方塊開始!");Sleep(3000); }int main() {welcome();closegraph();return 0; }2 初始化游戲環境
2.1 界面效果及分析
效果:
分析:
2.2 代碼實現
int score = 0; // 總分 int rank = 0; //等級void initGameScene() {char str[16];cleardevice();setcolor(WHITE);rectangle(29, 29, 334, 633);rectangle(27, 27, 336, 635);rectangle(370, 50, 515, 195);setfont(24, 0, "楷體");setcolor(LIGHTGRAY);outtextxy(405, 215, "下一個:");setcolor(RED);outtextxy(405, 280, "分數:");sprintf(str, "%d", score);outtextxy(415, 310, str);outtextxy(405, 375, "等級:");sprintf(str, "%d", rank);outtextxy(425, 405, str);setfont(22, 0, "楷體");setcolor(LIGHTBLUE);outtextxy(390, 475, "操作說明:");outtextxy(390, 500, "↑: 旋轉");outtextxy(390, 525, "↓: 下降");outtextxy(390, 550, "←: 左移");outtextxy(390, 575, "→: 右移");outtextxy(390, 600, "空格: 暫停"); }int main() {welcome();initGameScene();system("pause");closegraph();return 0; }3 新方塊
3.1 顯示效果
3.2 分析
以L型方塊為例:
每個方塊有4種形態:4個方向,所以使用4個二維數組來表示1種方塊。
3.3 代碼實現
#define BLOCK_COUNT 5 #define BLOCK_WIDTH 5 #define BLOCK_HEIGHT 5 #define UNIT_SIZE 20 //小磚塊的寬度和高度int color[BLOCK_COUNT] = {GREEN,CYAN,MAGENTA,BROWN,YELLOW };int NextIndex = -1;int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH] = {// | 形方塊{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },// L 形方塊{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },// 田 形方塊{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },// T 形方塊{ 0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },// Z 形方塊{ 0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 }, };void clearBlock(int x, int y) {setcolor(BLACK);setfont(23, 0, "楷體");for (int i = 0; i<BLOCK_HEIGHT; i++)for (int j = 0; j<BLOCK_WIDTH; j++)outtextxy(x + UNIT_SIZE*j, y + UNIT_SIZE*i, "■"); }void drawBlock(int x, int y, int index) {setfont(23, 0, "楷體");setcolor(color[index]);for (int i = 0; i<5; i++)for (int j = 0; j<5; j++)if (block[4 * index][i][j] == 1)outtextxy(x + 20 * j, y + 20 * i, "■"); }void nextblock() {int x = 391, y = 71;//在右側的提示區清除原來的方塊clearBlock(x, y);// 在右側的提示區繪制新方塊// 1. 產生新的方塊srand(time(NULL));NextIndex = rand() % BLOCK_COUNT;// 2. 繪制drawBlock(x, y, NextIndex); }int main() {welcome();initGameScene();nextblock();system("pause");closegraph();return 0; }4 降落方塊
4.1 使用訪問數組確定是否有方塊
int visit[30][15], Color[30][15]; // visit[i][j] == 1 表示該位置有方塊int main() {welcome();initGameScene();nextblock();// 清空訪問數組Sleep(500);memset(visit, 0, sizeof(visit));system("pause");closegraph();return 0; }4.2 設計游戲循環
int BlockIndex = -1; //當前方塊的序號void newblock() { //新方塊下降}int main() {welcome();initGameScene();nextblock();// 清空訪問數組Sleep(500);memset(visit, 0, sizeof(visit));// 最開始時, 第一個方塊,就是下一個方塊BlockIndex = NextIndex;while (1){newblock();}system("pause");closegraph();return 0; }5 全部代碼實現
#include <stdio.h> #include <graphics.h> #include <time.h> #include <conio.h> //kbhit()使用int score = 0; //總分 int rank = 0; //等級#define BLOCK_COUNT 5 #define BLOCK_WIDTH 5 #define BLOCK_HEIGHT 5 #define UNIT_SIZE 20#define START_X 130 #define START_Y 30#define KEY_UP 72 #define KEY_RIGHT 77 #define KEY_DOWN 80 #define KEY_LEFT 75 #define KEY_SPACE 32int speed = 500; int minX = 30; int minY = 30;typedef enum {BLOCK_UP,BLOCK_RIGHT,BLOCK_DOWN,BLOCK_LEFT } block_dir_t;typedef enum {MOVE_DOWN,MOVE_LEFT,MOVE_RIGHT } move_dir_t;int NextIndex = -1; //下一個方塊的種類 int BlockIndex = -1; //當前方塊的種類int color[BLOCK_COUNT] = {GREEN, CYAN, MAGENTA, BROWN, YELLOW };int visit[30][15]; //訪問數組 int markColor[30][15]; //表示對應位置的顏色int block[BLOCK_COUNT*4][BLOCK_HEIGHT][BLOCK_WIDTH] = {// | 型方塊{0, 0, 0, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 1, 0, 0,0, 0, 0, 0, 0 },{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },// L 形方塊{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },// 田 形方塊{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },// T 形方塊{ 0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },// Z 形方塊{ 0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0 },{ 0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 } };// 歡迎界面 void welcome(void) {// 初始化畫布initgraph(550, 660);// 設置窗口標題HWND window = GetHWnd(); //獲取窗口SetWindowText(window, _T("俄羅斯方塊 奇牛學院 Rock")); //設置窗口標題// 設置文本的字體樣式setfont(40, 0, _T("微軟雅黑"));setcolor(WHITE);outtextxy(205, 200, _T("俄羅斯方塊"));setfont(22, 0, _T("楷體"));outtextxy(175, 300, _T("編程, 從俄羅斯方塊開始!"));Sleep(3000); //睡眠(暫停)3000毫秒,3秒針 }// 初始化游戲場景 void initGameScene(void) {char str[16];//清除屏幕cleardevice();rectangle(27, 27, 336, 635);rectangle(29, 29, 334, 633);rectangle(370, 50, 515, 195);setfont(24, 0, _T("楷體"));setcolor(LIGHTGRAY);outtextxy(405, 215, _T("下一個"));setcolor(RED);outtextxy(405, 280, _T("分數"));sprintf(str, "%d", score); outtextxy(415, 310, str);outtextxy(405, 375, _T("等級"));sprintf(str, "%d", rank); outtextxy(425, 405, str);// 操作說明 ↑ ↓ ← →setcolor(LIGHTBLUE);outtextxy(390, 475, "操作說明");outtextxy(390, 500, "↑:旋轉");outtextxy(390, 525, "↓: 下降");outtextxy(390, 550, "←: 左移");outtextxy(390, 575, "→: 右移");outtextxy(390, 600, "空格:暫停"); }void clearBlock(void) {setcolor(BLACK);setfont(23, 0, "楷體");for (int i=0; i<BLOCK_HEIGHT; i++) {for (int j=0; j<BLOCK_WIDTH; j++) {//"■"int x = 391 + j * UNIT_SIZE;int y = 71 + i * UNIT_SIZE;outtextxy(x, y, "■");}} }// 繪制方塊 void drawBlock(int x, int y) {setcolor(color[NextIndex]);setfont(23, 0, "楷體");for (int i=0; i<BLOCK_HEIGHT; i++) {for (int j=0; j<BLOCK_WIDTH; j++) {//"■"if (block[NextIndex*4][i][j] == 1) {int x2 = x + j * UNIT_SIZE;int y2 = y + i * UNIT_SIZE;outtextxy(x2, y2, "■");}}} }// 繪制方塊: 在指定位置繪制指定方塊的指定方向 void drawBlock(int x, int y, int blockIndex, block_dir_t dir) {setcolor(color[blockIndex]);setfont(23, 0, "楷體");int id = blockIndex * 4 + dir;for (int i=0; i<BLOCK_HEIGHT; i++) {for (int j=0; j<BLOCK_WIDTH; j++) {//"■"if (block[id][i][j] == 1) {int x2 = x + j * UNIT_SIZE;int y2 = y + i * UNIT_SIZE;outtextxy(x2, y2, "■");}}} }// 清除指定位置指定方向的方塊 // 參數x: 方塊的左上角的x坐標 // 參數y: 方塊的左上角在游戲區域內的坐標,距離游戲區域頂部的距離 void clearBlock(int x, int y, block_dir_t dir) {setcolor(BLACK);int id = BlockIndex * 4 + dir;y += START_Y;for (int i=0; i<5; i++) {for (int j=0; j<5; j++) {if (block[id][i][j] == 1) {// 擦除該方塊的第i行的第j列outtextxy(x+20*j, y+i*20, "■");}}} }void nextblock(void) {clearBlock(); // 清除右上角區域// 隨機選擇一種方塊srand(time(NULL)); //使用時間函數的返回值,來作為隨機種子NextIndex = rand() % BLOCK_COUNT;drawBlock(391, 71); }// 如果在指定位置可以向指定方向移動,就返回1, 否則就返回0 int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {// 計算當前方塊的左上角在30x15的游戲區中的位置(第多少行,第多少列)int x = (y0 - minY) / UNIT_SIZE;int y = (x0 - minX) / UNIT_SIZE;int id = BlockIndex * 4 + blockDir;int ret = 1;if (moveDir == MOVE_DOWN) {for (int i=0; i<5; i++) {for (int j=0; j<5; j++) {if (block[id][i][j] == 1 &&(x + i + 1 >= 30 || visit[x+i+1][y+j] == 1)) {ret = 0;}}}} else if (moveDir == MOVE_LEFT) {for (int i=0; i<5; i++) {for (int j=0; j<5; j++) {if (block[id][i][j] == 1 &&(y + j == 0 || visit[x+i][y+j-1]==1)) {ret = 0;}}}} else if (moveDir == MOVE_RIGHT) {for (int i=0; i<5; i++) {for (int j=0; j<5; j++) {if (block[id][i][j] == 1 && (y+j+1>=15 || visit[x+i][y+j+1]==1)) {ret = 0;}}}}return ret; }// 檢測游戲是否結束 void failCheck() {if (!moveable(START_X, START_Y, MOVE_DOWN, BLOCK_UP)) {setcolor(WHITE);setfont(45, 0, "隸體");outtextxy(75, 300, "GAME OVER!");Sleep(1000);system("pause");closegraph();exit(0);} }// 判斷當前方塊是否可以轉向到指定方向 // 注意, 此時還沒有轉到該方向!!! int rotatable(int x, int y, block_dir_t dir) {int id = BlockIndex * 4 + dir;int xIndex = (y - minY) / 20;int yIndex = (x - minX) / 20;if (!moveable(x, y, MOVE_DOWN, dir)) {return 0;}for (int i=0; i<5; i++) {for (int j=0; j<5; j++) {if (block[id][i][j] == 1 &&(yIndex+j<0 || yIndex+j>=15 || visit[xIndex+i][yIndex+j]==1)) {return 0;}}}return 1; }void wait(int interval) { int count = interval / 10;for (int i=0; i<count; i++) {Sleep(10);if (kbhit()) {return;}} }void mark(int x, int y, int blockIndex, block_dir_t dir) {int id = blockIndex * 4 + dir;int x2 = (y - minY) / 20;int y2 = (x - minX) / 20;for (int i=0; i<5; i++) {for (int j=0; j<5; j++) {if (block[id][i][j] == 1) {visit[x2+i][y2+j] = 1;markColor[x2+i][y2+j] = color[blockIndex];}}} }void move(void){int x = START_X;int y = START_Y;int k = 0;block_dir_t blockDir = BLOCK_UP;int curSpeed = speed;// 檢測游戲是否結束failCheck();// 持續向下降落while (1) {if (kbhit()) {int key = getch();if (key == KEY_SPACE) {getch();}}// 清除當前方塊clearBlock(x, k, blockDir);if (kbhit()) {int key = getch();if(key == KEY_UP) {block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);if (rotatable(x, y+k, nextDir)) {blockDir = nextDir;}} else if (key == KEY_DOWN) {curSpeed = 50;} else if (key == KEY_LEFT) {if (moveable(x, y+k+20, MOVE_LEFT, blockDir)) {x -= 20;}} else if (key ==KEY_RIGHT) {if (moveable(x, y+k+20, MOVE_RIGHT, blockDir)) {x += 20; //x = x + 20;}}}k += 20;// 繪制當前方塊drawBlock(x, y+k, BlockIndex, blockDir);wait(curSpeed);//k += 20;// 方塊的“固化”處理if (!moveable(x, y+k, MOVE_DOWN, blockDir)) {mark(x, y+k, BlockIndex, blockDir);break;}} }void newblock() {// 確定即將使用的方塊的類別BlockIndex = NextIndex;// 繪制剛從頂部下降的方塊drawBlock(START_X, START_Y);// 讓新出現的方塊暫停一會,讓用戶識別到Sleep(100); //0.1秒// 在右上角區域,繪制下一個方塊nextblock();// 方塊降落move(); }//消除第x行,并把上面的行都下移 void down(int x){for (int i=x; i>0; i--) {// 消除第i行,第j列的方格消除for (int j=0; j<15; j++) {if (visit[i-1][j]) {visit[i][j] = 1;markColor[i][j] = markColor[i-1][j];setcolor(markColor[i][j]);outtextxy(20*j + minX, 20*i+minY, "■");} else {visit[i][j] = 0;setcolor(BLACK);outtextxy(20*j + minX, 20*i+minY, "■");}}}// 清除最頂上的哪一行(就是行標為0的那一行)setcolor(BLACK);for (int j=0; j<15; j++) {visit[0][j] = 0;outtextxy(20*j + minX, minY, "■");} }// 更新分數,參數lines表示消除的行數 void addScore(int lines) {char str[32];setcolor(RED);score += lines * 10;sprintf(str, "%d", score);outtextxy(415, 310, str); }void updateGrade() {// 更新等級的提示// 假設:50分一級rank = score / 50;char str[16];sprintf(str, "%d", rank);outtextxy(425, 405, str);// 更新速度, 等級越高,速度越快,speed越小!// 最慢:500, 最快是100speed = 500 - rank*100;if (speed <= 100) {speed = 100;} }void check(void) {int i, j;int clearLines = 0;for (i=29; i>=0; i--) {// 檢查第i行有沒有滿for (j=0; j<15 && visit[i][j]; j++) ;//執行到此處時,有兩種情況:// 1. 第i行沒有滿,即表示有空位 此時 j<15// 2. 第i行已滿了,此時 j>=15if (j >= 15) {// 此時,第i行已經滿了,就需要消除第i行down(i); //消除第i行,并把上面的行都下移i++; // 因為最外層的循環中有 i--, 所以我們先i++, 使得下次循環時,再把這一行檢查一下clearLines++;}}// 更新分數addScore(clearLines);// 更新等級(更新等級提示,更新速度)updateGrade(); }int main(void) {welcome();initGameScene();// 產生新方塊nextblock();Sleep(500);// 初始化訪問數組memset(visit, 0, sizeof(visit));while (1) {newblock();// 消除滿行,并更新分數和速度check();}system("pause");closegraph();return 0; }參考資料:
總結
以上是生活随笔為你收集整理的EasyX实现俄罗斯方块游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 选择题蒙题技巧(蒙题技巧方法口诀分享)
- 下一篇: 朗科智能有什么产品 主要从事智能控制器及