源码下载地址: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:

[cpp]  view plain copy
  1. #ifndef TETRIS_H_
  2. #define TETRIS_H_
  3. #include <windows.h>
  4. //长条形
  5. const int A1 = 0;
  6. const int A2 = 7;
  7. //方块
  8. const int B = 1;
  9. //L 形状
  10. const int C11 = 2;
  11. const int C12 = 8;
  12. const int C13 = 9;
  13. const int C14 = 10;
  14. //L 的另一个形状
  15. const int C21 = 3;
  16. const int C22 = 11;
  17. const int C23 = 12;
  18. const int C24 = 13;
  19. //Z 形状
  20. const int D11 = 4;
  21. const int D12 = 14;
  22. //Z 的另一个形状
  23. const int D21 = 5;
  24. const int D22 = 15;
  25. //土字形
  26. const int E31 = 6;
  27. const int E32 = 16;
  28. const int E33 = 17;
  29. const int E34 = 18;
  30. class tetris
  31. {
  32. private:
  33. int map[12][23];        //背景
  34. int top;            //当前的最高点
  35. int score;          //分数
  36. int level;          //难度等级
  37. int ID;             //当前的方块的形状
  38. int hotPoint[2];        //热点,当前活动的所在点
  39. public:
  40. tetris()
  41. {
  42. for (int i = 0; i < 12; i++)<span style="white-space:pre">     </span>//初始化地图
  43. for (int j = 0; j < 23; j++)
  44. map[i][j] = 0;
  45. top = 99;
  46. score = 0;
  47. level = 1;
  48. ID = 0;
  49. hotPoint[0] = 5;    //下落起始点的横坐标
  50. hotPoint[1] = 0;    //下落起始点的纵坐标
  51. }
  52. void DrawMap();         <span style="white-space:pre">    </span>//绘制地图
  53. void initInterface();           //初始化界面
  54. void DrawBox(int x, int y, int id); //绘制图形
  55. void ReBox(int x, int y, int id);   //擦除图形
  56. int  IsJudge(int x, int y, int id); //是否可以绘制图形
  57. int  TurnBlock(int id);         //旋转方块
  58. void UpdateMap(int id);         //更新画面
  59. void RunGame();             //运行
  60. };
  61. #endif

下面就是包含所有形状的二维数组,最后一个数是颜色,还有包含每个形状的高度的数组:

[cpp]  view plain copy
  1. int sharp[19][9] =                  //每个一维数组内有8个点,每两个点是一个 形状的一个小方格,在4*4的表格中
  2. {
  3. { 0, 0, 0, 1, 0, 2, 0, 3, FOREGROUND_RED | FOREGROUND_INTENSITY },          //长条形
  4. { 0, 0, 1, 0, 0, 1, 1, 1, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY },   //方形
  5. { 0, 0, 0, 1, 1, 1, 2, 1, FOREGROUND_GREEN | FOREGROUND_RED },              //L形
  6. { 0, 1, 1, 1, 2, 1, 2, 0, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },  //反L形
  7. { 0, 0, 1, 0, 1, 1, 2, 1, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY },    //Z形
  8. { 1, 0, 2, 0, 0, 1, 1, 1, FOREGROUND_GREEN | FOREGROUND_INTENSITY },            //反Z形
  9. { 0, 0, 0, 1, 0, 2, 1, 1, FOREGROUND_BLUE | FOREGROUND_INTENSITY },     //土形
  10. //下面是上面形状的变换
  11. { 0, 0, 1, 0, 2, 0, 3, 0, FOREGROUND_RED | FOREGROUND_INTENSITY },
  12. { 1, 0, 1, 1, 1, 2, 0, 2, FOREGROUND_GREEN | FOREGROUND_RED },
  13. { 0, 0, 1, 0, 2, 0, 2, 1, FOREGROUND_GREEN | FOREGROUND_RED },
  14. { 0, 0, 1, 0, 0, 1, 0, 2, FOREGROUND_GREEN | FOREGROUND_RED },
  15. { 0, 0, 1, 0, 1, 1, 1, 2, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },
  16. { 0, 0, 1, 0, 2, 0, 0, 1, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },
  17. { 0, 0, 0, 1, 0, 2, 1, 2, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY },
  18. { 1, 0, 0, 1, 1, 1, 0, 2, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY },
  19. { 0, 0, 0, 1, 1, 1, 1, 2, FOREGROUND_GREEN | FOREGROUND_INTENSITY },
  20. { 0, 0, 1, 0, 2, 0, 1, 1, FOREGROUND_BLUE | FOREGROUND_INTENSITY },
  21. { 0, 1, 1, 0, 1, 1, 1, 2, FOREGROUND_BLUE | FOREGROUND_INTENSITY },
  22. { 1, 0, 0, 1, 1, 1, 2, 1, FOREGROUND_BLUE | FOREGROUND_INTENSITY }
  23. };
  24. int high[19] = { 4, 2, 2, 2, 2, 2, 3, 1, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 2 };  //数组是用来保存上面每个一维数组的各个形状高度的

