C语言——实践小游戏(贪吃蛇)代码版

大家好久不见,我是残念我回来了,希望在你看完之后,能对你有所帮助,有什么不足请指正!共同学习交流
本文由:残念ing原创CSDN首发,如需要转载请通知
个人主页:残念ing-CSDN博客,欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:残念ing 的C语言系列专栏——CSDN博客

头文件和主函数的声明

snake.h

#pragma once#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<stdbool.h>
#include<locale.h>
#define WALL  L'■'
#define SNAKE L'●'
#define HEADSNAKE L'○'
#define FOOD L'★'
#define POS_X 24
#define POS_Y 5
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1)? 1:0)
//游戏状态
enum GAME_STATUS
{OK = 1,//正常运行ESC,//正常退出KILL_BY_WALL,//撞墙了KILL_BY_SELF//撞到自己了
};//⽅向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};//蛇身结点的定义
typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode,* pSnakeNode;//typedef struct SnakeNode* pSnakeNode;//蛇
typedef struct Snake
{pSnakeNode pSnake;//维护整条蛇的指针,指向蛇头pSnakeNode pFood;//指向食物的指针int Score;//当前累计的分数int FoodWeight;//一个食物的分数int SleepTime;//整条蛇的睡眠时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢enum GAME_STATUS status;//游戏当前的状态enum DIRECTION dir;//蛇当前走的方向
}Snake,* pSnake;//定位控制台光标位置
void setpos(int x, int y);
//游戏准备
void GameStart(pSnake ps);//打印欢迎界面
void WelcomeToGame();
//绘制地图
void CreateMap();
//初始化贪吃蛇
void InintSnake(pSnake ps);
//创建食物
void CreateFood(pSnake ps);//运行整个游戏的逻辑
void GameRun(pSnake ps);//玩游戏的过程//打印帮助信息
void printfHelpInfo();//每次的移动
void SnakeMove(pSnake ps);//判断蛇头下一步要走的位置是不是食物 是返回1,不是返回0;
int NextIsFood(pSnake ps, pSnakeNode pnext);//是食物就吃
void EatFood(pSnake ps, pSnakeNode pnext);
//不是食物
void NotEatFood(pSnake ps, pSnakeNode pnext);//检测撞墙
void KillByWall(pSnake ps);
//检测撞到自己
void KillBySelf(pSnake ps);//游戏结束的善后
void GameEnd(pSnake ps);//善后工作

主函数的详细实现

snake.c

