源碼下載地址:http://download.csdn.net/detail/lt_lover/9721862
最近想寫一個俄羅斯方塊,正好電腦裏面有個以前下的代碼,於是就看了看思路,然後自己加了一些東西,要是忘了就不好了
先做7個不同類型的方塊,分別爲 長條形、方形、L形、反L形、Z形、反Z形、土字形。用一個二維數組保存每個形狀,每個形狀使用4個點,每個點代表每種形狀的一個小方格,比如:{ 0, 0, 0, 1, 0, 2, 0, 3, FOREGROUND_RED | FOREGROUND_INTENSITY } 就是點(0,0)、(0,1)、(0,2)、(0,3) 4個點,最後一個參數是顏色,這個是紅色高亮,如圖:
然後用一個數組保存所有圖形的高度,消除的時候需要用到高度,上面長條的高度就是1。
下面是代碼,定義的時候每個形狀的初始狀態標號分別爲0,1,2,3,4,5,6,變換的形狀爲7--18,先是頭文件,Tetris.h:
- #ifndef TETRIS_H_
- #define TETRIS_H_
- #include <windows.h>
- //長條形
- const int A1 = 0;
- const int A2 = 7;
- //方塊
- const int B = 1;
- //L 形狀
- const int C11 = 2;
- const int C12 = 8;
- const int C13 = 9;
- const int C14 = 10;
- //L 的另一個形狀
- const int C21 = 3;
- const int C22 = 11;
- const int C23 = 12;
- const int C24 = 13;
- //Z 形狀
- const int D11 = 4;
- const int D12 = 14;
- //Z 的另一個形狀
- const int D21 = 5;
- const int D22 = 15;
- //土字形
- const int E31 = 6;
- const int E32 = 16;
- const int E33 = 17;
- const int E34 = 18;
- class tetris
- {
- private:
- int map[12][23]; //背景
- int top; //當前的最高點
- int score; //分數
- int level; //難度等級
- int ID; //當前的方塊的形狀
- int hotPoint[2]; //熱點,當前活動的所在點
- public:
- tetris()
- {
- for (int i = 0; i < 12; i++)<span style="white-space:pre"> </span>//初始化地圖
- for (int j = 0; j < 23; j++)
- map[i][j] = 0;
- top = 99;
- score = 0;
- level = 1;
- ID = 0;
- hotPoint[0] = 5; //下落起始點的橫座標
- hotPoint[1] = 0; //下落起始點的縱座標
- }
- void DrawMap(); <span style="white-space:pre"> </span>//繪製地圖
- void initInterface(); //初始化界面
- void DrawBox(int x, int y, int id); //繪製圖形
- void ReBox(int x, int y, int id); //擦除圖形
- int IsJudge(int x, int y, int id); //是否可以繪製圖形
- int TurnBlock(int id); //旋轉方塊
- void UpdateMap(int id); //更新畫面
- void RunGame(); //運行
- };
- #endif
- int sharp[19][9] = //每個一維數組內有8個點,每兩個點是一個 形狀的一個小方格,在4*4的表格中
- {
- { 0, 0, 0, 1, 0, 2, 0, 3, FOREGROUND_RED | FOREGROUND_INTENSITY }, //長條形
- { 0, 0, 1, 0, 0, 1, 1, 1, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY }, //方形
- { 0, 0, 0, 1, 1, 1, 2, 1, FOREGROUND_GREEN | FOREGROUND_RED }, //L形
- { 0, 1, 1, 1, 2, 1, 2, 0, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY }, //反L形
- { 0, 0, 1, 0, 1, 1, 2, 1, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY }, //Z形
- { 1, 0, 2, 0, 0, 1, 1, 1, FOREGROUND_GREEN | FOREGROUND_INTENSITY }, //反Z形
- { 0, 0, 0, 1, 0, 2, 1, 1, FOREGROUND_BLUE | FOREGROUND_INTENSITY }, //土形
- //下面是上面形狀的變換
- { 0, 0, 1, 0, 2, 0, 3, 0, FOREGROUND_RED | FOREGROUND_INTENSITY },
- { 1, 0, 1, 1, 1, 2, 0, 2, FOREGROUND_GREEN | FOREGROUND_RED },
- { 0, 0, 1, 0, 2, 0, 2, 1, FOREGROUND_GREEN | FOREGROUND_RED },
- { 0, 0, 1, 0, 0, 1, 0, 2, FOREGROUND_GREEN | FOREGROUND_RED },
- { 0, 0, 1, 0, 1, 1, 1, 2, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },
- { 0, 0, 1, 0, 2, 0, 0, 1, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },
- { 0, 0, 0, 1, 0, 2, 1, 2, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },
- { 1, 0, 0, 1, 1, 1, 0, 2, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY },
- { 0, 0, 0, 1, 1, 1, 1, 2, FOREGROUND_GREEN | FOREGROUND_INTENSITY },
- { 0, 0, 1, 0, 2, 0, 1, 1, FOREGROUND_BLUE | FOREGROUND_INTENSITY },
- { 0, 1, 1, 0, 1, 1, 1, 2, FOREGROUND_BLUE | FOREGROUND_INTENSITY },
- { 1, 0, 0, 1, 1, 1, 2, 1, FOREGROUND_BLUE | FOREGROUND_INTENSITY }
- };
- int high[19] = { 4, 2, 2, 2, 2, 2, 3, 1, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 2 }; //數組是用來保存上面每個一維數組的各個形狀高度的
- void setCurPos(int i, int j, int color = 1 | 2 | 4)
- { <span style="white-space:pre"> </span>//color相當於自己選擇顏色,沒有就用默認的白色
- HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); //獲得標準輸出句柄
- SetConsoleTextAttribute(out, color);<span style="white-space:pre"> </span>//設置顏色
- COORD pos = { i * 2, j };
- SetConsoleCursorPosition(out, pos);<span style="white-space:pre"> </span>//設置位置
- }
- void tetris::DrawMap()
- {
- //地圖框架
- for (int i = 0; i < 14; i++) // 0 - 13
- {
- setCurPos(i, 0);
- cout << "■";
- }
- for (int i = 0; i < 25; i++) // 0 - 24
- {
- setCurPos(0, i);
- cout << "■";
- setCurPos(13, i);
- cout << "■";
- }
- for (int i = 0; i < 14; i++)
- {
- setCurPos(i, 24);
- cout << "■";
- }
- //信息框架
- for (int i = 15; i <= 25; i++)
- {
- setCurPos(i, 0);
- cout << "■";
- setCurPos(i, 8);
- cout << "■";
- }
- for (int i = 0; i <= 8; i++)
- {
- setCurPos(15, i);
- cout << "■";
- setCurPos(25, i);
- cout << "■";
- }
- setCurPos(16, 12);
- cout << "俄羅斯方塊(6D)";
- setCurPos(16, 15);
- cout << " 分數: " << score;
- setCurPos(16, 16);
- cout << " 等級: " << level;
- }
- void tetris::DrawBox(int x, int y, int id)<span style="white-space:pre"> </span>//畫方塊
- {
- int nx = 0, ny = 0;
- int color = sharp[id][8];
- for (int i = 0; i < 4; i++)
- {
- nx = x + sharp[id][i * 2];
- ny = y + sharp[id][i * 2 + 1];
- setCurPos(nx + 1, ny + 1, color);<span style="white-space:pre"> </span><span style="font-family: Arial, Helvetica, sans-serif;">//玩的地圖比實際的地圖橫縱座標都大1(因爲有一個外圍)</span><span style="white-space:pre">
- </span> cout << "■";
- }
- }
- void tetris::ReBox(int x, int y, int id)<span style="white-space:pre"> </span>//消除方塊
- {
- int nx = 0, ny = 0;
- for (int i = 0; i < 4; i++)
- {
- nx = x + sharp[id][i * 2];
- ny = y + sharp[id][i * 2 + 1];
- setCurPos(nx + 1, ny + 1);<span style="white-space:pre"> </span>
- cout << " ";
- }
- }
- int tetris::IsJudge(int x, int y, int id)
- {
- int nx = 0, ny = 0;
- for (int i = 0; i < 4; i++)
- {
- nx = x + sharp[id][i * 2];
- ny = y + sharp[id][i * 2 + 1];
- if (nx < 0 || nx >= 12 || ny < 0 || ny >= 23 || map[nx][ny] != 0) //不能放了,返回0
- return 0;
- }
- return 1;
- }
- int tetris::TurnBlock(int id)
- {
- switch (id)
- {
- case A1: id = A2; break;
- case A2: id = A1; break;
- case B: id = B; break;
- case C11:id = C12; break;
- case C12:id = C13; break;
- case C13:id = C14; break;
- case C14:id = C11; break;
- case C21:id = C22; break;
- case C22:id = C23; break;
- case C23:id = C24; break;
- case C24:id = C21; break;
- case D11:id = D12; break;
- case D12:id = D11; break;
- case D21:id = D22; break;
- case D22:id = D21; break;
- case E31:id = E32; break;
- case E32:id = E33; break;
- case E33:id = E34; break;
- case E34:id = E31; break;
- }
- return id;
- }
- void tetris::UpdateMap(int id)
- {
- int nx = 0, ny = 0;
- int flag;
- int clear = 0; //清除了多少個行,最後積分
- for (int i = 0; i < 4; i++)
- {
- nx = hotPoint[0] + sharp[id][i * 2];
- ny = hotPoint[1] + sharp[id][i * 2 + 1];
- map[nx][ny] = sharp[id][8]; //保存顏色值,因爲顏色值不爲0,所以可以和沒有方格區分開
- }
- if (hotPoint[1] < top)<span style="white-space:pre"> </span>//因爲地圖的最上面是0,最底層是22,所以當前熱點的y座標如果小於top,就是最高點變化了,更新一下top
- top = hotPoint[1];
- for (int j = hotPoint[1]; j < hotPoint[1] + high[id]; j++) //從上向下進行消除,從下向上容易少消行
- {
- flag = 0;
- for (int i = 0; i < 12; i++)
- {
- if (map[i][j] == 0) <span style="white-space:pre"> </span>//沒有可以消除的
- {
- flag = 1;
- break;
- }
- }
- if (flag == 0) //可以消除當前行
- {
- for (int k = j; k >= top; k--)<span style="white-space:pre"> </span>//將每一行的上一行下移,直到最高點所在行下移完畢
- {
- if (k == 0) //消除 到了最頂行
- {
- for (int i = 0; i < 12; i++)
- {
- map[i][k] = 0;
- setCurPos(i + 1, k + 1);
- cout << " ";
- }
- }
- else
- {
- for (int i = 0; i < 12; i++)
- {
- map[i][k] = map[i][k - 1];
- setCurPos(i + 1, k + 1); //因爲有兩條圖形框邊,遊戲運行過程中的座標系相對於 真正的座標系是x、y都加 1 的
- if (map[i][k] == 0) //被刪除行的 上一行是空的,所以這一行也是空的
- cout << " ";
- else //上一行不是空的
- {
- int tempColor = map[i][k];
- setCurPos(i + 1, k + 1, tempColor);
- cout << "■";
- }
- }
- }
- }
- top++; <span style="white-space:pre"> </span>//消除成功,最高點下降一個
- clear++;
- score += clear * 100;
- }
- }
- setCurPos(16, 15);
- cout << " 分數: " << score;
- }
- void tetris::RunGame()
- {
- initInterface();
- system("cls");
- DrawMap();
- char x = ' '; //讀取鍵盤信息
- int i = 0; <span style="white-space:pre"> </span> //計時,到時間沒有獲得指令,自動下降
- int Count = 0;
- int nextId = 0;
- int curId = 0;
- srand(time(0));
- curId = rand() % 7;
- nextId = rand() % 7;
- DrawBox(hotPoint[0], hotPoint[1], curId); //畫當前圖形
- DrawBox(17, 3, nextId); //畫出下一個要出現的圖形
- Count = 10000 - 1000 * level;
- while (1)
- {
- if (i >= Count) //可以自動下移了
- {
- i = 0; //將 i 清零,下次繼續計數
- if (IsJudge(hotPoint[0], hotPoint[1] + 1, curId) == 0) <span style="white-space:pre"> </span>//下個位置無效,到底了
- {
- UpdateMap(curId); //更新一下畫面
- ReBox(17, 3, nextId); <span style="white-space:pre"> </span> //清除原來的下一個圖形
- curId = nextId;
- nextId = rand() % 7;
- hotPoint[0] = 5; //更新熱點
- hotPoint[1] = 0;
- DrawBox(hotPoint[0], hotPoint[1], curId);
- DrawBox(17, 3, nextId); <span style="white-space:pre"> </span>//畫上現在的下一個圖形
- if (IsJudge(hotPoint[0], hotPoint[1], curId) == 0) //無法繪製當前圖形
- {
- system("cls");
- cout << "遊戲結束!!!最終得分爲:" << score << endl;
- system("pause");
- exit(0);
- }
- }
- else
- {
- ReBox(hotPoint[0], hotPoint[1], curId);
- hotPoint[1]++;
- DrawBox(hotPoint[0], hotPoint[1], curId);
- }
- }
- if (_kbhit()) //讀取鍵盤信息
- {
- x = _getch();
- if (x == 'a' || x == 'A') //左移
- {
- if (IsJudge(hotPoint[0] - 1, hotPoint[1], curId))
- {
- ReBox(hotPoint[0], hotPoint[1], curId);
- hotPoint[0]--;
- DrawBox(hotPoint[0], hotPoint[1], curId);
- }
- }
- else if (x == 'd' || x == 'D') <span style="white-space:pre"> </span>//右移
- {<span style="white-space:pre"> </span>
- if (IsJudge(hotPoint[0] + 1, hotPoint[1], curId))
- {
- ReBox(hotPoint[0], hotPoint[1], curId);
- hotPoint[0]++;
- DrawBox(hotPoint[0], hotPoint[1], curId);
- }
- }
- else if (x == 's' || x == 'S') <span style="white-space:pre"> </span>//向下加速
- {
- if (IsJudge(hotPoint[0], hotPoint[1] + 1, curId))
- {
- ReBox(hotPoint[0], hotPoint[1], curId);
- hotPoint[1]++;
- DrawBox(hotPoint[0], hotPoint[1], curId);
- }
- }
- else if (x == 'w' || x == 'W')<span style="white-space:pre"> </span>//變形
- {
- int temp = curId;
- curId = TurnBlock(curId);
- if (IsJudge(hotPoint[0], hotPoint[1], curId))
- {
- ReBox(hotPoint[0], hotPoint[1], temp);
- DrawBox(hotPoint[0], hotPoint[1], curId);
- }
- else
- curId = temp;
- }
- else if (x == ' ') //暫停
- {
- _getch();
- }
- while (_kbhit()) //讀取掉剩下的鍵盤信息s
- _getch();
- }
- i++;
- }
- }
- #include "Tetris.h"
- int main()
- {
- tetris ter;
- ter.RunGame();
- return 0;
- }