采用了双向链表结点来模拟蛇身结点;

  通过C语言光标控制函数来打印地图、蛇身和食物;

  1. /**************************
  2. ***************************
  3. 贪吃蛇游戏
  4. C语言数据结构
  5. 作者:Dew
  6. 时间:2019年3月23日
  7. 版本:1.0
  8. ***************************
  9. **************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <Windows.h>
  14. #include <conio.h>
  15.  
  16. #define N 30
  17. #define TRUE 1
  18. #define FALSE 0
  19. #define TIME 300
  20.  
  21. #define LEFT 37
  22. #define UP 38
  23. #define RIGHT 39
  24. #define DOWN 40
  25.  
  26. void initMap();
  27. void showGame();
  28. void initSnake();
  29. void control(int key);
  30. void updateSnake(int next_head_x, int next_head_y);
  31. void gotoxy(int x, int y); //光标控制
  32. void gameRun();
  33. void moveUp();
  34. void moveDown();
  35. void moveLeft();
  36. void moveRight();
  37. void createFood();
  38. void addSnakeNode(int cur_tail_x, int cur_tail_y);
  39. void crashTest(int head_x, int head_y);
  40.  
  41. struct snakeNode {
  42. int pos_x;
  43. int pos_y;
  44. snakeNode* pre;
  45. snakeNode* next;
  46. };
  47.  
  48. struct foodNode {
  49. int pos_x;
  50. int pos_y;
  51. };
  52.  
  53. int map[N][N];
  54. int keyPress;
  55. int key;
  56.  
  57. int next_head_x, next_head_y;
  58. int cur_tail_x, cur_tail_y;
  59.  
  60. snakeNode* snake_head = (snakeNode *)malloc(sizeof(snakeNode));
  61. snakeNode* snake_tail = (snakeNode *)malloc(sizeof(snakeNode));
  62.  
  63. foodNode* food = (foodNode *)malloc(sizeof(foodNode));
  64.  
  65. int main()
  66. {
  67. initSnake();
  68.  
  69. initMap();
  70.  
  71. gameRun();
  72.  
  73. return 0;
  74. }
  75.  
  76. void initMap()
  77. {
  78. int i, j;
  79. for(i = 0; i < N; i++)
  80. for (j = 0; j < N; j++)
  81. {
  82. if (i == 0 || i == N - 1)
  83. map[i][j] = 1;
  84. else if (j == 0 || j == N - 1)
  85. map[i][j] = 1;
  86. else
  87. map[i][j] = 0;
  88. }
  89. }
  90.  
  91. void showGame()
  92. {
  93. int i, j;
  94. for (i = 0; i < N; i++)
  95. {
  96. for (j = 0; j < N; j++)
  97. {
  98. if (map[i][j] == 1) {
  99. gotoxy(j*2, i);
  100. printf("□");
  101. }
  102. else if (map[i][j] == 0) {
  103. gotoxy(j*2, i);
  104. printf(" ");
  105. }
  106. }
  107. printf("\n");
  108. }
  109. gotoxy(snake_head->pos_y * 2, snake_head->pos_x);
  110. printf("●");
  111. gotoxy(snake_tail->pos_y * 2, snake_tail->pos_x);
  112. printf("●");
  113. gotoxy(food->pos_y * 2, food->pos_x);
  114. printf("◇");
  115. }
  116.  
  117. void initSnake()
  118. {
  119. snake_head->pos_x = 15;
  120. snake_head->pos_y = 15;
  121. snake_head->pre = NULL;
  122. snake_head->next = snake_tail;
  123.  
  124. snake_tail->pre = snake_head;
  125. snake_tail->pos_x = snake_tail->pre->pos_x + 1;
  126. snake_tail->pos_y = snake_tail->pre->pos_y;
  127. snake_tail->next = NULL;
  128.  
  129. food->pos_x = rand() % 28 + 1;
  130. food->pos_y = rand() % 28 + 1;
  131. }
  132.  
  133. void control(int direction)
  134. {
  135. if (direction == UP)
  136. {
  137. moveUp();
  138. }
  139. else if (direction == DOWN)
  140. {
  141. moveDown();
  142. }
  143. else if (direction == LEFT)
  144. {
  145. moveLeft();
  146. }
  147. else if (direction == RIGHT)
  148. {
  149. moveRight();
  150. }
  151.  
  152. }
  153.  
  154. void updateSnake(int next_head_x, int next_head_y)
  155. {
  156. snakeNode* p = snake_tail;
  157. while (p != snake_head)
  158. {
  159. p->pos_x = p->pre->pos_x;
  160. p->pos_y = p->pre->pos_y;
  161. p = p->pre;
  162. }
  163. p->pos_x = next_head_x;
  164. p->pos_y = next_head_y;
  165. }
  166.  
  167. void gotoxy(int x, int y)
  168. {
  169. COORD pos;
  170. HANDLE hOutput;
  171. pos.X = x;
  172. pos.Y = y;
  173. hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  174. SetConsoleCursorPosition(hOutput, pos);
  175. }
  176.  
  177. void gameRun()
  178. {
  179. showGame();
  180.  
  181. control(UP);
  182.  
  183. while (TRUE)
  184. {
  185. if (GetAsyncKeyState(VK_RIGHT))
  186. {
  187. control(RIGHT);
  188. Sleep(TIME);
  189. }
  190. else if (GetAsyncKeyState(VK_LEFT))
  191. {
  192. control(LEFT);
  193. Sleep(TIME);
  194. }
  195. else if (GetAsyncKeyState(VK_UP))
  196. {
  197. control(UP);
  198. Sleep(TIME);
  199. }
  200. else if (GetAsyncKeyState(VK_DOWN))
  201. {
  202. control(DOWN);
  203. Sleep(TIME);
  204. }
  205. }
  206. }
  207.  
  208. void moveUp()
  209. {
  210. while (TRUE)
  211. {
  212. next_head_x = snake_head->pos_x - 1;
  213. next_head_y = snake_head->pos_y;
  214. cur_tail_x = snake_tail->pos_x;
  215. cur_tail_y = snake_tail->pos_y;
  216. updateSnake(next_head_x, next_head_y);
  217. gotoxy(next_head_y * 2, next_head_x);
  218. printf("●");
  219. crashTest(next_head_x, next_head_y);
  220. if (next_head_x == food->pos_x && next_head_y == food->pos_y)
  221. {
  222. addSnakeNode(cur_tail_x, cur_tail_y);
  223. createFood();
  224. }
  225. else
  226. {
  227. gotoxy(cur_tail_y * 2, cur_tail_x);
  228. printf(" ");
  229. }
  230.  
  231. Sleep(TIME);
  232.  
  233. if (GetAsyncKeyState(VK_RIGHT))
  234. {
  235. control(RIGHT);
  236. Sleep(TIME);
  237. }
  238. else if (GetAsyncKeyState(VK_LEFT))
  239. {
  240. control(LEFT);
  241. Sleep(TIME);
  242. }
  243. else if (GetAsyncKeyState(VK_UP))
  244. {
  245. control(UP);
  246. Sleep(TIME);
  247. }
  248. else if (GetAsyncKeyState(VK_DOWN))
  249. {
  250. continue;
  251. }
  252.  
  253. }
  254. }
  255.  
  256. void moveDown()
  257. {
  258. while (TRUE)
  259. {
  260. next_head_x = snake_head->pos_x + 1;
  261. next_head_y = snake_head->pos_y;
  262. cur_tail_x = snake_tail->pos_x;
  263. cur_tail_y = snake_tail->pos_y;
  264. updateSnake(next_head_x, next_head_y);
  265. gotoxy(next_head_y * 2, next_head_x);
  266. printf("●");
  267. crashTest(next_head_x, next_head_y);
  268. if (next_head_x == food->pos_x && next_head_y == food->pos_y)
  269. {
  270. addSnakeNode(cur_tail_x, cur_tail_y);
  271. createFood();
  272. }
  273. else
  274. {
  275. gotoxy(cur_tail_y * 2, cur_tail_x);
  276. printf(" ");
  277. }
  278.  
  279. Sleep(TIME);
  280. if (GetAsyncKeyState(VK_RIGHT))
  281. {
  282. control(RIGHT);
  283. Sleep(TIME);
  284. }
  285. else if (GetAsyncKeyState(VK_LEFT))
  286. {
  287. control(LEFT);
  288. Sleep(TIME);
  289. }
  290. else if (GetAsyncKeyState(VK_UP))
  291. {
  292. continue;
  293. }
  294. else if (GetAsyncKeyState(VK_DOWN))
  295. {
  296. control(DOWN);
  297. Sleep(TIME);
  298. }
  299.  
  300. }
  301. }
  302.  
  303. void moveLeft()
  304. {
  305. while (TRUE)
  306. {
  307. next_head_x = snake_head->pos_x;
  308. next_head_y = snake_head->pos_y - 1;
  309. cur_tail_x = snake_tail->pos_x;
  310. cur_tail_y = snake_tail->pos_y;
  311. updateSnake(next_head_x, next_head_y);
  312. gotoxy(next_head_y * 2, next_head_x);
  313. printf("●");
  314. crashTest(next_head_x, next_head_y);
  315. if (next_head_x == food->pos_x && next_head_y == food->pos_y)
  316. {
  317. addSnakeNode(cur_tail_x, cur_tail_y);
  318. createFood();
  319. }
  320. else
  321. {
  322. gotoxy(cur_tail_y * 2, cur_tail_x);
  323. printf(" ");
  324. }
  325.  
  326. Sleep(TIME);
  327. if (GetAsyncKeyState(VK_RIGHT))
  328. {
  329. continue;
  330. }
  331. else if (GetAsyncKeyState(VK_LEFT))
  332. {
  333. control(LEFT);
  334. Sleep(TIME);
  335. }
  336. else if (GetAsyncKeyState(VK_UP))
  337. {
  338. control(UP);
  339. Sleep(TIME);
  340. }
  341. else if (GetAsyncKeyState(VK_DOWN))
  342. {
  343. control(DOWN);
  344. Sleep(TIME);
  345. }
  346.  
  347. }
  348. }
  349.  
  350. void moveRight()
  351. {
  352. while (TRUE)
  353. {
  354. next_head_x = snake_head->pos_x;
  355. next_head_y = snake_head->pos_y + 1;
  356. cur_tail_x = snake_tail->pos_x;
  357. cur_tail_y = snake_tail->pos_y;
  358. updateSnake(next_head_x, next_head_y);
  359. gotoxy(next_head_y * 2, next_head_x);
  360. printf("●");
  361. crashTest(next_head_x, next_head_y);
  362. if (next_head_x == food->pos_x && next_head_y == food->pos_y)
  363. {
  364. addSnakeNode(cur_tail_x, cur_tail_y);
  365. createFood();
  366. }
  367. else
  368. {
  369. gotoxy(cur_tail_y * 2, cur_tail_x);
  370. printf(" ");
  371. }
  372.  
  373. Sleep(TIME);
  374. if (GetAsyncKeyState(VK_RIGHT))
  375. {
  376. control(RIGHT);
  377. Sleep(TIME);
  378. }
  379. else if (GetAsyncKeyState(VK_LEFT))
  380. {
  381. continue;
  382. }
  383. else if (GetAsyncKeyState(VK_UP))
  384. {
  385. control(UP);
  386. Sleep(TIME);
  387. }
  388. else if (GetAsyncKeyState(VK_DOWN))
  389. {
  390. control(DOWN);
  391. Sleep(TIME);
  392. }
  393.  
  394. }
  395. }
  396.  
  397. void createFood()
  398. {
  399. food->pos_x = rand() % 28 + 1;
  400. food->pos_y = rand() % 28 + 1;
  401. gotoxy(food->pos_y * 2, food->pos_x);
  402. printf("◇");
  403. }
  404.  
  405. void addSnakeNode(int cur_tail_x, int cur_tail_y)
  406. {
  407. snakeNode* tempNode = (snakeNode *)malloc(sizeof(snakeNode));
  408. tempNode->pos_x = cur_tail_x;
  409. tempNode->pos_y = cur_tail_y;
  410. tempNode->next = NULL;
  411. snake_tail->next = tempNode;
  412. tempNode->pre = snake_tail;
  413. snake_tail = tempNode;
  414. }
  415.  
  416. void crashTest(int head_x, int head_y)
  417. {
  418. snakeNode* p = snake_head->next;
  419. while (p != NULL)
  420. {
  421. if (p->pos_x == head_x && p->pos_y == head_y)
  422. {
  423. gotoxy(32 * 2, 15);
  424. printf("...发生撞击!......游戏结束...");
  425. getchar();
  426. }
  427. if (p->pos_x == 1 || p->pos_x == N - 2 || p->pos_y == 1 || p->pos_y == N - 2)
  428. {
  429. gotoxy(32 * 2, 15);
  430. printf("...发生撞击!......游戏结束...");
  431. getchar();
  432. }
  433. p = p->next;
  434. }
  435. }

贪吃蛇游戏——C语言双向链表实现的更多相关文章

  1. 基于EasyX库的贪吃蛇游戏——C语言实现

    接触编程有段时间了,一直想学习怎么去写个游戏来练练手.在看了B站上的教学终于可以自己试试怎么实现贪吃蛇这个游戏了.好了,废话不多说,我们来看看如何用EasyX库来实现贪吃蛇. 一.准备 工具vc++6 ...

  2. 贪吃蛇游戏C语言源代码学习

    源代码下载地址为:www.clang.cc 阅读学习了源代码,并做了简单的注释和修改,里面只用了链表数据结构,非常适合C语言入门者学习阅读. 程序可在VS2013下编译运行. #include< ...

  3. 【C语言项目】贪吃蛇游戏(上)

    目录 00. 目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) 3.5 欢迎界面函 ...

  4. 贪吃蛇游戏(printf输出C语言版本)

    这一次我们应用printf输出实现一个经典的小游戏—贪吃蛇,主要难点是小蛇数据如何存储.如何实现转弯的效果.吃到食物后如何增加长度. 1 构造小蛇 首先,在画面中显示一条静止的小蛇.二维数组canva ...

  5. 使用Love2D引擎开发贪吃蛇游戏

    今天来介绍博主近期捣腾的一个小游戏[贪吃蛇],贪吃蛇这个游戏相信大家都不会感到陌生吧.今天博主将通过Love2D这款游戏引擎来为大家实现一个简单的贪吃蛇游戏,在本篇文章其中我们将会涉及到贪吃蛇的基本算 ...

  6. Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录

    一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...

  7. 用C++实现的贪吃蛇游戏

    我是一个C++初学者,控制台实现了一个贪吃蛇游戏. 代码如下: //"贪吃蛇游戏"V1.0 //李国良于2016年12月29日编写完成 #include <iostream& ...

  8. WebGL实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  9. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

随机推荐

  1. .NET core2.0 发布至IIS中

    .NET CORE和asp.net 发布时不太一样,ASP.NET Core不再是由IIS工作进程(w3wp.exe)托管,而是使用自托管Web服务器(Kestrel)运行,IIS则是作为反向代理的角 ...

  2. 安装WebLogic失败,出现”[VALIDATION] [ERROR]:INST-07004: Oracle 主目录(O) 位置包含一个或多个无效字符“解决方案

    题如图 解决方案: 在管理员cmd窗口定位到jdk bin目录,然后输入以下命令 java -jar F:\java\fmw_12.2.1.3.0_wls_quick_Disk1_1of1\fmw_1 ...

  3. OSI模型网络七层协议

    物理层 物理层是OSI的第一层,它虽然处于最底层,却是整个开放系统的基础.物理层为设备之间的数据通信提供传输媒体及互连设备,为数据传输提供可靠的环境. 1.1媒体和互连设备 物理层的媒体包括架空明线. ...

  4. Neutron路由篇:L3 agent+Namespace

    Neutron 的路由服务是由 l3 agent 提供的. 除此之外,l3 agent 通过 iptables 提供 firewall 和 floating ip 服务.     l3 agent 需 ...

  5. JavaScript加载次序问题

    3个文件,一个index.html如下 <!DOCTYPE html> <html> <head> <meta charset="UTF-8&quo ...

  6. [转帖]Qemu 简述

    Qemu 简述 记得KVM 就是 底层用的qemu https://www.cnblogs.com/bakari/p/7858029.html 本文首发于我的公众号 Linux云计算网络(id: cl ...

  7. js 解决两值交换

    总结七种办法来交换a和b的变量值 交换变量值方案一 最最最简单的办法就是使用一个临时变量了 不过使用临时变量的方法实在是太low了 var t; t = a; a = b; b = t;   首先把a ...

  8. servlet(4)异常处理

    一.异常处理 当一个 Servlet 抛出一个异常时,处理异常的servlet可以从HttpServletRequest里面得到几个属性,如下: 1.javax.servlet.error.statu ...

  9. CF 1119C Ramesses and Corner Inversion

    https://codeforces.com/problemset/problem/1119/C 题目 给两个矩阵,只能选宽和高大于等于2的子矩阵左上.左下.右上.右下四点翻转(1->0,0-& ...

  10. python+ffmpeg切割视频

    什么是ffmpeg 1.1 简介 FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包 ...