使用C语言实现经典贪吃蛇游戏

打印 上一主题 下一主题

主题 1707|帖子 1707|积分 5121

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一、项目概述

我们的目的是创建一个根本的贪吃蛇游戏,它具有以下功能:
蛇能够根据玩家的键盘输入改变方向。
当蛇吃到食物时,蛇的长度增长,同时分数增长。
蛇可以在窗口边缘“穿墙”移动。
游戏界面包括一个蛇和一个随机出现的食物。
支持游戏暂停功能。

二、情况配置

为了实现这个项目,我们需要准备以下开发工具:

  • Visual Studio Code 或其他任何C/C++ IDE。
  • Turbo C++ 或者安装了相应库的当代IDE,由于代码中使用了graphics.h,该头文件通常与Turbo C++一起使用。
  • MinGW 或者其他编译器,用来编译C代码。
注意:graphics.h库不是标准C库的一部门,在某些当代情况中大概不可用。如果不能使用graphics.h,可以思量使用如SDL、OpenGL等其他图形库来替换。
三、代码详解

1. 数据布局定义

首先,定义了两个布局体:snake 和 Food。其中snake包含蛇的位置信息和方向等属性;Food则表现食物的位置和颜色等信息。
  1. struct snake {
  2.         int size;
  3.         int dir;
  4.         int speed;
  5.         POINT coor[SNAKE_NUM];
  6. };
  7. struct Food {
  8.         int score;
  9.         int x;
  10.         int y;
  11.         int r;
  12.         bool flag;
  13.         DWORD color;
  14. };
复制代码
2. 初始化游戏

初始化函数GameInit()负责设置游戏的根本参数,如图形窗口的大小、蛇的初始位置和速度等。
  1. void GameInit() {
  2.         initgraph(640, 480, SHOWCONSOLE);
  3.         srand(GetTickCount());
  4.         snake.size = 3;
  5.         snake.speed = 10;
  6.         snake.dir = RIGHT;
  7.         ...
  8. }
复制代码
3. 绘制游戏画面

GameDraw()函数负责绘制当前的游戏状态,包括配景色、蛇和食物的位置。
  1. void GameDraw() {
  2.         BeginBatchDraw();
  3.         setbkcolor(RGB(28, 115, 119));
  4.         cleardevice();
  5.         // 绘制蛇和食物
  6.         ...
  7.         EndBatchDraw();
  8. }
复制代码
4. 控制蛇的移动

snakeMove()函数根据当前的方向更新蛇的位置,并实现了蛇穿过屏幕边缘的功能。
  1. void snakeMove() {
  2.         for (int i = snake.size - 1; i > 0; i--) {
  3.                 snake.coor[i] = snake.coor[i - 1];
  4.         }
  5.         switch (snake.dir) {
  6.                 case UP: ...
  7.                 case DOWN: ...
  8.                 case LEFT: ...
  9.                 case RIGHT: ...
  10.         }
  11. }
复制代码
5. 用户输入处置处罚

keyControl()函数监听键盘输入并改变蛇的方向。
  1. void keyControl() {
  2.         if (_kbhit()) {
  3.                 switch (_getch()) {
  4.                         case 'w': ...
  5.                         case 's': ...
  6.                         case 'a': ...
  7.                         case 'd': ...
  8.                         case ' ': // 暂停游戏
  9.                                 while (1) {
  10.                                         if (_getch() == ' ') return;
  11.                                 }
  12.                 }
  13.         }
  14. }
复制代码
6. 吃食物逻辑

Eatfood()函数查抄蛇是否吃到了食物,如果是,则增长蛇的长度和玩家的分数。
  1. void Eatfood() {
  2.         if (food.flag && ... && ...) {
  3.                 food.flag = false;
  4.                 snake.size++;
  5.         }
  6.         if (!food.flag) {
  7.                 food.x = rand() % 640;
  8.                 ...
  9.                 food.flag = true;
  10.         }
  11.         if (!food.flag) {
  12.                 food.score++;
  13.                 printf("得分: %d", food.score);
  14.         }
  15. }
复制代码
四、主循环

末了,在main()函数中创建了一个无限循环,用于不断更新游戏状态和渲染画面。
  1. int main() {
  2.         GameInit();
  3.         GameDraw();
  4.         while (1) {
  5.                 GameDraw();
  6.                 snakeMove();
  7.                 keyControl();
  8.                 Eatfood();
  9.                 Sleep(100);
  10.         }
  11.         return 0;
  12. }
