当前位置:   article > 正文

C语言游戏项目——贪吃蛇游戏_c语言写游戏需要用到的知识点

c语言写游戏需要用到的知识点
  • 贪吃蛇游戏所需要运用到的知识

  • 贪吃蛇游戏创建界面

  • 贪吃蛇游戏框架基本函数

  • 贪吃蛇游戏总代码


    因为本人在编写贪吃蛇的时候会用到easyX,所以建议读者可以先了解一些EasyX,这样能够帮助你对本篇文章的理解。

1.贪吃蛇需要的知识

结构体,枚举,函数,在进行游戏界面的创建的时候会用到C++的图形绘制easyX,因为贪吃蛇的控制是在键盘上来实现控制的,所以还需要引用头文件<conio.h>(当然这个头文件也是在easyX中的)。所以基本上就是需要结构体,函数,数组这些知识。

 2.贪吃蛇游戏界面的创建

虽然我们平时在写代码观看代码的运行的时候,会出现一个黑色的程序框,但是用easyX除了会保留原有的黑色程序框之外,还会在创建一个新的程序框,原有的黑色程序框可以方便我们后期对游戏数据进行观察。

  1. #include <stdio.h>
  2. #include <graphics.h>//
  3. #define WIDE 500 // 创建界面的长
  4. #define HEIGHT 300 //创建界面的宽
  5. #define MAX 400 //表示贪吃蛇最大节数为400
  6. int main()
  7. {
  8. //这个函数用来创建一个新的程序框,也就是游戏窗口。
  9. initgraph(WIDE,HEIGHT,SHOWCONSOLE)
  10. //SHOWCONSOLE 表示所创建的程序窗口是正常的,存在最小化和关闭功能
  11. //NOCLOSE 表示所创建的程序窗口是没有关闭功能的,没有完全通过游戏是不让进行关闭的
  12. //NOMINIMIZE 表示所创建的程序窗口是没有最小化功能。
  13. while(1)
  14. {
  15. }//之所以要这个,是因为如果没有的话所创建的程序窗口会一闪而过。
  16. closegrapg();//这个函数的作用是关闭上面所创建的程序窗口,创建窗口总是需要关闭的,不然它会一直存在那里
  17. return 0;
  18. }

这样在程序运行的时候除了会出现原有的黑色控制台窗口,还会再出现一个长为500,宽为300的游戏窗口。

3.贪吃蛇游戏基本函数

1,创建贪吃蛇的基本属性——初始移动方向,初始长度,初始移动速度,初始节数所对应的坐标。利用结构体来将这些数据都弄在一起。

  1. //创建贪吃蛇的数据
  2. struct Snake
  3. {
  4. int length;//贪吃蛇的长度
  5. int speed;//贪吃蛇的移动速度
  6. int dir;//贪吃蛇的初始移动方向
  7. POINT pos[MAX];//贪吃蛇的初始出现坐标
  8. //POINT 用来定义一个结构体变量,这里用来定义pos,使pos能存下每节圆的圆心位置。
  9. };

2,初始化游戏数据

当然这里只是来初始化贪吃蛇的初始化数据,还没有对食物的基本数据进行初始化。

  1. //进行游戏开始的数据初始化
  2. void initgame()
  3. {
  4. snake.length = 3;//初始长度
  5. snake.speed = 8;//初始移动速度
  6. snake.dir = RIGHT;//初始移动方向
  7. for (int i = 0; i < snake.length; i++)//这里是来定位贪吃蛇每节圆的圆心位置
  8. {
  9. snake.pos[i].x = 40 - 10 * i;
  10. snake.pos[i].y = 10;
  11. }
  12. }

3,初步绘画出游戏的基本界面

  1. //进行游戏绘画界面
  2. void gamedrw()
  3. {
  4. //建立双缓冲区绘画界面,这样可以使贪吃蛇在移动的过程中避免了游戏界面出现闪屏显现
  5. BeginBatchDraw();
  6. setbkcolor(RGB(180, 173, 160));//设置背景颜色
  7. //如果没有这个函数,那么就没办法显示出来设置的背景颜色
  8. cleardevice();//背景刷新
  9. //来定位贪吃蛇开始的身体部位坐标
  10. for (int k = 0; k < snake.length; k++)
  11. {
  12. setfillcolor(RED);//设置绘画贪吃蛇身体圆的填充颜色
  13. //solidcircle 绘制出没有边框的圆
  14. solidcircle(snake.pos[k].x, snake.pos[k].y, 5);//绘制贪吃蛇的雏形
  15. }
  16. FlashBatchDraw();
  17. }

