• 贪吃蛇游戏代码(C语言项目)


    本篇仅提供C语言代码,详细讲解在这篇博客:C语言:贪吃蛇游戏(从0开始完整版)-CSDN博客

    1、运行演示

    QQ2024618-155655

    2、代码构成(vs编译器)

    3、C语言代码

    3.1 头文件Snake.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define POS_X 24
    9. #define POS_Y 5
    10. #define WALL L'□'
    11. #define BODY L'●'
    12. #define FOOD L'★'
    13. //类型的声明
    14. //蛇的方向
    15. enum DIRECTION
    16. {
    17. UP = 1,
    18. DOWN,
    19. LEFT,
    20. RIGHT
    21. };
    22. //蛇的状态
    23. //正常、撞墙、撞到自己、正常退出
    24. enum GAME_STATUS
    25. {
    26. OK, //正常
    27. KILL_BY_WALL, //撞墙
    28. KILL_BY_SELF, //撞到自己
    29. END_NORMAL //正常退出
    30. };
    31. //蛇身的节点类型
    32. typedef struct SnakeNode
    33. {
    34. //坐标
    35. int x;
    36. int y;
    37. //指向下一个节点的指针
    38. struct SnakeNode* next;
    39. }SnakeNode, * pSnakeNode;
    40. //贪吃蛇
    41. typedef struct Snake
    42. {
    43. pSnakeNode _pSnake;//指向蛇头的指针
    44. pSnakeNode _pFood;//指向食物节点的指针
    45. enum DIRECTION _dir;//蛇的方向
    46. enum GAME_STATUS _status;//游戏的状态
    47. int _food_weight;//一个食物的分数
    48. int _score; //总成绩
    49. int _sleep_time; //休息时间,时间越短,速度越快,时间越长,速度越慢
    50. }Snake, * pSnake;
    51. //函数的声明
    52. //
    53. //
    54. //定位光标位置
    55. void SetPos(int x, int y);
    56. //欢迎界面的打印
    57. void WelcomeToGame();
    58. //游戏的初始化
    59. void GameStart(pSnake ps);
    60. //创建地图
    61. void CreateMap();
    62. //初始化蛇身
    63. void InitSnake(pSnake ps);
    64. //创建食物
    65. void CreateFood(pSnake ps);
    66. //游戏运行的逻辑
    67. void GameRun(pSnake ps);
    68. //蛇的移动-走一步
    69. void SnakeMove(pSnake ps);
    70. //判断下一个坐标是否是食物
    71. int NextIsFood(pSnakeNode next, pSnake ps);
    72. //下一个位置是食物,就吃掉食物
    73. void EatFood(pSnakeNode next, pSnake ps);
    74. //下一个位置不是食物
    75. void NoFood(pSnakeNode next, pSnake ps);
    76. //检测蛇是否撞墙
    77. void KillByWall(pSnake ps);
    78. //检测蛇是否撞到自己
    79. void KillBySelf(pSnake ps);
    80. //游戏善后的工作
    81. void GameEnd(pSnake ps);

    3.2 Snake.c(游戏相关代码)

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include "snake.h"
    3. void SetPos(int x, int y)
    4. {
    5. HANDLE hOutput = NULL;
    6. //获取标准输出的句柄(⽤来标识不同设备的数值)
    7. hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    8. COORD pos = { x,y };
    9. SetConsoleCursorPosition(hOutput, pos);
    10. }
    11. void WelcomeToGame()
    12. {
    13. SetPos(40, 12);
    14. wprintf(L"欢迎来到贪吃蛇小游戏!");
    15. SetPos(43, 17);
    16. system("pause");
    17. system("cls");
    18. SetPos(25, 14);
    19. wprintf(L"用 ↑. ↓ . ← . → 来控制蛇的移动,按F3加速,F4减速\n");
    20. SetPos(40, 16);
    21. wprintf(L"加速能够得到更高的分数\n");
    22. SetPos(43, 20);
    23. system("pause");
    24. system("cls");
    25. }
    26. //●
    27. void CreateMap()
    28. {
    29. //上围墙
    30. for (int i = 0; i < 29; i++)
    31. {
    32. wprintf(L"%c", WALL);
    33. }
    34. //下围墙
    35. SetPos(0, 26);
    36. for (int i = 0; i < 29; i++)
    37. {
    38. wprintf(L"%c", WALL);
    39. }
    40. //左围墙
    41. for (int i = 1; i < 26; i++)
    42. {
    43. SetPos(0, i);
    44. wprintf(L"%c", WALL);
    45. }
    46. //右围墙
    47. {
    48. for (int i = 1; i < 26; i++)
    49. {
    50. SetPos(56, i);
    51. wprintf(L"%c", WALL);
    52. }
    53. }
    54. }
    55. #include
    56. //初始化蛇身
    57. void InitSnake(pSnake ps)
    58. {
    59. pSnakeNode cur = NULL;
    60. for (int i = 0; i < 5; i++)
    61. {
    62. cur = (pSnakeNode)malloc(sizeof(SnakeNode));
    63. if (cur == NULL)
    64. {
    65. perror("InitSnake::malloc() fail\n");
    66. return;
    67. }
    68. cur->x = POS_X + i * 2;
    69. cur->y = POS_Y;
    70. cur->next = NULL;
    71. if (ps->_pSnake == NULL)
    72. {
    73. ps->_pSnake = cur;
    74. }
    75. else
    76. {
    77. cur->next = ps->_pSnake;
    78. ps->_pSnake = cur;
    79. }
    80. }
    81. cur = ps->_pSnake;
    82. while (cur)
    83. {
    84. SetPos(cur->x, cur->y);
    85. wprintf(L"%lc", BODY);
    86. cur = cur->next;
    87. }
    88. //设置贪吃蛇的属性
    89. ps->_dir = RIGHT;//默认向右
    90. ps->_score = 0;
    91. ps->_food_weight = 10;
    92. ps->_sleep_time = 200;//单位是毫秒
    93. ps->_status = OK;
    94. }
    95. //创建食物
    96. void CreateFood(pSnake ps)
    97. {
    98. #if 1
    99. int x = 0;
    100. int y = 0;
    101. again:
    102. do
    103. {
    104. x = rand() % 53 + 2;//2~54
    105. y = rand() % 25 + 1;//1~25
    106. } while (x % 2 != 0);//只能为2的倍数
    107. pSnakeNode cur = ps->_pSnake;
    108. while (cur)
    109. {
    110. //不能和蛇身的坐标重合
    111. if (cur->x == x && cur->y == y)
    112. {
    113. goto again;
    114. }
    115. cur = cur->next;
    116. }
    117. pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
    118. if (pFood == NULL)
    119. {
    120. perror("CreateFood()::malloc()");
    121. return;
    122. }
    123. pFood->x = x;
    124. pFood->y = y;
    125. pFood->next = NULL;
    126. SetPos(x, y);
    127. wprintf(L"%lc", FOOD);
    128. ps->_pFood = pFood;
    129. #endif
    130. }
    131. void GameStart(pSnake ps)
    132. {
    133. system("mode con cols=100 lines=30");
    134. system("title 贪吃蛇");
    135. HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
    136. //隐藏光标操作
    137. CONSOLE_CURSOR_INFO CursorInfo;
    138. GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
    139. CursorInfo.bVisible = false; //隐藏控制台光标
    140. SetConsoleCursorInfo(houtput, &CursorInfo);//设置控制台光标状态
    141. WelcomeToGame();
    142. CreateMap();
    143. InitSnake(ps);
    144. CreateFood(ps);
    145. }
    146. void HelpInfor(pSnake ps)
    147. {
    148. SetPos(60, 12);
    149. printf("不能穿墙,不能咬伤自己");
    150. SetPos(60, 13);
    151. printf("用 ↑. ↓ . ← . → 来控制蛇的移动");
    152. SetPos(60, 14);
    153. printf("按F3加速,F4减速");
    154. SetPos(60, 15);
    155. printf("ESC:退出游戏 space:暂停游戏");
    156. SetPos(60, 18);
    157. printf("由用户 小丁爱养花 制作");
    158. }
    159. //最⾼位是1,说明按键的状态是按下,
    160. // 如果最⾼是0,说明按键的状态是抬起
    161. #define KeyPress(VK) (GetAsyncKeyState(VK)&1)
    162. void Pause()
    163. {
    164. while (1)
    165. {
    166. Sleep(200);
    167. if (KeyPress(VK_SPACE))
    168. {
    169. break;
    170. }
    171. }
    172. }
    173. //判断下一个坐标是否是食物
    174. int NextIsFood(pSnakeNode next, pSnake ps)
    175. {
    176. if (next->x == ps->_pFood->x && next->y == ps->_pFood->y)
    177. {
    178. return 1;
    179. }
    180. else
    181. {
    182. return 0;
    183. }
    184. }
    185. //下一个位置是食物,就吃掉食物
    186. void EatFood(pSnakeNode next, pSnake ps)
    187. {
    188. ps->_pFood->next = ps->_pSnake;
    189. ps->_pSnake = ps->_pFood;
    190. free(next);
    191. next = NULL;
    192. pSnakeNode cur = ps->_pSnake;
    193. while (cur)
    194. {
    195. SetPos(cur->x, cur->y);
    196. wprintf(L"%lc", BODY);
    197. cur = cur->next;
    198. }
    199. ps->_score += ps->_food_weight;
    200. CreateFood(ps);
    201. }
    202. //下一个位置不是食物
    203. void NoFood(pSnakeNode next, pSnake ps)
    204. {
    205. next->next = ps->_pSnake;
    206. ps->_pSnake = next;
    207. pSnakeNode cur = ps->_pSnake;
    208. pSnakeNode prev = NULL;
    209. while (cur->next != NULL)
    210. {
    211. prev = cur;
    212. SetPos(cur->x, cur->y);
    213. wprintf(L"%lc", BODY);
    214. cur = cur->next;
    215. }
    216. SetPos(cur->x, cur->y);
    217. wprintf(L" ");
    218. if (prev)
    219. {
    220. prev->next = NULL;
    221. }
    222. free(cur);
    223. cur = NULL;
    224. }
    225. //检测蛇是否撞墙
    226. void KillByWall(pSnake ps)
    227. {
    228. if (ps->_pSnake->x <= 1|| ps->_pSnake->x >= 56
    229. || ps->_pSnake->y <= 0|| ps->_pSnake->y >= 26)
    230. {
    231. ps->_status = KILL_BY_WALL;
    232. }
    233. }
    234. //检测蛇是否撞到自己
    235. void KillBySelf(pSnake ps)
    236. {
    237. pSnakeNode body = ps->_pSnake->next;
    238. while (body)
    239. {
    240. if (ps->_pSnake->x == body->x && ps->_pSnake->y == body->y)
    241. {
    242. ps->_status = KILL_BY_SELF;
    243. break;
    244. }
    245. body = body->next;
    246. }
    247. }
    248. //蛇的移动-走一步
    249. void SnakeMove(pSnake ps)
    250. {
    251. pSnakeNode next = (pSnakeNode)malloc(sizeof(SnakeNode));
    252. if (next == NULL)
    253. {
    254. perror("CreateFood()::malloc()");
    255. return;
    256. }
    257. next->next = NULL;
    258. if (ps->_dir == UP)
    259. {
    260. next->x = ps->_pSnake->x;
    261. next->y = ps->_pSnake->y - 1;
    262. }
    263. else if (ps->_dir == DOWN)
    264. {
    265. next->x = ps->_pSnake->x;
    266. next->y = ps->_pSnake->y + 1;
    267. }
    268. else if (ps->_dir == LEFT)
    269. {
    270. next->x = ps->_pSnake->x - 2;
    271. next->y = ps->_pSnake->y;
    272. }
    273. else if (ps->_dir == RIGHT)
    274. {
    275. next->x = ps->_pSnake->x + 2;
    276. next->y = ps->_pSnake->y;
    277. }
    278. if (NextIsFood(next, ps))
    279. {
    280. EatFood(next, ps);
    281. }
    282. else
    283. {
    284. NoFood(next, ps);
    285. }
    286. //检测蛇是否撞墙
    287. KillByWall(ps);
    288. //检测蛇是否撞到自己
    289. KillBySelf(ps);
    290. }
    291. //游戏运行的逻辑
    292. void GameRun(pSnake ps)
    293. {
    294. HelpInfor(ps);
    295. do
    296. {
    297. SetPos(60, 7);
    298. printf("得分:%d 每个食物得分:%d", ps->_score, ps->_food_weight);
    299. if (KeyPress(VK_UP) && ps->_dir != DOWN)
    300. {
    301. ps->_dir = UP;
    302. }
    303. else if (KeyPress(VK_DOWN) && ps->_dir != UP)
    304. {
    305. ps->_dir = DOWN;
    306. }
    307. else if (KeyPress(VK_LEFT) && ps->_dir != RIGHT)
    308. {
    309. ps->_dir = LEFT;
    310. }
    311. else if (KeyPress(VK_RIGHT) && ps->_dir != LEFT)
    312. {
    313. ps->_dir = RIGHT;
    314. }
    315. else if (KeyPress(VK_SPACE))
    316. {
    317. Pause();
    318. }
    319. else if (KeyPress(VK_ESCAPE))
    320. {
    321. ps->_status = END_NORMAL;
    322. }
    323. else if (KeyPress(VK_F3))
    324. {
    325. if (ps->_sleep_time > 80)
    326. {
    327. ps->_sleep_time -= 30;
    328. ps->_food_weight += 2;
    329. }
    330. }
    331. else if (KeyPress(VK_F4))
    332. {
    333. if (ps->_food_weight > 2)
    334. {
    335. ps->_sleep_time += 30;
    336. ps->_food_weight -= 2;
    337. }
    338. }
    339. SnakeMove(ps);
    340. Sleep(ps->_sleep_time);
    341. } while (ps->_status == OK);
    342. }
    343. //游戏善后的工作
    344. void GameEnd(pSnake ps)
    345. {
    346. SetPos(24, 12);
    347. switch(ps->_status)
    348. {
    349. case KILL_BY_WALL:
    350. wprintf(L"!!!您撞上墙壁了,游戏结束!!!");
    351. break;
    352. case KILL_BY_SELF:
    353. wprintf(L"!!!您撞上自己了,游戏结束!!!");
    354. break;
    355. case END_NORMAL:
    356. wprintf(L"!!!您主动退出游戏,游戏结束!!!");
    357. break;
    358. }
    359. pSnakeNode cur = ps->_pSnake;
    360. pSnakeNode prev = NULL;
    361. while (cur)
    362. {
    363. prev = cur;
    364. cur = cur->next;
    365. free(prev);
    366. }
    367. prev = cur = NULL;
    368. }

    3.3 test.c(运行相关代码)

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include "snake.h"
    3. //
    4. void TestSnack()
    5. {
    6. //char ch = '\0';
    7. int ch = 0;
    8. do {
    9. system("cls");
    10. Snake snake = { 0 };
    11. GameStart(&snake);
    12. GameRun(&snake);
    13. GameEnd(&snake);
    14. SetPos(20, 15);
    15. printf("是否开始新的一局游戏?Y/N:");
    16. ch = getchar();
    17. //while (getchar() != '\n');
    18. while (getchar() != '\n');
    19. system("cls");
    20. } while (ch == 'y' || ch == 'Y');
    21. SetPos(5, 26);
    22. }
    23. int main()
    24. {
    25. setlocale(LC_ALL, "");
    26. srand((unsigned int)time(NULL));
    27. TestSnack();
    28. return 0;
    29. }

  • 相关阅读:
    数据结构手写算法整理(考研)
    Day26:内部类的详解
    11 Python 进程与线程编程
    Python学习记录 面向对象编程
    spring boot 将配置文件信息 赋值到类注解
    Metabase学习教程:提问-5
    好用的 JS 脚本
    【算法训练-二分查找 三】【特殊二分】寻找峰值
    【附源码】计算机毕业设计java圆梦酒店管理系统设计与实现
    用 Python 自动生成数据日报!
  • 原文地址:https://blog.csdn.net/2401_83595513/article/details/139776410