#include #include #include #include #include #include #include #include using namespace std; //建立图形的坐标 int Map[24][8] = { {0,0,1,0,2,0,3,0},{0,0,0,1,0,2,0,3},{0,0,1,0,2,0,3,0},{0,0,0,1,0,2,0,3},//l型 {0,0,1,0,0,1,1,1},{0,0,1,0,0,1,1,1},{0,0,1,0,0,1,1,1},{0,0,1,0,0,1,1,1},//正方体 {0,0,1,0,1,1,1,2},{0,1,1,1,2,0,2,1},{0,0,0,1,0,2,1,2},{0,0,0,1,1,0,2,0},//L型 {1,0,1,1,1,2,0,2},{0,0,0,1,1,1,2,1},{0,0,0,1,0,2,1,0},{0,0,1,0,2,0,2,1},//反L型 {0,0,0,1,1,1,1,2},{0,1,1,0,1,1,2,0},{0,0,0,1,1,1,1,2},{0,1,1,0,1,1,2,0},//⚡型 {0,1,0,2,1,0,1,1},{0,0,1,0,1,1,2,1},{0,1,0,2,1,0,1,1},{0,0,1,0,1,1,2,1} //反⚡型 }; int height[24] = { 4,1,4,1,2,2,2,2,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3 };//每个图形的高度 void HideCursor()//隐藏光标 { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_CURSOR_INFO CursorInfo; GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息 CursorInfo.bVisible = false; //隐藏控制台光标 SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态 } void SetPos(int i, int j)//设定光标位置 { COORD pos = { i,j }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); } class Box //游戏的类 { private: int map[30][30];//记录哪些位置有方块 int point = 0;//记录分数 int shape;//记录是哪个图形 int speed = 0;//速度 int top;//当前图形的最高位置 int level;//难度 struct Base//基准点坐标 { int x, y; }base; public: Box()//初始化 { shape = 0, point = 0; top = 9999; level = 0; base.x = 0; base.y = 6; memset(map, 0, sizeof(map)); } void buildmap();//画地图 void menu();//开始菜单 void run();//游戏运行 void rotate();//旋转图形 void draw(int x, int y, int Shape);//绘制图形 void erase(int x, int y, int Shape);//删除图形 int judgeshape();//产生一个形状 bool judge(int x, int y, int shape);//判断是否可以画方格 void Move(char c);//判断键盘输入并处理 void update();//更新地图 void color(int shape);//给方块设定颜色 }; void Box::menu() //开始菜单 { cout << endl << endl << endl; cout << "***********************************" << endl; cout << "****** ******" << endl; cout << "****** #俄罗斯方块# ******" << endl; cout << "****** ******" << endl; cout << "****** 致敬童年,回味无穷 ******" << endl; cout << "****** ******" << endl; cout << "****** 选择难度(1~9): ******" << endl; cout << "****** ******" << endl; cout << "***********************************" << endl << endl; cout << "控制:\nA/a:左移 W/w:变换\nD/d:右移 P/p:暂停\nS/s:加速 Q/q:退出\n"; SetPos(25, 9); while (1) { if (_kbhit()) { int n; cin >> n; if (1 <= n && n <= 9) { level = n; system("cls"); break; } } } } void Box::buildmap() //初始地图 { int i; for (i = 0; i < 16; i++)//游戏主界面大方格 { SetPos(i * 2, 0);//控制光标位置 cout << "■";//每个图形占两列 } for (i = 1; i <= 28; i++) { SetPos(0, i); cout << "■"; SetPos(30, i); cout << "■"; } for (i = 0; i < 16; i++) { SetPos(i * 2, 28); cout << "■"; } for (i = 17; i <= 26; i++) { SetPos(i * 2, 0); cout << "■"; } for (i = 1; i <= 8; i++) { SetPos(17 * 2, i); cout << "■"; SetPos(26 * 2, i); cout << "■"; } for (i = 17; i <= 26; i++) { SetPos(i * 2, 9); cout << "■"; } SetPos(38, 14); cout << "俄罗斯方块"; SetPos(38, 16); cout << "难度:" << level; SetPos(38, 18); cout << "分数:" << point; } void Box::rotate() //旋转图形,改变输出坐标 { switch (shape) { case 0:shape = 1; break; case 1:shape = 0; break; case 4:break; case 8:shape = 9; break; case 9:shape = 10; break; case 10:shape = 11; break; case 11:shape = 8; break; case 12:shape = 13; break; case 13:shape = 14; break; case 14:shape = 15; break; case 15:shape = 12; break; case 16:shape = 17; break; case 17:shape = 16; break; case 20:shape = 21; break; case 21:shape = 20; break; } } void Box::draw(int x, int y, int Shape) //绘制图形 { int xx, yy; for (int i = 0; i < 4; i++) { //由于方格占两行两列,所以需要*2 xx = x + Map[Shape][i * 2]; yy = y + Map[Shape][i * 2 + 1]; SetPos((yy + 1) * 2, xx + 1); cout << "■"; } } void Box::erase(int x, int y, int Shape) //删除原图形 { int xx, yy; for (int i = 0; i < 4; i++) { xx = x + Map[Shape][i * 2]; yy = y + Map[Shape][i * 2 + 1]; SetPos((yy + 1) * 2, xx + 1); cout << " "; //用两个空格填充原图形 } } int Box::judgeshape() //产生一个随机的图形 { int x = rand() % 24; if (x < 4) return 0; else if (x >= 4 && x <= 7) return 4; else if (x >= 8 && x <= 11) return 8; else if (x >= 12 && x <= 15) return 12; else if (x >= 16 && x <= 19) return 16; else return 20; } bool Box::judge(int x, int y, int shape) //判断当前是否可以绘制方块 { int i; int nx, ny; for (i = 0; i < 4; i++) { nx = x + Map[shape][i * 2]; ny = y + Map[shape][i * 2 + 1]; if (nx < 0 || nx >= 27 || ny < 0 || ny >= 14 || map[nx][ny] == 1) return 0; } return 1; } void Box::Move(char c) //读取键盘输入处理 { if (c == 'A' || c == 'a') { if (judge(base.x, base.y - 1, shape)) { erase(base.x, base.y, shape); base.y -= 1; draw(base.x, base.y, shape); } } else if (c == 'D' || c == 'd') { if (judge(base.x, base.y + 1, shape)) { erase(base.x, base.y, shape); base.y += 1; draw(base.x, base.y, shape); } } else if (c == 'S' || c == 's') { if (judge(base.x + 3, base.y, shape))//下三格没有方格才可以加速 { erase(base.x, base.y, shape); base.x += 2; //让坐标下降一个方格 draw(base.x, base.y, shape); } } else if (c == 'W' || c == 'w') { int t = shape; rotate(); if (judge(base.x, base.y, shape))//判断是否可以旋转 { erase(base.x, base.y, t); draw(base.x, base.y, shape); } else { shape = t; } } else if (c == 'Q' || c == 'q') { system("cls"); color(-1); buildmap(); SetPos(5, 13); cout << " 游戏结束 "; SetPos(5, 14); cout << " 最终分数为:" << point; SetPos(0, 29); system("pause"); exit(0); } else if (c == 'P' || c == 'p') { color(-1); SetPos(5, 13); cout << " 游戏已暂停 "; SetPos(5, 14); cout << " 按P/p键继续 "; while (1) { if (_kbhit()) { char cc = _getch(); if (cc == 'P' || cc == 'p')//暂停后再次按P继续游戏 { SetPos(5, 13); cout << " ";//将上面两行字删除 SetPos(5, 14); cout << " "; break; } } } } } void Box::update() //更新地图 { int xx, yy; for (int i = 0; i < 4; i++)//将图形所在的位置标记 { xx = base.x + Map[shape][i * 2]; yy = base.y + Map[shape][i * 2 + 1]; map[xx][yy] = 1; } if (base.x < top)//记录当前的最高点 { top = base.x; } int num = 0;//记录需要清除的行数,即分数 for (int i = base.x; i < base.x + height[shape]; i++)//从现在图形的基点向下 { int flag = 1;//判断这一行是否可以消除 for (int j = 0; j < 14; j++) { if (map[i][j] == 0) { flag = 0; break; } } if (flag)//可以消除 { for (int j = i; j >= top; j--)//从可以消除的一行开始,上面所有方格下移一行 { if (j == 0)//特判如果这一行是第0行 { for (int k = 0; k < 14; k++) { map[j][k] = 0; SetPos((k + 1) * 2, j + 1); cout << " "; } } else { for (int k = 0; k < 14; k++) { map[j][k] = map[j - 1][k]; SetPos((k + 1) * 2, j + 1); color(-1);//将颜色设定为白色 if (map[j][k] == 1) cout << "■"; else cout << " "; } } } top++;//top下移,防止重复更新 num++; point += num * 100; } else//不能删除这一行 { for (int j = base.x + height[shape] - 1; j >= base.x; j--) { for (int k = 0; k < 14; k++) { SetPos((k + 1) * 2, j + 1); color(-1);//将颜色设置为白色 if (map[j][k] == 1) cout << "■"; else cout << " "; } } } } SetPos(38, 18);//更新分数 cout << "分数:" << point; } void Box::color(int x) //设置颜色 { if (x >= 0 && x < 4)//设为红色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED); } else if (x >= 4 && x <= 7)//设为绿色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN); } else if (x >= 8 && x <= 11)//设为蓝色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE); } else if (x >= 12 && x <= 15)//设为橘色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN); } else if (x >= 16 && x <= 19)//设为天蓝色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN); } else if (x >= 20 && x <= 23)//设为紫色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE); } else if (x == -1)//设为白色 { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } } void Box::run() //运行游戏 { buildmap(); //绘制地图 SetPos(7, 11); cout << "按任意键开始!"; while (1)//按任意键开始游戏 { if (_kbhit()) { system("cls"); color(-1);//白色 buildmap(); break; } } srand(unsigned(time(0)));//利用系统时间随机数产生随机图形 shape = judgeshape();//现在的图形 int nextshape = judgeshape();//下一个图形 color(shape);//更改输出的图形颜色 draw(base.x, base.y, shape);//绘制图形 color(nextshape); draw(3, 20, nextshape); speed = 100 - level * 10;//设置图形下落速度,根据所选难度不同速度不同 color(shape); int cnt = 0; //记录当前经过多少时间 while (1)//每次循环时间为1毫秒 { if (cnt >= speed)//超过50毫秒后自动向下移动 { cnt = 0;//计数器归零 if (judge(base.x + 1, base.y, shape))//下一格没有方块,图形下移一格 { erase(base.x, base.y, shape); color(shape); draw(base.x + 1, base.y, shape); base.x += 1; } else //下一格有方块 { update();//更新图形 shape = nextshape;//更新当前图形为下一个图形 nextshape = judgeshape();//生成新的下一个图形 erase(3, 20, shape); color(nextshape); draw(3, 20, nextshape); base.x = 0; base.y = 5;//更新基点 color(shape); draw(base.x, base.y, shape); if (!judge(base.x, base.y, shape))//如果不能绘制图形,说明到达顶点,游戏结束 { color(-1); SetPos(5, 13); cout << " 游戏结束 "; SetPos(5, 14); cout << " 最终分数为:" << point; SetPos(0, 29); system("pause"); exit(0); } } } if (_kbhit())//如果有键盘输入 { char c = _getch(); Move(c);//判断处理键盘输入 while (_kbhit())//读掉剩下的键盘信息 _getch(); } Sleep(1);//等待1毫秒 cnt++;//计数器+1 } } int main() { Box Tetrisl;//创建俄罗斯方块类 system("mode con cols=120 lines=42");//调整窗口大小 Tetrisl.menu();//显示游戏开始菜单 HideCursor();//游戏开始后隐藏光标 Tetrisl.run();//游戏运行 system("pause"); return 0; }