当程序在的运行的时候就会出现这样的界面。这样就设计好了基本的游戏游戏界面。

 4,游戏界面设计好了后就需要实现贪吃蛇的移动

首先,需要明确怎样来实现贪吃蛇的移动,也就是让上面界面的三个圆实现移动。通过上面的绘画贪吃蛇大体结构,我们是通过定位每个圆的圆心位置来绘制图形的,那么实现贪吃蛇的移动就可以理解为让后面的一个圆的圆心来去取代前一个圆的圆心位置然后在进行绘制图形,这样就实现了贪吃蛇的移动。

开始写贪吃蛇移动函数之前,先来定义一个枚举,来列出来贪吃蛇的移动方向。

  1. enum Move
  2. {
  3. UP,
  4. DOWN,
  5. LEFT,
  6. RIGHT,
  7. };

然后就是来实现贪吃蛇的移动方向。

  1. void snakemove()
  2. {
  3. //从尾部开始向前替代来实现贪吃蛇的人性化移动
  4. for (int i = snake.length - 1; i > 0; i--)
  5. {
  6. snake.pos[i] = snake.pos[i - 1];
  7. }//让后面的一个圆的来代替前一个圆的位置,这样就可以来实现贪吃蛇的移动。
  8. // 这里i 之所以不包括 0,是因为通过只改变第一个圆的位置,然后就让后面的圆来取代前一个圆的原来的位置就好了。
  9. switch (snake.dir)
  10. {
  11. case UP:
  12. snake.pos[0].y -= snake.speed;
  13. //设置贪吃蛇能穿墙
  14. if (snake.pos[0].y - 5 < 0)
  15. {
  16. snake.pos[0].y = HEIGHT;
  17. }
  18. break;
  19. case DOWN:
  20. snake.pos[0].y += snake.speed;
  21. if (snake.pos[0].y + 5 > HEIGHT)
  22. {
  23. snake.pos[0].y = 0;
  24. }
  25. break;
  26. case LEFT:
  27. snake.pos[0].x -= snake.speed;
  28. if (snake.pos[0].x - 5 < 0)
  29. {
  30. snake.pos[0].x = WIDE;
  31. }
  32. break;
  33. case RIGHT:
  34. snake.pos[0].x += snake.speed;
  35. if (snake.pos[0].x + 5 > WIDE)
  36. {
  37. snake.pos[0].x = 0;
  38. }
  39. break;
  40. default:
  41. break;
  42. }
  43. }

5,利用键盘来控制贪吃蛇的移动

利用键盘来控制贪吃蛇的移动的话首先就是需要知道上下左右这几个键值,上:72,‘w’,‘W’。下:80,‘s’,‘S’。左:75,‘a’,‘A’。右:77,‘d’,‘D’。然后就是需要引用头文件<conio.h>(这个头文件是easyX中的,用来实现键盘控制),_getch();键盘消息函数,用来获取键盘按键信息。

  1. void keycontrol()
  2. {
  3. if (_kbhit())//阻塞函数,来判断是否从键盘输入信息,当没有从键盘上输入方向信息的时候
  4. //贪吃蛇会保持原有的方向继续移动,当接收到方向信息的时候就会改变方向。
  5. {
  6. userkey = _getch();//设置一个char型的变量来接收从键盘上输入的方向信息
  7. switch (userkey)
  8. {
  9. case 72:
  10. case 'w':
  11. case 'W':
  12. //防止贪吃蛇出现反方向移动
  13. if (snake.dir != DOWN)
  14. snake.dir = UP;
  15. break;
  16. case 80:
  17. case 's':
  18. case 'S':
  19. if (snake.dir != UP)
  20. snake.dir = DOWN;
  21. break;
  22. case 75:
  23. case 'a':
  24. case 'A':
  25. if(snake.dir != RIGHT)
  26. snake.dir = LEFT;
  27. break;
  28. case 77:
  29. case 'd':
  30. case 'D':
  31. if(snake.dir != LEFT)
  32. snake.dir = RIGHT;
  33. break;
  34. default:
  35. break;
  36. }
  37. }
  38. }