设定光标位置的函数,同时设定输出的颜色:

[cpp]  view plain copy
  1. void setCurPos(int i, int j, int color = 1 | 2 | 4)
  2. {                           <span style="white-space:pre">    </span>//color相当于自己选择颜色,没有就用默认的白色
  3. HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);       //获得标准输出句柄
  4. SetConsoleTextAttribute(out, color);<span style="white-space:pre">            </span>//设置颜色
  5. COORD pos = { i * 2, j };
  6. SetConsoleCursorPosition(out, pos);<span style="white-space:pre">         </span>//设置位置
  7. }

下面是画地图的函数,地图是长12,宽23的地图,然后用白块做一圈外围,外围比地图大1,下面是代码:

[cpp]  view plain copy
  1. void tetris::DrawMap()
  2. {
  3. //地图框架
  4. for (int i = 0; i < 14; i++)     // 0 - 13
  5. {
  6. setCurPos(i, 0);
  7. cout << "■";
  8. }
  9. for (int i = 0; i < 25; i++) // 0 - 24
  10. {
  11. setCurPos(0, i);
  12. cout << "■";
  13. setCurPos(13, i);
  14. cout << "■";
  15. }
  16. for (int i = 0; i < 14; i++)
  17. {
  18. setCurPos(i, 24);
  19. cout << "■";
  20. }
  21. //信息框架
  22. for (int i = 15; i <= 25; i++)
  23. {
  24. setCurPos(i, 0);
  25. cout << "■";
  26. setCurPos(i, 8);
  27. cout << "■";
  28. }
  29. for (int i = 0; i <= 8; i++)
  30. {
  31. setCurPos(15, i);
  32. cout << "■";
  33. setCurPos(25, i);
  34. cout << "■";
  35. }
  36. setCurPos(16, 12);
  37. cout << "俄罗斯方块(6D)";
  38. setCurPos(16, 15);
  39. cout << " 分数: " << score;
  40. setCurPos(16, 16);
  41. cout << " 等级: " << level;
  42. }

下面是画方块和消除方块的函数:

[cpp]  view plain copy
  1. void tetris::DrawBox(int x, int y, int id)<span style="white-space:pre">      </span>//画方块
  2. {
  3. int nx = 0, ny = 0;
  4. int color = sharp[id][8];
  5. for (int i = 0; i < 4; i++)
  6. {
  7. nx = x + sharp[id][i * 2];
  8. ny = y + sharp[id][i * 2 + 1];
  9. 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">
  10. </span>       cout << "■";
  11. }
  12. }
  13. void tetris::ReBox(int x, int y, int id)<span style="white-space:pre">        </span>//消除方块
  14. {
  15. int nx = 0, ny = 0;
  16. for (int i = 0; i < 4; i++)
  17. {
  18. nx = x + sharp[id][i * 2];
  19. ny = y + sharp[id][i * 2 + 1];
  20. setCurPos(nx + 1, ny + 1);<span style="white-space:pre">      </span>
  21. cout << " ";
  22. }
  23. }

下面是判断是否可以完成想要的操作,比如下降,翻转,x、y是当前热点的坐标,然后根据当前坐标加上每种图形的四个点,全都没有超界或者没有方块,就可以做操作:

[cpp]  view plain copy
  1. int tetris::IsJudge(int x, int y, int id)
  2. {
  3. int nx = 0, ny = 0;
  4. for (int i = 0; i < 4; i++)
  5. {
  6. nx = x + sharp[id][i * 2];
  7. ny = y + sharp[id][i * 2 + 1];
  8. if (nx < 0 || nx >= 12 || ny < 0 || ny >= 23 || map[nx][ny] != 0)   //不能放了,返回0
  9. return 0;
  10. }
  11. return 1;
  12. }

下面是翻转方块的操作,就是改一下方块id:

