找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6483|回复: 2
打印 上一主题 下一主题
收起左侧

c++小游戏(贪吃蛇)源程序

[复制链接]
跳转到指定楼层
楼主
ID:613800 发表于 2019-9-25 09:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
设计的小游戏,初学者可以加点自己想加的其他功能。

游戏规则
        贪食蛇游戏要求玩家控制方向键(或WSAD键)来控制小蛇的前进方向,以使蛇吃掉面板上随即位置上的食物。每次成功吃掉食物后小蛇体长将增加一点,得分增加。当小蛇撞到边界或者蛇头与蛇身相撞时,蛇将挂掉,游戏随之结束。

游戏结构设计
        游戏应当包含初始欢迎界面,游戏界面,游戏结束界面。

        建立一个CGame类,来管理游戏的进度。该类放在Game.h文件中,在该类中可以分别定义NewGame(),PlayGame(),SetGame()和ExitGame()四个函数来控制游戏的各个单元,为了使整个程序看起来更像个游戏,可以采取更加漂亮的界面来展示游戏各部分。


NewGame()函数设定游戏欢迎界面。可以简单地输出了一些方块字符组成的游戏名SNAKE和一句提示“Press any key to start…”。点击任意键后,游戏程序将转入SetGame()中继续执行。可以加上一些动态效果,让提示”Press any keyto start…”不断跳动。
SetGame()中包括游戏的设置内容。可以选择Easy,Normal,Hard三个选项。这三个选项将对应小蛇不同的的移动速度,具体来说将体现在PlayGame()函数中每次循环执行速度。设置完成后,游戏程序将转入PlayGame()继续执行。
PlayGame()函数主体将是一个死循环,因为可将游戏考虑成一个无穷的循环,循环中迭代的每一步都依次进行:判断用户是否输入、然后根据用户输入调整游戏内容(如果没有输入则按默认方式继续执行游戏)、判断是否符合规则(不符合则跳出循环,转入ExitGame()退出游戏)、判断是否需要加分扣分。执行完以上这些步骤后,将进行下一次迭代。当然进行游戏之前,还要执行必要的初始化工作,来显示大体框架和提示信息。
EitGame()中将显示游戏得分,并询问玩家是否再玩一次。这里拼出了一个骷髅头的图案,表示Game Over。


        以上为游戏的主体内容,这四个函数设定了游戏的基本结构,剩余部分将继续考虑细节问题。然后再展示Game.h的细节内容。

建立游戏对象
        先建立一系列类表示游戏对象,其中应包括对游戏对象的处理方式(函数)。分析游戏,可以知道游戏主体是小蛇和食物。

        所有的游戏对象,包括蛇和食物,都是由控制台上的一系列点组成的。因此需要很多处理点对象的方法。可建立Point.h来定义CPoint对象,来简化其他对象的处理。