6,设置好food的数据变量,然后实现贪吃蛇移动吃食物

首先,食物所需要的数据变量为(这里让生成一个圆来代替食物):圆心坐标位置,圆的半径。判断食物是否还存在,当不存在的时候那就再次随机位置重新生成一个新的圆。

那么就同样的用结构体来将这些数据变量包括在一起。

  1. struct Food
  2. {
  3. int x;//确定食物的坐标
  4. int y;
  5. int r;//确定食物的半径
  6. bool flag;//确定是否食物被吃掉
  7. };

当然相对的就是同样需要来给这些变量初始化数据。

  1. food.x = rand() % WIDE;
  2. food.y = rand() % HEIGHT;
  3. food.r = returnround();//随机生成圆的半径。当半径大的时候可以让得分更大一些,这些都是可以来设置的
  4. food.flag = true;

returnround();函数就是来随机生成圆的半径长度。

  1. int returnround()
  2. {
  3. //八分之一的概率生成半径为10的圆
  4. if (rand() % 8 == 0)
  5. {
  6. return 10;
  7. }
  8. else
  9. return 5;
  10. }

这些都设置好的话,当程序运行的时候就会出现这样的。

 7,实现贪吃蛇吃掉食物

吃掉食物第一的想法应该会是当蛇头的圆心跟食物的圆心重合时候就让蛇的长度加1,但是在一个平面上让两个点重合难度有点大,而且也不是太现实。所以可这样来想,当两个圆心的相对位置小于两点间的距离的话就当贪吃蛇吃掉食物了,那这样的话就简单多了。

  1. void eatfood()
  2. {
  3. if (food.flag&&snake.pos[0].x >= food.x - food.r&&snake.pos[0].x <= food.x + food.r
  4. &&snake.pos[0].y >= food.y - food.r&&snake.pos[0].y <= food.y + food.r)
  5. {
  6. food.flag = false;
  7. snake.length++;
  8. }
  9. //当食物被吃掉的时候就重新生成一个新的食物位置,以来实现游戏的继续。
  10. if (!food.flag)
  11. {
  12. food.x = rand() % WIDE;
  13. food.y = rand() % HEIGHT;
  14. food.r = returnround();
  15. food.flag = true;
  16. }
  17. }

这样贪吃蛇就基本上弄成功了,当然,你也可以加上得分,进行进一步的优化代码,让游戏设计的更加的完美。

