俄罗斯方块的 C++实现
源码下载地址: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>//设置位置
- }
下面是画地图的函数,地图是长12,宽23的地图,然后用白块做一圈外围,外围比地图大1,下面是代码:
- 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 << " ";
- }
- }
下面是判断是否可以完成想要的操作,比如下降,翻转,x、y是当前热点的坐标,然后根据当前坐标加上每种图形的四个点,全都没有超界或者没有方块,就可以做操作:
- 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;
- }
下面是翻转方块的操作,就是改一下方块id:
- 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++;
- }
- }
最后就是main函数了:
- #include "Tetris.h"
- int main()
- {
- tetris ter;
- ter.RunGame();
- return 0;
- }
最后把上面的连起来就可以运行了,下面是截图:
俄罗斯方块的 C++实现相关推荐
- python编的俄罗斯方块游戏下载_python写的俄罗斯方块游戏
python写的俄罗斯方块游戏 功能包括:记录所花费时间;消去的总行数;总分;排行榜,最高记录查看等. 排行榜中包含一系列的统计功能,如单位时间消去的行数,单位时间得分等. from Tkinter ...
- GitHub开源的超逼真俄罗斯方块游戏
俄罗斯方块一直是各类程序语言热衷实现的经典游戏,有很多JavaScript实现版本,本开源项目使用React实现. 项目试玩网址:https://chvin.github.io/react-tetri ...
- Python实现俄罗斯方块
目录 1.外形设计 2.方块设计 3.停靠设计 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.但是想到旋转,停靠,消除等操作,感觉好像很难啊,等真正写完了发现 ...
- AI玩俄罗斯方块(Python实现)
目录 1.环境 2.实现机制(Pierre Dellacherie算法) 3.代码实现 人工智能大火的今天,如果还是自己玩俄罗斯方块未免显得太LOW,为什么不对游戏升级,让机器自己去玩俄罗斯方块呢?有 ...
- 如何让AI教机器自己玩俄罗斯方块?
作者 | Ahab 转载自公众号Ahab杂货铺(ID:PythonLearningCamp) 人工智能大火的今天,如果还是自己玩俄罗斯方块未免显得太 LOW,为什么不对游戏升级,让机器自己去玩俄罗斯方 ...
- 500行代码写一个俄罗斯方块游戏
导读:本文我们要制作一个俄罗斯方块游戏. 01 俄罗斯方块 Tetris 俄罗斯方块游戏是世界上最流行的游戏之一.是由一名叫Alexey Pajitnov的俄罗斯程序员在1985年制作的,从那时起,这 ...
- 算法帖——用舞蹈链算法(Dancing Links)求解俄罗斯方块覆盖问题
问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形.如何用计算机求解? 解决这类问题的方法不一而足,然而核心思想都是穷举法,不同的方法仅仅是对穷举法进行了优化 用13块不同形状的俄罗斯方块(每个 ...
- python俄罗斯方块算法详解_用 Python 写一个俄罗斯方块游戏 (
@@ -2,34 +2,34 @@ > * 原文作者:[Dr Pommes](https://medium.com/@pommes) > * 译文出自:[掘金翻译计划](https://g ...
- pygame简单的俄罗斯方块游戏和简单的打字游戏
1.pygame简单的俄罗斯方块游戏 一.对战的方块管理 定义一个BlockManage管理对战的方块 根据BlockManage根据传入的玩家id返回方块,保证每个玩家拿到的方块序列是一致的,所以在 ...
- linux下c语言俄罗斯方块,C语言实现俄罗斯方块源代码
本文实例为大家分享了C语言实现俄罗斯方块的具体代码,供大家参考,具体内容如下 Head.h #ifndef _HEAD_H_ #define _HEAD_H_ #include #include #i ...
最新文章
- 二本毕业后3年发两篇Nature引热议,他此前研究刷新世界纪录
- 计算机网络运输层习题5-13
- MAS 714课程笔记12: 线性规划
- 下列哪个不是it行业技术岗位_28岁毕业进入IT互联网行业从事技术研发岗位是否还来得及...
- location 匹配规则 (NGINX)
- Nginx 安装配置【必须把文件到放到机器上】
- 真正的大学老师,是那些无需打卡和考评,也会不可遏止地要去读书写作和上课的人...
- python字典键值对转化为相应的变量名和变量值
- 适合小白的Python学习大纲
- -00020 ora_ORA-00020 超出最大进程数的解决方法
- OpenJTAG与JLink的区别比较
- SqlServer 按指定顺序进行排序
- php二分法实力,php常见的几种排序以及二分法查找
- 【知云】第十期:如何保障云上游戏安全?云盾+高防IP筑起云上安全高墙
- 粒子群算法 模拟退火算法
- 计算机网络原理(3)数据编码技术
- POI复制Excel模板并填充数据
- 华硕电脑GeForce类显卡如何解决:NVIDIA安装程序无法继续
- EXCEL常见数据处理操作(一)
- 【图像分割】基于matlab扩散张量成像(DTI)脑白质纤维束成像【含Matlab源码 2174期】