#define _CRT_SECURE_NO_WARNINGS 1#include"snake.h"//将光标位置设置到指定的位置
void setpos(int x, int y)
{//获取句柄HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//设置光标的坐标COORD tmp = { x,y };SetConsoleCursorPosition(handle, tmp);
}void WelcomeToGame()
{setpos(40,10);printf("欢迎来到贪吃蛇小游戏!!!");setpos(43, 20);system("pause");//请按任意键继续进行下一步system("cls");//清屏setpos(10, 10);printf("请用 ↑	↓	←	→	分别来控制蛇的移动,SHIFT为加速,CTRL为减速");setpos(40, 12);printf("注意:加速将会使你得到更多分");setpos(43, 20);system("pause");//请按任意键继续进行下一步system("cls");//清屏
}//打印墙
void CreateMap()
{//上setpos(0, 0);for (int i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//下setpos(0, 26);for (int i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//左for (int i = 0; i <=25; i++){ setpos(0, i);wprintf(L"%lc", WALL);}//右for (int i = 0; i <=25; i++){setpos(56, i);wprintf(L"%lc", WALL);}}//初始化蛇
void InintSnake(pSnake ps)
{pSnakeNode cur=NULL;for (int i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InintSnake():malloc");return;}cur->x = POS_X +  2 * i;cur->y = POS_Y;cur->next = NULL;//头插if (ps->pSnake == NULL){ps->pSnake = cur;}else{cur->next = ps->pSnake;ps->pSnake = cur;}}//打印蛇cur = ps->pSnake;while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", SNAKE);cur = cur->next;}//贪吃蛇的基本属性初始化ps->dir = RIGHT;ps->FoodWeight = 10;ps->pFood = NULL;ps->Score = 0;ps->SleepTime = 200;ps->status = OK;
}//创建食物
void CreateFood(pSnake ps)
{int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);//坐标和蛇的身体的每个节点的做坐标比较pSnakeNode cur = ps->pSnake;while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}//创建食物pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->x = x;pFood->y = y;ps->pFood = pFood;setpos(x, y);wprintf(L"%lc", FOOD);}void GameStart(pSnake ps)
{//设置控制台的信息,窗口大小,窗口名system("mode con cols=100 lines=30");//设置窗口的长和宽system("title 贪吃蛇");//设置窗口名//隐藏关标HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false;//隐藏控制台光标SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标的状态//打印欢迎信息WelcomeToGame();//绘制地图CreateMap();//初始化蛇InintSnake(ps);//创建食物CreateFood(ps);
}void printfHelpInfo()
{setpos(63, 15);printf("注意:不能穿墙,不能咬到自己");setpos(63, 16);printf("用↑↓← →分别来控制蛇的移动");setpos(63, 17);printf("SHIFT为加速,CTRL为减速");setpos(63, 18);printf("Esc为退出游戏,space为暂停游戏");
}void pause()
{while (1){Sleep(100);if (KEY_PRESS(VK_SPACE)){break;}}
}int NextIsFood(pSnake ps, pSnakeNode pnext)
{if (ps->pFood->x == pnext->x && ps->pFood->y == pnext->y){return 1;}elsereturn 0;
}void EatFood(pSnake ps, pSnakeNode pnext)
{pnext->next = ps->pSnake;ps->pSnake = pnext;//打印蛇pSnakeNode cur = ps->pSnake;while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", SNAKE);cur = cur->next;}ps->Score += ps->FoodWeight;//释放旧的食物free(ps->pFood);//新建食物CreateFood(ps);
}void NotEatFood(pSnake ps, pSnakeNode pnext)
{//头插法pnext->next = ps->pSnake;ps->pSnake = pnext;//释放尾结点pSnakeNode cur = ps->pSnake;while (cur->next->next){setpos(cur->x, cur->y);wprintf(L"%lc", SNAKE);cur = cur->next;}//将尾节点的位置打印成空白字符setpos(cur->next->x, cur->next->y);printf("  ");free(cur->next);cur->next = NULL;//易错
}void KillByWall(pSnake ps)
{if (ps->pSnake->x == 0 || ps->pSnake->x == 56 || ps->pSnake->y == 0 || ps->pSnake->y == 26){ps->status = KILL_BY_WALL;}
}void KillBySelf(pSnake ps)
{pSnakeNode cur = ps->pSnake->next;while (cur){if (cur->x == ps->pSnake->x && cur->y == ps->pSnake->y){ps->status = KILL_BY_SELF; return;}cur = cur->next;}}void SnakeMove(pSnake ps)
{pSnakeNode pnext = (pSnakeNode)malloc(sizeof(SnakeNode));if (pnext == NULL){perror("SnakeMove()::malloc()");return;}pnext->next = NULL; switch (ps->dir){case UP:pnext->x = ps->pSnake->x;pnext->y = ps->pSnake->y - 1;break;case DOWN:pnext->x = ps->pSnake->x;pnext->y = ps->pSnake->y + 1;break;case LEFT:pnext->x = ps->pSnake->x - 2;pnext->y = ps->pSnake->y;break;case RIGHT:pnext->x = ps->pSnake->x + 2;pnext->y = ps->pSnake->y;break;}//下一个坐标是不是食物if (NextIsFood(ps, pnext)){//是食物就吃EatFood(ps, pnext);}else{//不是食物就走NotEatFood(ps, pnext);}//检测撞墙KillByWall(ps);//检测撞到自己KillBySelf(ps);
}void GameRun(pSnake ps)
{//打印帮助信息printfHelpInfo();//检测按键do{//当前的分数情况setpos(63,10);printf("总得分:%5d 每个食物: %02d",ps->Score,ps->FoodWeight);//检查按键// 上 下 左 右 ESC 空格 shift Ctrlif (KEY_PRESS(VK_UP) && ps->dir != DOWN){ps->dir = UP;}else if (KEY_PRESS(VK_DOWN) && ps->dir != UP){ps->dir = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT){ps->dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT){ps->dir = RIGHT;}else if (KEY_PRESS(VK_ESCAPE)){ps->status = ESC;break;}else if (KEY_PRESS(VK_SPACE)){//游戏要暂定pause();//暂定和回复暂定}else if(KEY_PRESS(VK_RSHIFT)){if (ps->SleepTime >= 80){ps->SleepTime -= 30;ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_RCONTROL)){if (ps->FoodWeight > 2){ps->SleepTime += 30;ps->FoodWeight -= 2;}}//睡眠一下Sleep(ps->SleepTime);//走一步SnakeMove(ps);} while (ps->status==OK);
}void GameEnd(pSnake ps)
{setpos(17, 15);switch (ps->status){case ESC:printf("退出游戏\n");break;case KILL_BY_WALL:printf("撞到墙了!!!!,游戏结束\n");break;case KILL_BY_SELF:printf("咬到自己了!!!!,游戏结束\n");break;}//释放贪吃蛇的链表资源pSnakeNode  cur = ps->pSnake;pSnakeNode del = NULL;while (cur){del = cur;cur = cur->next;free(del);}free(ps->pFood);ps = NULL;
}