贪吃蛇游戏总代码

  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <time.h>
  4. #include <math.h>
  5. #include <stdlib.h>
  6. #include <graphics.h>
  7. #include <Windows.h>
  8. #include <mmsystem.h>//包含多媒体设备头文件
  9. #pragma comment(lib,"winmm.lib")//加载静态库
  10. #define WIDE 500
  11. #define HEIGHT 300
  12. #define MAX 400
  13. //设置蛇的结构
  14. struct Snake
  15. {
  16. int length;//设定长度
  17. int speed;//蛇的速度
  18. int dir;//蛇的方向
  19. POINT pos[MAX];
  20. }snake;
  21. enum DIR//蛇的方向
  22. {
  23. UP,
  24. DOWN,
  25. LEFT,
  26. RIGHT,
  27. };
  28. struct Food
  29. {
  30. //画一个圆来代替食物
  31. int x;
  32. int y;
  33. int r;
  34. bool flag;
  35. }food;
  36. int returnround()
  37. {
  38. if (rand() % 10 == 0)
  39. {
  40. return 10;
  41. }
  42. else
  43. {
  44. return 5;
  45. }
  46. }
  47. void initgame()
  48. {
  49. snake.length = 3;//蛇的初始长度
  50. snake.dir = RIGHT;//蛇的初始方向
  51. snake.speed = 8;//蛇的初始速度
  52. //初始化每个蛇身圆的位置
  53. for (int i = 0; i < snake.length; i++)
  54. {
  55. snake.pos[i].x = 40 - 10 * i;
  56. snake.pos[i].y = 10;
  57. }
  58. food.x = rand() % WIDE;
  59. food.y = rand() % HEIGHT;
  60. food.r = returnround();
  61. food.flag = true;
  62. }
  63. void gamedrw()
  64. {
  65. srand((unsigned int)time(NULL));
  66. //双缓冲区绘制
  67. BeginBatchDraw();
  68. //设置背景颜色
  69. setbkcolor(RGB(187, 173, 160));
  70. cleardevice();
  71. //画初始化的蛇
  72. for (int i = 0; i < snake.length; i++)
  73. {
  74. setfillcolor(RED);
  75. solidcircle(snake.pos[i].x, snake.pos[i].y, 5);
  76. }
  77. setfillcolor(BLACK);
  78. solidcircle(food.x, food.y, food.r);
  79. FlushBatchDraw();
  80. }
  81. void snakemove()
  82. {
  83. //从尾部开始,进行向前坐标取代
  84. for (int i = snake.length-1; i >0; i--)
  85. {
  86. snake.pos[i] = snake.pos[i - 1];
  87. }
  88. switch (snake.dir)
  89. {
  90. case RIGHT:
  91. //实现贪吃蛇的移动
  92. snake.pos[0].x+= snake.speed;
  93. //实现贪吃蛇的穿墙
  94. if (snake.pos[0].x + 5 > WIDE)
  95. {
  96. snake.pos[0].x = 0;
  97. }
  98. break;
  99. case LEFT:
  100. snake.pos[0].x-= snake.speed;
  101. if (snake.pos[0].x + 5 < 0)
  102. {
  103. snake.pos[0].x = WIDE;
  104. }
  105. break;
  106. case UP:
  107. snake.pos[0].y-= snake.speed;
  108. if (snake.pos[0].y + 5 < 0)
  109. {
  110. snake.pos[0].y = HEIGHT;
  111. }
  112. break;
  113. case DOWN:
  114. snake.pos[0].y+= snake.speed;
  115. if (snake.pos[0].y + 5 > HEIGHT)
  116. {
  117. snake.pos[0].y = 0;
  118. }
  119. break;
  120. default:
  121. break;
  122. }
  123. }
  124. void keycontrol()
  125. {
  126. //检测有没有按键,有按键就返回真
  127. if (_kbhit())
  128. {
  129. //接收键盘传来的按键
  130. switch (_getch())
  131. {
  132. case 'w':
  133. case 'W':
  134. case 72:
  135. if(snake.dir != DOWN)
  136. snake.dir = UP;
  137. break;
  138. case 's':
  139. case 'S':
  140. case 80:
  141. if(snake.dir != UP)
  142. snake.dir = DOWN;
  143. break;
  144. case 'a':
  145. case 'A':
  146. case 75:
  147. if(snake.dir != RIGHT)
  148. snake.dir = LEFT;
  149. break;
  150. case 'd':
  151. case 'D':
  152. case 77:
  153. if(snake.dir != LEFT)
  154. snake.dir = RIGHT;
  155. break;
  156. default:
  157. break;
  158. }
  159. }
  160. }
  161. void eatfood()
  162. {
  163. if (food.flag && snake.pos[0].x>=food.x-food.r&&snake.pos[0].x<=food.x+food.r
  164. &&snake.pos[0].y>=food.y-food.r&&snake.pos[0].y<=food.y+food.r)
  165. {
  166. food.flag = false;
  167. snake.length++;
  168. }
  169. if (!food.flag)
  170. {
  171. food.x = rand() % WIDE;
  172. food.y = rand() % HEIGHT;
  173. food.r = returnround();
  174. food.flag = true;
  175. }
  176. }
  177. int main()
  178. {
  179. //播放BGM
  180. //给多媒体设备发送一个字符串 alias表示命名为 bgm
  181. mciSendString("open ./BGM.map3 alias bgm", 0, 0, 0);
  182. mciSendString("play bgm repeat", 0, 0, 0);
  183. initgraph(WIDE, HEIGHT, SHOWCONSOLE);
  184. initgame();
  185. gamedrw();
  186. while (1)
  187. {
  188. gamedrw();
  189. snakemove();
  190. keycontrol();
  191. eatfood();
  192. Sleep(200);
  193. }
  194. closegraph();
  195. return 0;
  196. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/372538
推荐阅读
相关标签
  

闽ICP备14008679号