代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <conio.h>
  5. #include <windows.h>
  6. #define W 32
  7. #define H 22
  8. const int SIZE_SK = 30*20;
  9. HANDLE hOut;
  10. COORD pos= {0, 0};
  11. CONSOLE_CURSOR_INFO cur_info = {1, 0};
  12. struct snake {
  13. short x, y; //节点坐标
  14. short md; //节点运动方向
  15. short num; //节点内容
  16. int col; //节点颜色
  17. } snake[30*20];
  18. const short dx[4] = {-1, 1, 0, 0}; //方向
  19. const short dy[4] = {0, 0, -1, 1}; //方向
  20. short gamemap[W][H];
  21. short head, tail, score=0;


  22. void initmap(int tm);
  23. void createFood(void);
  24. int getkeys(void);
  25. int move(int idx);
  26. void pntSnake(int i);
  27. void drawEdge(void);
  28. void gameinfo(char *s, int n);


  29. int main(void)
  30. {
  31. int tm = 150; //刷新间隔150毫秒
  32. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  33. SetConsoleCursorInfo(hOut, &cur_info); //隐藏光标
  34. system("COLOR 2f");
  35. initmap(tm);
  36. return 0;
  37. }
  38. void initmap(int tm)
  39. {
  40. short x, y, i, j;
  41. int index, tmp, ret_m;

  42. while (1){
  43. head=0;
  44. tail=-1;
  45. score=0;
  46. //初始化蛇节点随机颜色
  47. srand(time(0));
  48. for (i=0; i<SIZE_SK; i++)
  49. snake[i].col = rand()%8+8 | 0x20;
  50. //初始化地图数组
  51. for (i=0; i<W; i++)
  52. for (j=0; j<H; j++)
  53. gamemap[i][j] = 0;
  54. system("cls");
  55. //绘制边界
  56. drawEdge();
  57. //打印蛇头
  58. srand(time(0));
  59. do {
  60. x = rand()%(W-2) + 1;
  61. y = rand()%(H-2) + 1;
  62. } while (gamemap[x][y] != 0); //只在空白处生成
  63. snake[head].x = x;
  64. snake[head].y = y;
  65. gamemap[x][y] = snake[head].num = 1;
  66. pos.X = x*2;
  67. pos.Y = y;
  68. SetConsoleCursorPosition(hOut, pos);
  69. printf("█");
  70. //打印食物
  71. createFood();
  72. while ((index=getkeys()) == 4)
  73. Sleep(500);
  74. //循环开始
  75. while (1){
  76. ret_m = move(index);
  77. if (ret_m == 1){
  78. pos.X = 0; pos.Y = H;
  79. SetConsoleCursorPosition(hOut, pos);
  80. printf("哎呀,挂了哦 ^_^");
  81. break;
  82. }
  83. else if (ret_m == 2){
  84. pos.X = 0; pos.Y = H;
  85. SetConsoleCursorPosition(hOut, pos);
  86. printf("哎呀,超神了 ^_^");
  87. break;
  88. }
  89. Sleep(tm);
  90. if ((tmp = getkeys()) != 4)
  91. index = tmp;
  92. }
  93. //菜单代码
  94. puts(" 按w\\s\\a\\d 继续玩,退出请关闭我");
  95. getch();
  96. }
  97. }
  98. void createFood(void)
  99. {
  100. short x, y;
  101. srand(time(0));
  102. do {
  103. x = rand()%(W-2) + 1;
  104. y = rand()%(H-2) + 1;
  105. } while (gamemap[x][y] != 0);
  106. gamemap[x][y] = 2;
  107. pos.X = x*2; pos.Y = y;
  108. SetConsoleCursorPosition(hOut, pos);
  109. SetConsoleTextAttribute(hOut, 0x2f);
  110. printf("⊙");
  111. }
  112. int getkeys(void) //获取方向键
  113. {
  114. char ch;
  115. while(kbhit()){
  116. ch = getch();
  117. if(ch == 'w')
  118. return 2;
  119. if(ch == 's')
  120. return 3;
  121. if(ch == 'a')
  122. return 0;
  123. if(ch == 'd')
  124. return 1;
  125. while (kbhit());
  126. }
  127. return 4;
  128. }
  129. int move(int idx)
  130. {
  131. int newx, newy, pt_tail, i;

  132. newx = snake[head].x + dx[idx];
  133. newy = snake[head].y + dy[idx];
  134. switch (gamemap[newx][newy]){
  135. case 0:
  136. if ((head = ++head%SIZE_SK) != tail){ //不相等即蛇节点队列未满
  137. snake[head].x = newx;
  138. snake[head].y = newy;
  139. snake[head].num = 1;
  140. gamemap[newx][newy] = 1;
  141. tail = ++tail%SIZE_SK;
  142. snake[tail].num = 0; //清除尾部,打印空字符
  143. gamemap[snake[tail].x][snake[tail].y] = 0;
  144. snake[head].md = idx; //存储移动方向
  145. pt_tail = tail - 1;
  146. }
  147. else
  148. return 2; //回合结束标记2代表蛇填满空间
  149. break;
  150. case 2:
  151. if ((head = ++head%SIZE_SK) != tail){ //不相等即蛇节点队列未满
  152. snake[head].x = newx; //head+1后存储新坐标为蛇头
  153. snake[head].y = newy;
  154. snake[head].num = 1;
  155. gamemap[newx][newy] = 1;
  156. snake[head].md = idx; //存储移动方向
  157. pt_tail = tail = tail%SIZE_SK;
  158. score++;
  159. createFood();
  160. }
  161. break;
  162. case 3:
  163. return 1; //遇到墙壁
  164. case 1:
  165. return 1; //遇到自身
  166. default: ;
  167. }
  168. //打印蛇
  169. if (pt_tail == -1)
  170. pt_tail++;
  171. if (pt_tail < head){ //尾巴在头部后面(这两者是数组索引)
  172. for (i=pt_tail; i<=head; i++){
  173. pntSnake(i); //打印
  174. }
  175. }
  176. else{
  177. for (i=pt_tail; i<SIZE_SK; i++)
  178. pntSnake(i);
  179. for (i=0; i<=head; i++)
  180. pntSnake(i);
  181. }
  182. gameinfo(" 分数", score);
  183. return 0;
  184. }
  185. void pntSnake(int i)
  186. {
  187. //转换x坐标:内部是连续整数,打印时一个字符占位2,所以要2x
  188. pos.X = snake[i].x * 2;
  189. pos.Y = snake[i].y;
  190. SetConsoleCursorPosition(hOut, pos);
  191. if (snake[i].num == 0){
  192. putchar('\0'); //清除蛇尾
  193. putchar('\0');}
  194. else if (snake[i].num == 1){
  195. //下面函数第二个参数低4位控制前景色,高4位控制背景色,共8位
  196. SetConsoleTextAttribute(hOut, snake[i].col);
  197. printf("█");
  198. }
  199. }
  200. void drawEdge(void)
  201. {
  202. int i;
  203. for (i=0; i<W; i++){
  204. pos.X = i*2; pos.Y = 0;
  205. SetConsoleCursorPosition(hOut, pos);
  206. printf("█");
  207. gamemap[i][pos.Y] = 3;
  208. pos.Y = H-1;
  209. SetConsoleCursorPosition(hOut, pos);
  210. printf("█");
  211. gamemap[i][H-1] = 3;
  212. }
  213. for (i=1; i<H-1; i++){
  214. pos.X = 0; pos.Y = i;
  215. SetConsoleCursorPosition(hOut, pos);
  216. printf("█");
  217. gamemap[pos.X][i] = 3;
  218. pos.X = (W-1)*2;
  219. SetConsoleCursorPosition(hOut, pos);
  220. printf("█");
  221. gamemap[W-1][i] = 3;
  222. }
  223. }
  224. void gameinfo(char *s, int n)
  225. {
  226. pos.X = 0; pos.Y = H;
  227. SetConsoleCursorPosition(hOut, pos);
  228. SetConsoleTextAttribute(hOut, 0x2f);
  229. printf(" 贪吃蛇");
  230. printf(" %s: %d", s, n);
  231. }
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:833828 发表于 2020-11-8 20:45 | 只看该作者
请问为什么我运行不了呢?(我就直接把代码复制进去了)
回复

使用道具 举报

板凳
ID:882731 发表于 2021-2-23 10:09 | 只看该作者
helloSCM 发表于 2020-11-8 20:45
请问为什么我运行不了呢?(我就直接把代码复制进去了)

这是整个程序实现贪食蛇功能还是要设计界面?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表