[cpp]  view plain copy
  1. int tetris::TurnBlock(int id)
  2. {
  3. switch (id)
  4. {
  5. case A1: id = A2;  break;
  6. case A2: id = A1;  break;
  7. case B:  id = B;   break;
  8. case C11:id = C12; break;
  9. case C12:id = C13; break;
  10. case C13:id = C14; break;
  11. case C14:id = C11; break;
  12. case C21:id = C22; break;
  13. case C22:id = C23; break;
  14. case C23:id = C24; break;
  15. case C24:id = C21; break;
  16. case D11:id = D12; break;
  17. case D12:id = D11; break;
  18. case D21:id = D22; break;
  19. case D22:id = D21; break;
  20. case E31:id = E32; break;
  21. case E32:id = E33; break;
  22. case E33:id = E34; break;
  23. case E34:id = E31; break;
  24. }
  25. return id;
  26. }

下面是更新地图,当有方块落到最底下时,检查下落方块的高度范围内是否可以消行,如果可以就消除:

[cpp]  view plain copy
  1. void tetris::UpdateMap(int id)
  2. {
  3. int nx = 0, ny = 0;
  4. int flag;
  5. int clear = 0;                          //清除了多少个行,最后积分
  6. for (int i = 0; i < 4; i++)
  7. {
  8. nx = hotPoint[0] + sharp[id][i * 2];
  9. ny = hotPoint[1] + sharp[id][i * 2 + 1];
  10. map[nx][ny] = sharp[id][8];             //保存颜色值,因为颜色值不为0,所以可以和没有方格区分开
  11. }
  12. if (hotPoint[1] < top)<span style="white-space:pre">           </span>//因为地图的最上面是0,最底层是22,所以当前热点的y坐标如果小于top,就是最高点变化了,更新一下top
  13. top = hotPoint[1];
  14. for (int j = hotPoint[1]; j < hotPoint[1] + high[id]; j++)   //从上向下进行消除,从下向上容易少消行
  15. {
  16. flag = 0;
  17. for (int i = 0; i < 12; i++)
  18. {
  19. if (map[i][j] == 0)         <span style="white-space:pre">    </span>//没有可以消除的
  20. {
  21. flag = 1;
  22. break;
  23. }
  24. }
  25. if (flag == 0)                      //可以消除当前行
  26. {
  27. for (int k = j; k >= top; k--)<span style="white-space:pre">           </span>//将每一行的上一行下移,直到最高点所在行下移完毕
  28. {
  29. if (k == 0)             //消除 到了最顶行
  30. {
  31. for (int i = 0; i < 12; i++)
  32. {
  33. map[i][k] = 0;
  34. setCurPos(i + 1, k + 1);
  35. cout << " ";
  36. }
  37. }
  38. else
  39. {
  40. for (int i = 0; i < 12; i++)
  41. {
  42. map[i][k] = map[i][k - 1];
  43. setCurPos(i + 1, k + 1);   //因为有两条图形框边,游戏运行过程中的坐标系相对于 真正的坐标系是x、y都加 1 的
  44. if (map[i][k] == 0)    //被删除行的 上一行是空的,所以这一行也是空的
  45. cout << " ";
  46. else                        //上一行不是空的
  47. {
  48. int tempColor = map[i][k];
  49. setCurPos(i + 1, k + 1, tempColor);
  50. cout << "■";
  51. }
  52. }
  53. }
  54. }
  55. top++;                  <span style="white-space:pre">    </span>//消除成功,最高点下降一个
  56. clear++;
  57. score += clear * 100;
  58. }
  59. }
  60. setCurPos(16, 15);
  61. cout << " 分数: " << score;
  62. }

下面就是运行游戏了,把上面的代码组合一下就好:

[cpp]  view plain copy
  1. void tetris::RunGame()
  2. {
  3. initInterface();
  4. system("cls");
  5. DrawMap();
  6. char x = ' ';                   //读取键盘信息
  7. int i = 0;      <span style="white-space:pre">    </span>       //计时,到时间没有获得指令,自动下降
  8. int Count = 0;
  9. int nextId = 0;
  10. int curId = 0;
  11. srand(time(0));
  12. curId = rand() % 7;
  13. nextId = rand() % 7;
  14. DrawBox(hotPoint[0], hotPoint[1], curId);   //画当前图形
  15. DrawBox(17, 3, nextId);             //画出下一个要出现的图形
  16. Count = 10000 - 1000 * level;
  17. while (1)
  18. {
  19. if (i >= Count)                                  //可以自动下移了
  20. {
  21. i = 0;                                  //将 i 清零,下次继续计数
  22. if (IsJudge(hotPoint[0], hotPoint[1] + 1, curId) == 0)  <span style="white-space:pre">        </span>//下个位置无效,到底了
  23. {
  24. UpdateMap(curId);                       //更新一下画面
  25. ReBox(17, 3, nextId);               <span style="white-space:pre">    </span>   //清除原来的下一个图形
  26. curId = nextId;
  27. nextId = rand() % 7;
  28. hotPoint[0] = 5;                        //更新热点
  29. hotPoint[1] = 0;
  30. DrawBox(hotPoint[0], hotPoint[1], curId);
  31. DrawBox(17, 3, nextId);                 <span style="white-space:pre">    </span>//画上现在的下一个图形
  32. if (IsJudge(hotPoint[0], hotPoint[1], curId) == 0)      //无法绘制当前图形
  33. {
  34. system("cls");
  35. cout << "游戏结束!!!最终得分为:" << score << endl;
  36. system("pause");
  37. exit(0);
  38. }
  39. }
  40. else
  41. {
  42. ReBox(hotPoint[0], hotPoint[1], curId);
  43. hotPoint[1]++;
  44. DrawBox(hotPoint[0], hotPoint[1], curId);
  45. }
  46. }
  47. if (_kbhit())                                   //读取键盘信息
  48. {
  49. x = _getch();
  50. if (x == 'a' || x == 'A')                       //左移
  51. {
  52. if (IsJudge(hotPoint[0] - 1, hotPoint[1], curId))
  53. {
  54. ReBox(hotPoint[0], hotPoint[1], curId);
  55. hotPoint[0]--;
  56. DrawBox(hotPoint[0], hotPoint[1], curId);
  57. }
  58. }
  59. else if (x == 'd' || x == 'D')              <span style="white-space:pre">        </span>//右移
  60. {<span style="white-space:pre">           </span>
  61. if (IsJudge(hotPoint[0] + 1, hotPoint[1], curId))
  62. {
  63. ReBox(hotPoint[0], hotPoint[1], curId);
  64. hotPoint[0]++;
  65. DrawBox(hotPoint[0], hotPoint[1], curId);
  66. }
  67. }
  68. else if (x == 's' || x == 'S')              <span style="white-space:pre">        </span>//向下加速
  69. {
  70. if (IsJudge(hotPoint[0], hotPoint[1] + 1, curId))
  71. {
  72. ReBox(hotPoint[0], hotPoint[1], curId);
  73. hotPoint[1]++;
  74. DrawBox(hotPoint[0], hotPoint[1], curId);
  75. }
  76. }
  77. else if (x == 'w' || x == 'W')<span style="white-space:pre">                      </span>//变形
  78. {
  79. int temp = curId;
  80. curId = TurnBlock(curId);
  81. if (IsJudge(hotPoint[0], hotPoint[1], curId))
  82. {
  83. ReBox(hotPoint[0], hotPoint[1], temp);
  84. DrawBox(hotPoint[0], hotPoint[1], curId);
  85. }
  86. else
  87. curId = temp;
  88. }
  89. else if (x == ' ')                          //暂停
  90. {
  91. _getch();
  92. }
  93. while (_kbhit())                            //读取掉剩下的键盘信息s
  94. _getch();
  95. }
  96. i++;
  97. }
  98. }

最后就是main函数了:

[cpp]  view plain copy
  1. #include "Tetris.h"
  2. int main()
  3. {
  4. tetris ter;
  5. ter.RunGame();
  6. return 0;
  7. }

最后把上面的连起来就可以运行了,下面是截图:

