• C语言之实现贪吃蛇小游戏篇(2)


    目录

    🎇测试游戏test.c

    🎇游戏头文件包含&函数声明snake.h

    🎇游戏实现snake.c


    🎇测试游戏test.c

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include "snake.h"
    3. void test()
    4. {
    5. int ch = 0;
    6. do
    7. {
    8. Snake snake = { 0 };//创建了贪吃蛇
    9. //1. 游戏开始 - 初始化游戏
    10. GameStart(&snake);
    11. //2. 游戏运行 - 游戏的正常运行过程
    12. GameRun(&snake);
    13. //3. 游戏结束 - 游戏善后(释放资源)
    14. GameEnd(&snake);
    15. SetPos(20, 18);
    16. printf("再来一局吗?(Y/N):");
    17. ch = getchar();
    18. getchar();// 清理掉\n
    19. } while (ch == 'Y' || ch == 'y');
    20. SetPos(0, 27);
    21. }
    22. int main()
    23. {
    24. //设置程序适应本地环境
    25. setlocale(LC_ALL, "");
    26. srand((unsigned int)time(NULL));
    27. test();
    28. return 0;
    29. }

    🎇游戏头文件包含&函数声明snake.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #define WALL L'□'
    9. #define BODY L'●'
    10. #define FOOD L'★'
    11. #define POS_X 24
    12. #define POS_Y 5
    13. #define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )
    14. enum DIRECTION
    15. {
    16. UP = 1,
    17. DOWN,
    18. LEFT,
    19. RIGHT
    20. };
    21. enum GAME_STATUS
    22. {
    23. OK,//正常运行
    24. END_NORMAL,//按ESC退出
    25. KILL_BY_WALL,
    26. KILL_BY_SELF
    27. };
    28. //贪吃蛇结点的描述
    29. typedef struct SnakeNode
    30. {
    31. //坐标
    32. int x;
    33. int y;
    34. struct SnakeNode* next;
    35. }SnakeNode, * pSnakeNode;
    36. //贪吃蛇的结构
    37. typedef struct Snake
    38. {
    39. pSnakeNode _pSnake;//指向贪吃蛇头结点的指针
    40. pSnakeNode _pFood;//指向食物结点的指针
    41. int _Score;//贪吃蛇累计的总分
    42. int _FoodWeight;//一个食物的分数
    43. int _SleepTime;//每走一步休息的时间,时间越短,速度越快,时间越长,速度越慢
    44. enum DIRECTION _Dir;//描述蛇的方向
    45. enum GAME_STATUS _Status;//游戏的状态:正常、退出、撞墙、吃到自己
    46. }Snake, * pSnake;
    47. //游戏开始 - 完成游戏的初始化动作
    48. void GameStart(pSnake ps);
    49. //定位坐标
    50. void SetPos(short x, short y);
    51. //游戏开始的欢迎界面
    52. void WelComeToGame();
    53. //打印地图
    54. void CreateMap();
    55. //初始化贪吃蛇
    56. void InitSnake(pSnake ps);
    57. //创建食物
    58. void CreateFood(pSnake ps);
    59. //游戏的正常运行
    60. void GameRun(pSnake ps);
    61. //打印帮助信息
    62. void PrintHelpInfo();
    63. //游戏暂定和恢复
    64. void Pause();
    65. //蛇的移动
    66. void SnakeMove(pSnake ps);
    67. //判断蛇头到达的坐标处是否是食物
    68. int NextIsFood(pSnake ps, pSnakeNode pnext);
    69. //吃掉食物
    70. void EatFood(pSnake ps, pSnakeNode pnext);
    71. //不吃食物
    72. void NoFood(pSnake ps, pSnakeNode pnext);
    73. //蛇是否撞墙
    74. void KillByWall(pSnake ps);
    75. //蛇是否自杀
    76. void KillBySelf(pSnake ps);
    77. //游戏结束后的善后处理
    78. void GameEnd(pSnake ps);

    🎇游戏实现snake.c

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

    屏幕录制 2023-12-02 204515

     

    ✔✔✔✔✔最后感谢大家的阅读,若有错误和不足,欢迎指正!乖乖敲代码哦! 

    代码---------→【唐棣棣 (TSQXG) - Gitee.com

    联系---------→【邮箱:2784139418@qq.com】

  • 相关阅读:
    面试官随便问几个问题就知道你究竟做没做过微信支付宝支付
    JSON从入门到大师
    chatgpt赋能python:Python再次运行快捷键介绍及使用技巧
    使用ElementUI完成登入注册的跨域请求提高开发效率
    【LeetCode每日一题】——448.找到所有数组中消失的数字
    Python数据可视化的3大步骤,你知道吗?
    iOS开发 - 抛开表面看本质之iOS常用架构(MVC,MVP,MVVM)
    【1day】用友时空KSOA平台 任意文件上传漏洞学习
    Jammy@Jetson Orin - Tensorflow & Keras Get Started: Concept
    【Python】-- 异常(捕获指定异常、常见异常类型)
  • 原文地址:https://blog.csdn.net/m0_74841364/article/details/134757225