复制代码
完整代码:

  1. #include<stdio.h>
  2. #include<graphics.h>
  3. #include<conio.h>
  4. #include<stdlib.h>
  5. #define SNAKE_NUM 500 //蛇的最大节数
  6. enum DIR //蛇的方向
  7. {
  8.         UP,
  9.         DOWN,
  10.         LEFT,
  11.         RIGHT,
  12. };
  13. //蛇的结构
  14. struct snake
  15. {
  16.         int size;//蛇的节数
  17.         int dir;//蛇的方向
  18.         int speed;//蛇的速度
  19.         POINT coor[SNAKE_NUM];//坐标
  20. }snake;
  21. //食物结构
  22. struct Food
  23. {
  24.         int score;
  25.         int x;
  26.         int y;
  27.         int r; //食物大小
  28.         bool flag;//食物是否被吃
  29.         DWORD color;
  30. }food;
  31. //数据初始化
  32. void GameInit()
  33. {                                                //显示控制台
  34.         initgraph(640, 480,SHOWCONSOLE);//图形窗口
  35.         //设置随机数种子
  36.         srand(GetTickCount());
  37.         //初始化蛇 一开始有三节
  38.         snake.size = 3;
  39.         snake.speed = 10;
  40.         snake.dir = RIGHT;
  41.         for (int i = 0; i < snake.size ; i++)
  42.         {
  43.                 snake.coor[i].x = 40-10*i;
  44.                 snake.coor[i].y = 10;
  45.         }
  46.         //初始化食物 rand()随机生产一个整数
  47.         //随机数种子需要头文件stdlib.h
  48.                 food.x = rand() % 640;
  49.                 food.y = rand() % 480;
  50.                 food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
  51.                 food.r = rand() % 10 + 5;
  52.                 food.flag = true;
  53. }
  54. void GameDraw()
  55. {
  56.         //双缓冲绘图
  57.         BeginBatchDraw();
  58.         setbkcolor(RGB(28, 115, 119));//设置背景颜色
  59.         cleardevice();
  60.         //绘制蛇
  61.         setfillcolor(YELLOW);
  62.         for (int i = 0; i < snake.size; i++)
  63.         {
  64.                 solidcircle(snake.coor[i].x, snake.coor[i].y, 5);
  65.         }
  66.         //绘制食物
  67.         if (food.flag)
  68.         {
  69.                 solidcircle(food.x, food.y, food.r);
  70.         }
  71.         EndBatchDraw();
  72. }
  73. //移动蛇
  74. void snakeMove()
  75. {
  76.         //移动即蛇头改变
  77.         //让身体跟随蛇头移动
  78.         for (int i = snake.size-1; i > 0; i--)
  79.         {
  80.                 snake.coor[i] = snake.coor[i - 1];
  81.         }
  82.                 switch (snake.dir)
  83.                 {
  84.                 case UP:
  85.                         snake.coor[0].y-=snake.speed;
  86.                         if (snake.coor[0].y + 10 <= 0)//超出上面的边界
  87.                         {
  88.                                 snake.coor[0].y = 480;
  89.                         }
  90.                         break;
  91.                 case DOWN:
  92.                         snake.coor[0].y+=snake.speed;
  93.                         if (snake.coor[0].y - 10 >= 480)
  94.                         {
  95.                                 snake.coor[0].y = 0;
  96.                         }
  97.                         break;
  98.                 case LEFT:
  99.                         snake.coor[0].x-=snake.speed;
  100.                         if (snake.coor[0].x + 10 <= 0)
  101.                         {
  102.                                 snake.coor[0].x = 640;
  103.                         }
  104.                         break;
  105.                 case RIGHT:
  106.                                 snake.coor[0].x+=snake.speed;
  107.                                 if (snake.coor[0].x - 10 >= 640)
  108.                                 {
  109.                                         snake.coor[0].x = 0;
  110.                                 }
  111.                                 break;
  112.                 }
  113.        
  114. }
  115. //通过按键改变蛇的方向
  116. void keyControl()
  117. {
  118.         //判断有没有按键,如果有按键就返回真
  119.         if (_kbhit())
  120.         {
  121.                 //72 80 75 77上下左右键值
  122.                 switch (_getch())
  123.                 {
  124.                 case 'w':
  125.                 case 'W':
  126.                 case 72:
  127.                         //改变方向
  128.                         if (snake.dir != DOWN)
  129.                         {
  130.                                 snake.dir = UP;
  131.                         }
  132.                         break;
  133.                 case 's':
  134.                 case 'S':
  135.                 case 80:
  136.                         if (snake.dir != UP)
  137.                         {
  138.                                 snake.dir = DOWN;
  139.                         }
  140.                         break;
  141.                 case 'a':
  142.                 case 'A':
  143.                 case 75:
  144.                         if (snake.dir !=RIGHT)
  145.                         {
  146.                                 snake.dir = LEFT;
  147.                         }
  148.                         break;
  149.                 case 'd':
  150.                 case 'D':
  151.                 case 77:
  152.                         if (snake.dir != LEFT)
  153.                         {
  154.                                 snake.dir = RIGHT;
  155.                         }
  156.                         break;
  157.                 case' '://游戏暂停逻辑
  158.                         while (1)
  159.                         {
  160.                                 if (_getch() == ' ')
  161.                                         return;
  162.                         }
  163.                         break;
  164.             }
  165.         }
  166. }
  167. void Eatfood()
  168. {                //判断食物是否存在
  169.         if (food.flag && snake.coor[0].x >=food.x-food.r && snake.coor[0].x<= food.x+food.r&&
  170.                 snake.coor[0].y>=food.y-food.r && snake.coor[0].y<=food.y+food.r)
  171.         {
  172.                 food.flag = false;
  173.                 snake.size++;
  174.         }//若食物消失,则重新生成
  175.         if (!food.flag)
  176.         {
  177.                 food.x = rand() % 640;
  178.                 food.y = rand() % 480;
  179.                 food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
  180.                 food.r = rand() % 10 + 5;
  181.                 food.flag = true;
  182.         }
  183.         //吃食物加分
  184.         if (!food.flag)
  185.         {
  186.                 food.score++;
  187.                 printf("得分:", food.score);
  188.         }
  189. }
  190. int main()
  191. {
  192.         GameInit();
  193.         GameDraw();
  194.         while (1)
  195.         {
  196.                 GameDraw();
  197.                 snakeMove();
  198.                 keyControl();
  199.                 Eatfood();
  200.                 Sleep(100);
  201.         }
  202.         return 0;
  203. }
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

不到断气不罢休

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表