俄罗斯方块的 C++实现相关推荐

  1. python编的俄罗斯方块游戏下载_python写的俄罗斯方块游戏

    python写的俄罗斯方块游戏 功能包括:记录所花费时间;消去的总行数;总分;排行榜,最高记录查看等. 排行榜中包含一系列的统计功能,如单位时间消去的行数,单位时间得分等. from Tkinter ...

  2. GitHub开源的超逼真俄罗斯方块游戏

    俄罗斯方块一直是各类程序语言热衷实现的经典游戏,有很多JavaScript实现版本,本开源项目使用React实现. 项目试玩网址:https://chvin.github.io/react-tetri ...

  3. Python实现俄罗斯方块

    目录 1.外形设计 2.方块设计 3.停靠设计 俄罗斯方块是儿时最经典的游戏之一,刚开始接触 pygame 的时候就想写一个俄罗斯方块.但是想到旋转,停靠,消除等操作,感觉好像很难啊,等真正写完了发现 ...

  4. AI玩俄罗斯方块(Python实现)

    目录 1.环境 2.实现机制(Pierre Dellacherie算法) 3.代码实现 人工智能大火的今天,如果还是自己玩俄罗斯方块未免显得太LOW,为什么不对游戏升级,让机器自己去玩俄罗斯方块呢?有 ...

  5. 如何让AI教机器自己玩俄罗斯方块?

    作者 | Ahab 转载自公众号Ahab杂货铺(ID:PythonLearningCamp) 人工智能大火的今天,如果还是自己玩俄罗斯方块未免显得太 LOW,为什么不对游戏升级,让机器自己去玩俄罗斯方 ...

  6. 500行代码写一个俄罗斯方块游戏

    导读:本文我们要制作一个俄罗斯方块游戏. 01 俄罗斯方块 Tetris 俄罗斯方块游戏是世界上最流行的游戏之一.是由一名叫Alexey Pajitnov的俄罗斯程序员在1985年制作的,从那时起,这 ...

  7. 算法帖——用舞蹈链算法(Dancing Links)求解俄罗斯方块覆盖问题

    问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形.如何用计算机求解? 解决这类问题的方法不一而足,然而核心思想都是穷举法,不同的方法仅仅是对穷举法进行了优化 用13块不同形状的俄罗斯方块(每个 ...

  8. python俄罗斯方块算法详解_用 Python 写一个俄罗斯方块游戏 (

    @@ -2,34 +2,34 @@ > * 原文作者:[Dr Pommes](https://medium.com/@pommes) > * 译文出自:[掘金翻译计划](https://g ...

  9. pygame简单的俄罗斯方块游戏和简单的打字游戏

    1.pygame简单的俄罗斯方块游戏 一.对战的方块管理 定义一个BlockManage管理对战的方块 根据BlockManage根据传入的玩家id返回方块,保证每个玩家拿到的方块序列是一致的,所以在 ...

  10. linux下c语言俄罗斯方块,C语言实现俄罗斯方块源代码

    本文实例为大家分享了C语言实现俄罗斯方块的具体代码,供大家参考,具体内容如下 Head.h #ifndef _HEAD_H_ #define _HEAD_H_ #include #include #i ...

最新文章

  1. 二本毕业后3年发两篇Nature引热议,他此前研究刷新世界纪录
  2. 计算机网络运输层习题5-13
  3. MAS 714课程笔记12: 线性规划
  4. 下列哪个不是it行业技术岗位_28岁毕业进入IT互联网行业从事技术研发岗位是否还来得及...
  5. location 匹配规则 (NGINX)
  6. Nginx 安装配置【必须把文件到放到机器上】
  7. 真正的大学老师,是那些无需打卡和考评,也会不可遏止地要去读书写作和上课的人...
  8. python字典键值对转化为相应的变量名和变量值
  9. 适合小白的Python学习大纲
  10. -00020 ora_ORA-00020 超出最大进程数的解决方法
  11. OpenJTAG与JLink的区别比较
  12. SqlServer 按指定顺序进行排序
  13. php二分法实力,php常见的几种排序以及二分法查找
  14. 【知云】第十期:如何保障云上游戏安全?云盾+高防IP筑起云上安全高墙
  15. 粒子群算法 模拟退火算法
  16. 计算机网络原理(3)数据编码技术
  17. POI复制Excel模板并填充数据
  18. 华硕电脑GeForce类显卡如何解决:NVIDIA安装程序无法继续
  19. EXCEL常见数据处理操作(一)
  20. 【图像分割】基于matlab扩散张量成像(DTI)脑白质纤维束成像【含Matlab源码 2174期】

热门文章

  1. 电脑主机板刷bios、后无法获取网络ip的设置
  2. Combo Box (组合框)控件
  3. 为什么多迪技术人员都喜欢用python写爬虫?
  4. css字体大小兼容性问题
  5. 绿豆芽评级平台部分展示
  6. 数据团队规划布局感悟(二)
  7. 阿里巴巴社招内推,简历直达Leader,略过 HR筛选,流程快,效率高
  8. java大数运算详解【其三】大数乘法之平方算法之按位二次展开式算法
  9. 嵌入式热敏打印机模块-优库E58T-1玩起来
  10. 协同OA产品要完全符合企业的办公模式吗? 1