关于代码的测试

snake_test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"
void test()
{int ret = 0;do{ret = 0;Snake snake = { 0 };GameStart(&snake);//游戏开始前的初始化GameRun(&snake);//玩游戏的过程GameEnd(&snake);//游戏的善后Sleep(800);system("cls");//清屏setpos(40, 15);printf("要再来一次吗???(Y/N)");ret=getchar();getchar();//清理\n} while (ret=='Y'||ret=='y');
}
int main()
{//修该适合本地中文环境setlocale(LC_ALL, "");test();//贪吃蛇的测试return 0;
}

这是详细代码,之后会给大家详细解答。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/809035.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从 Oracle 到 MySQL 数据库的迁移之旅

文章目录 引言一、前期准备工作1.搭建新的MySQL数据库2 .建立相应的数据表2.1 数据库兼容性分析2.1.1 字段类型兼容性分析2.1.2 函数兼容性分析2.1.3 是否使用存储过程&#xff1f;存储过程的个数&#xff1f;复杂度&#xff1f;2.1.4 是否使用触发器&#xff1f;个数&#xff…

Paper Reading: MixTeacher:半监督目标检测中利用混合尺度教师挖掘有前景的标签

目录 简介目标/动机工作重点方法训练 实验总结 简介 题目&#xff1a;《MixTeacher: Mining Promising Labels with Mixed Scale Teacher for Semi-Supervised Object Detection》&#xff0c; CVPR 2023 日期&#xff1a;2023.3.16 单位&#xff1a;腾讯&#xff0c;上海交…

竞赛 图像识别-人脸识别与疲劳检测 - python opencv

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是…

Android MVVM架构学习——ViewModel DataBinding

关于MVVM架构&#xff0c;我并不想花篇幅去做重复性的描述&#xff0c;网上一搜都是一堆讲解&#xff0c;大家可以自行了解&#xff0c;我所做的只是以最简单的例子&#xff0c;最有效的步骤&#xff0c;从零开始&#xff0c;去实现一个相对有点学习参考价值的项目。 先来看本…

计算机网络——NAT技术

目录 前言 前篇 引言 SNAT&#xff08;Source Network Address Translation&#xff09;源网络地址转换 SNAT流程 确定性标记 DNAT&#xff08;Destination Network Address Translation&#xff0c;目标网络地址转换&#xff09; NAT技术重要性 前言 本博客是博主用于…

无人新零售引领的创新浪潮

无人新零售引领的创新浪潮 在数字化时代加速演进的背景下&#xff0c;无人新零售作为商业领域的一股新兴力量&#xff0c;正以其独特的高效性和便捷性重塑着传统的购物模式&#xff0c;开辟了一条充满创新潜力的发展道路。 依托人脸识别、物联网等尖端技术&#xff0c;无人新…

Redis中的集群(七)

集群 ASK错误 ASKING命令 ASKING命令唯一要做的就是打开发送该命令的客户端的REDIS_ASKING标识&#xff0c;以下是该命令的伪代码实现: def ASKING(): # 打开标识 client.flags | REDIS_ASKING# 向客户端返回OK回复 reply("OK")在一般情况下&#xff0c;如果客户…

搜维尔科技:【煤矿安全仿真】煤矿事故预防处置VR系统,矿山顶板灾害,冲击地压灾害等预防演练!

产品概述 煤矿事故预防处置VR系统 系统内容&#xff1a; 事故预防处置VR系统的内容包括&#xff1a;火灾的预防措施、火灾预兆、防灭火系统、火灾案例重现、顶板事故预兆、顶板事故原因、顶板事故案例重现、瓦斯概念及性质、瓦斯的涌出形式、瓦斯预兆、瓦斯爆炸条件及预防措…

数据结构之排序了如指掌(一)

目录 题外话 正题 排序概念 稳定性 直接插入排序 直接插入排序代码详解 直接插入排序复杂度分析 希尔排序(缩小增量排序) 希尔排序代码详解 小结 题外话 昨晚肚子疼没睡好,今天博客写的确实有点晚(找个借口),我一定会坚持,不辜负热爱我的家人们!! 正题 排序概念 一串…

苍穹外卖jwt令牌p10

点击小虫&#xff08;进入断点调试&#xff09;&#xff0c;打上断点&#xff0c;然后前端点击登录&#xff08;此时前端的数据会作为参数传入&#xff09;&#xff1a; 光标放在字段上还会显示接收到的数据&#xff1a; 若想程序在所希望的地方停止&#xff0c;可以添加断点&a…

《战神4》和《战神5》有什么联系吗 苹果电脑如何运行《战神4》苹果电脑玩战神 Mac玩游戏 战神5攻略 crossover激活码

《战神4》&#xff08;God of War 2018&#xff09;和《战神5》&#xff08;God of War: Ragnark&#xff09;是一对引人注目的游戏作品&#xff0c;它们不仅在游戏界引起了广泛的关注&#xff0c;也给玩家带来了深入探索北欧神话世界的机会。这两部游戏之间的联系不仅体现在剧…

【力扣】101. 对称二叉树

101. 对称二叉树 题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示…

JavaWeb开发01--Maven-Web入门-请求响应-分层解耦

一、Maven 1.maven概述 Apache Maven是一个项目管理和构建工具&#xff0c;它基于项目对象模型(POM)的概念&#xff0c;通过一小段描述信息来管理项目的构建。 根据提供的插件实现很多功能 maven的作用 管理和构建java项目的工具 依赖管理&#xff1a;可以直接在pom.xml文件…

深入理解MD5算法:原理、应用与安全

title: 深入理解MD5算法&#xff1a;原理、应用与安全 date: 2024/4/11 20:55:57 updated: 2024/4/11 20:55:57 tags: MD5算法数据安全哈希函数摘要算法安全漏洞SHA算法密码学 第一章&#xff1a;引言 导言 在当今数字化时代&#xff0c;数据安全和完整性变得至关重要。消息…

【Leetcode每日一题】 动态规划 - 下降路径最小和(难度⭐⭐)(55)

1. 题目解析 题目链接&#xff1a;931. 下降路径最小和 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了. 2.算法原理 对于这类路径类问题&#xff0c;通常我们首先需要分析状态表示以及状态转移的过程。特别地&#xff0c;本题涉及…

The C programming language (second edition,KR) exercise(CHAPTER 3)

E x c e r c i s e 3 − 1 Excercise\quad 3-1 Excercise3−1&#xff1a;输出结果如图1所示&#xff0c;这里故意让二分搜索算法去寻找一个在数组中不存在在的数&#xff0c;然后去看两种二分搜索算法分别所花费的时间的大小&#xff0c;为了使得所花费的时间更具有可分辨性&a…

【HTML】制作一个简单的线性动画

目录 前言 HTML部分 CSS部分 JS部分 效果图 总结 前言 无需多言&#xff0c;本文将详细介绍一段HTML代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建一个文本文档&#xff0c;两个文件夹&#xff0c;其中HTML的文件名改为[index.html]&am…

面试经典算法系列之二叉树1 -- 从前序与中序遍历序列构造二叉树

面试经典算法16 - 从前序与中序遍历序列构造二叉树 LeetCode.105 公众号&#xff1a;阿Q技术站 问题描述 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根…

VUE typescript 调用stompjs[Rabbit MQ]

npm拉下来最新的2.3.9版本&#xff0c;发现一些原来Js代码已经不能用了。顺便解读了下最新定义的内容 // <reference types"node" />export const VERSIONS: {V1_0: string;V1_1: string;V1_2: string;supportedVersions: () > string[]; };export class C…

airtest-ios真机搭建实践

首先阅读4 ios connection - Airtest Project Docs 在Windows环境下搭建Airtest对iOS真机进行自动化测试的过程相对复杂&#xff0c;因为iOS的自动化测试通常需要依赖Mac OS系统&#xff0c;但理论上借助一些工具和服务&#xff0c;Windows用户也可以间接完成部分工作。下面是…