【c语言】贪吃蛇

当我们不想学习新知识的时候,并且特别无聊,就会突然先看看别人怎么写游戏的,今天给大家分享的是贪吃蛇,所需要的知识有结构体,枚举,以及easy-x图形库的一些基本函数就完全够用了,本来我想插入游戏的音乐,但是没找到贪吃蛇的背景音乐,所以就没加,大家可以参考我之前的博文里面有如何加音乐的教程

包含的头文件

#include <stdio.h>
#include <graphics.h>//图形库头文件
#include <conio.h>//_kbhit()函数头文件
#include <stdlib.h>//srand函数头文件
#include <time.h>//time()函数头文件

初始化界面

int main()
{initgraph(640,480);//初始化界面while (1);return 0;}

初始化长640,宽480的界面,while(1);使得界面一直出现
在这里插入图片描述

设置背景颜色

int main()
{initgraph(640,480);setbkcolor(RGB(31, 29, 66));//设置背景颜色cleardevice();//清空绘图设备while (1);return 0;}

setbkcolor中的RGB(31, 29, 66),打开微信,同时按下Alt键,A,可获取你截图中颜色的RGB;
在这里插入图片描述

定义蛇的信息结构体,枚举定义蛇的方向

#define SNAKE_NUM 500// 最大有500节
struct Snake
{int size;//蛇的节数int dir;//蛇的方向int speed;//蛇的速度POINT coor[SNAKE_NUM];//蛇的坐标}snake;
enum DIR  //表示蛇的方向
{UP,//向上DOWN,//向下LEFT,//向左RIGHT,//向右
};

数据初始化

void gameinit()
{    snake.size = 3;//初始化蛇刚开始为三节snake.speed = 8;//初始速度是每按一次方向键改变八个像素的位置snake.dir = RIGHT;//初始蛇的方向是向右for (int i = 0; i < snake.size; i++){snake.coor[i].x = 40 - 10 * i;snake.coor[i].y = 10;}}

在for循环内定义好每一节的圆心坐标,记snake.coor[0].x为蛇头的圆心坐标的横坐标,记snake.coor[0].y为蛇头的圆心坐标的纵坐标,初始化三节,for循环定义这三节的坐标,头的圆心坐标为(40,10)中间为(30,10),最后为(20,10);初始化蛇应该是横着的。

整合函数

函数写的太乱,我们可以将相同的功能放在一个函数里面,比如说将initgraph(640, 480);放在gameinit()里面,将画的都放在gamedraw()函数里面。

//数据初始化
void gameinit()
{initgraph(640, 480);snake.size = 3;snake.speed = 8;snake.dir = RIGHT;for (int i = 0; i < snake.size; i++){snake.coor[i].x = 40 - 10 * i;snake.coor[i].y = 10;}}
void gamedraw()
{BeginBatchDraw();//双缓冲消除闪屏setbkcolor(RGB(31, 29, 66));//设置背景颜色cleardevice();//清空绘图设备//绘制蛇setfillcolor(RED);//设置蛇的颜色for (int i = 0; i < snake.size; i++){solidcircle(snake.coor[i].x, snake.coor[i].y, 5);//循环绘制蛇的三节身体}EndBatchDraw();//双缓冲消除闪屏}
int main()
{gameinit();gamedraw();while (1);return 0;}

在绘制蛇那里setfillcolor(RED);//设置蛇的颜色,在设置蛇的颜色下面的循环中是画初始化好的三节蛇的身体,solidcircle(snake.coor[i].x, snake.coor[i].y, 5);这个是画实心圆的函数,前两个参数为圆的横纵坐标,第三个参数是圆的半径
在这里插入图片描述

键盘控制移动方向

void keycontrol()
{//72 80 75 77if (_kbhit()){switch (_getch()){case 'w':case 'W':case 72:if (snake.dir != DOWN){snake.dir = UP;}break;case 's':case 'S':case 80:if (snake.dir != UP){snake.dir = DOWN;}break;case 'a':case 'A':case 75:if (snake.dir != RIGHT){snake.dir = LEFT;}break;case 'd':case 'D':case 77:if (snake.dir != LEFT){snake.dir = RIGHT;}break;}}}

_kbhit()是一个C和C++函数,用于非阻塞地响应键盘输入事件,即键盘敲击。它检查当前是否有键盘输入,如果有则返回一个非0值,否则返回0。
w,s,a,d对应的虚拟键值为72,80,75,77.当_kbhit()返回不为0,则有键按下,_getch 是 C 语言中常用的一个函数,它可以获取用户在控制台输入的一个字符,并且不需要回车。当按下方向键后,_getch()读取按下的字符,将蛇的方向改变成对应的方向键。为什么这里有条件判断语句if,是因为蛇在向一个方向走的时候不能直接往相反的方向走.比如说按下w,往上走,除了向下走外,向左走,和向右走的时候按向上走就可以向上走。

蛇的移动

void snakemove()
{for (int i = snake.size-1; i>0; i--)//身体跟着头移动{snake.coor[i] = snake.coor[i - 1];}switch (snake.dir)//头移动{case RIGHT:snake.coor[0].x+=snake.speed;if (snake.coor[0].x > 640){snake.coor[0].x = 0;}break;case UP:snake.coor[0].y-= snake.speed;if (snake.coor[0].y < 0){snake.coor[0].y = 480;}break;case DOWN:snake.coor[0].y+=snake.speed;if (snake.coor[0].y > 480){snake.coor[0].y = 0;}break;case LEFT:snake.coor[0].x-=snake.speed;if (snake.coor[0].x < 0){snake.coor[0].x = 640;}break;}}

每次调用snakemove函数,让后面每一节等于前面那一节的坐标,就能实现尾巴身体跟着头动,switch中是此时头移动的方向,向哪个方向移动,对应方向上的x坐标或者y坐标就+或者-snake.speed;比如说向左就是对应x-snake.speed,向右就是x+snake.speed;向上就是y-snake.speed;向下就是y+snake.speed;这里为什么有判断语句if,这里是因为当蛇头到达边界位置的话,就可以从相反的边界出来,界面的大小是640*480;比如说蛇向左走,遇到左边界,就把蛇头的x坐标置为640.

主函数变化

int main()
{gameinit();gamedraw();while (1){gamedraw();keycontrol();snakemove();Sleep(20);}return 0;}

将键盘控制函数和蛇的移动的函数放在while循环里面,因为要无时无刻地获取从键盘上读来地值和蛇的移动,当不加Sleep函数时,蛇跑的特别快,让程序休眠20ms
视频演示

20230921_173904

食物信息结构体定义

struct food
{int x;//食物的横坐标int y;//食物的纵坐标bool flag;//食物是否被吃int r;//食物半径DWORD color;//食物颜色}food;

食物信息初始化(修改数据初始化函数)

//数据初始化
void gameinit()
{    //设置随机数种子srand((unsigned int)time(NULL));//时间不断变化,initgraph(640, 480);//初始化界面snake.size = 3;snake.speed = 8;snake.dir=RIGHT;for (int i = 0;i<snake.size;i++){snake.coor[i].x = 40-10*i;snake.coor[i].y = 10;}//随机初始化食物的横纵坐标food.x = rand() % 640;food.y = rand() % 480;food.color = RGB(rand() % 256, rand() % 256, rand() % 256);food.r = rand() % 10 + 5;food.flag = true;}

因为食物的位置,颜色,以及食物的半径要随机生成,必须用到rand函数生成随机数,但rand生成的随机数是不变的,所以要通过srand函数生成随机数种子,食物必须在界面内,所以food.x=rand()%640的话,food.x的范围为0-639,同理food.y,以及RGB的三个参数都是0-255的,所以对256取余数,半径是在0-9之间,在加上5,食物半径就在5-14之间,food.flag 定义的是食物是否被吃掉,没被吃掉就为true,吃掉后food.flag变为false.

蛇吃食物

void eatfood()
{if (food.flag&&snake.coor[0].x>=food.x-food.r&&snake.coor[0].x<=food.x+food.r  && snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r){food.flag = false;snake.size++;}if (!food.flag)//食物消失重新生成一个{food.x = rand() % 640;food.y = rand() % 480;food.color = RGB(rand() % 256, rand() % 256, rand() % 256);food.r = rand() % 10 + 5;food.flag = true;}}

如果要吃掉食物用蛇头圆心的坐标等于食物圆心的坐标的话,是不容易吃到食物的,所以只要蛇头的圆心坐标落入以食物圆心做出的外切正方形的范围内的话,就算吃到,对应食物正方形的边界坐标为food.x-food.r(左边界),
food.x+food.r(右边界),food.y+food.r(上边界),food.y-food.r(下边界),只要蛇头圆心落入该范围内就算吃到,吃到的话,food.flag=false;表示食物被吃掉,并且蛇的长度snake.size++;当食物被吃掉后,food.flag=0,此时!food.flag=1;立即生成下一个食物坐标,如果这里判断蛇头是否落在食物范围内时,如果不加&&food.flag的话,蛇吃第一个食物,会由三节直接变成五节在这里插入图片描述

绘制食物(修改绘制函数)

void gamedraw()
{BeginBatchDraw();setbkcolor(RGB(31, 29, 66));//设置背景颜色cleardevice();//清空绘图设备//绘制蛇setfillcolor(RED);//设置蛇的颜色for (int i = 0; i < snake.size; i++){solidcircle(snake.coor[i].x, snake.coor[i].y, 5);}//绘制食物if (food.flag)//如果food.flag==1的话就绘制食物{solidcircle(food.x, food.y, food.r);}EndBatchDraw();}

主函数修改

int main()
{gameinit();gamedraw();while (1){gamedraw();keycontrol();snakemove();eatfood();//增加的Sleep(20);}return 0;}

游戏暂停函数

void gamestop()//空格,游戏暂停
{if (_kbhit()){if (_getch()== ' '){while (_getch() != ' ');}}}

按下空格游戏暂停,_kbhit函数作用上面解释过了,然后如果从键盘读取的空格后,缓冲区没东西,就在一直循环,在按一次就继续游戏,注意修改的主函数

修改主函数

int main()
{gameinit();gamedraw();while (1){gamestop();gamedraw();keycontrol();snakemove();eatfood();Sleep(20);}return 0;}

程序源码

#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#define SNAKE_NUM 500
enum DIR  //表示蛇的方向
{UP,DOWN,LEFT,RIGHT,
};
struct Snake//蛇结构体
{int size;//蛇的节数int dir;//蛇的方向int speed;//蛇的速度POINT coor[SNAKE_NUM];//节数}snake;
struct food//食物结构体
{int x;int y;bool flag;//食物是否被吃int r;//食物半径DWORD color;//食物颜色}food;
//数据初始化
void gameinit()
{initgraph(640, 480);snake.size = 3;snake.speed = 8;snake.dir = RIGHT;for (int i = 0; i < snake.size; i++){snake.coor[i].x = 40 - 10 * i;snake.coor[i].y = 10;}}
void gamestop()//空格,游戏暂停
{if (_kbhit()){if (_getch() == ' '){while (_getch() != ' ');}}}
void gamedraw()//画函数
{BeginBatchDraw();setbkcolor(RGB(31, 29, 66));//设置背景颜色cleardevice();//清空绘图设备//绘制蛇setfillcolor(RED);//设置蛇的颜色for (int i = 0; i < snake.size; i++){solidcircle(snake.coor[i].x, snake.coor[i].y, 5);}//绘制食物if (food.flag){solidcircle(food.x, food.y, food.r);}EndBatchDraw();}
void keycontrol()//键盘控制方向
{//72 80 75 77if (_kbhit()){switch (_getch()){case 'w':case 'W':case 72:if (snake.dir != DOWN){snake.dir = UP;}break;case 's':case 'S':case 80:if (snake.dir != UP){snake.dir = DOWN;}break;case 'a':case 'A':case 75:if (snake.dir != RIGHT){snake.dir = LEFT;}break;case 'd':case 'D':case 77:if (snake.dir != LEFT){snake.dir = RIGHT;}break;}}}
void snakemove()//蛇的移动
{for (int i = snake.size - 1; i > 0; i--)//身体跟着头移动{snake.coor[i] = snake.coor[i - 1];}switch (snake.dir)//头移动{case RIGHT:snake.coor[0].x += snake.speed;if (snake.coor[0].x > 640){snake.coor[0].x = 0;}break;case UP:snake.coor[0].y -= snake.speed;if (snake.coor[0].y < 0){snake.coor[0].y = 480;}break;case DOWN:snake.coor[0].y += snake.speed;if (snake.coor[0].y > 480){snake.coor[0].y = 0;}break;case LEFT:snake.coor[0].x -= snake.speed;if (snake.coor[0].x < 0){snake.coor[0].x = 640;}break;}}
void eatfood()//吃食物
{if (food.flag && snake.coor[0].x >= food.x - food.r && snake.coor[0].x <= food.x + food.r && snake.coor[0].y >= food.y - food.r && snake.coor[0].y <= food.y + food.r){food.flag = false;snake.size++;}if (!food.flag)//食物消失重新生成一个{food.x = rand() % 640;food.y = rand() % 480;food.color = RGB(rand() % 256, rand() % 256, rand() % 256);food.r = rand() % 10 + 5;food.flag = true;}}
int main()
{gameinit();gamedraw();while (1){gamestop();gamedraw();keycontrol();snakemove();eatfood();Sleep(20);}return 0;}

程序演示

20230921_184525

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

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

相关文章

创建一个简单的外卖订餐系统

在今天的快节奏生活中&#xff0c;外卖订餐系统已经成为了人们日常生活中不可或缺的一部分。这些系统通过在线点餐和配送服务&#xff0c;为用户提供了便捷的用餐体验。在本文中&#xff0c;我们将创建一个简单的外卖订餐系统&#xff0c;使用Python和Flask框架构建后端&#x…

Mac电脑系统怎么样才能干干净净地卸载应用程序?

Mac系统怎么样才能干干净净地卸载应用程序&#xff0c;不留下隐私数据和用户信息呢&#xff1f;如果有方法的话&#xff0c;那么该方法对于Mac电脑小白是否友好呢&#xff1f; CleanMyMac就是一款用于清理Mac系统下应用程序的一款清理工具&#xff0c;其内置了应用程序的安全卸…

轻松搞定Spring集成缓存,让你的应用程序飞起来!

Spring集成缓存 缓存接口开启注解缓存注解使用CacheableCachePutCacheEvictCachingCacheConfig 缓存存储使用 ConcurrentHashMap 作为缓存使用 Ehcache 作为缓存使用 Caffeine 作为缓存 主页传送门&#xff1a;&#x1f4c0; 传送 Spring 提供了对缓存的支持&#xff0c;允许你…

Spring MVC常见面试题

Spring MVC简介 Spring MVC框架是以请求为驱动&#xff0c;围绕Servlet设计&#xff0c;将请求发给控制器&#xff0c;然后通过模型对象&#xff0c;分派器来展示请求结果视图。简单来说&#xff0c;Spring MVC整合了前端请求的处理及响应。 Servlet 是运行在 Web 服务器或应用…

内存管理之虚拟内存

本篇遵循内存管理->地址空间->虚拟内存的顺序描述了内存管理、地址空间与虚拟内存见的递进关系&#xff0c;较为详细的介绍了作为在校大学生对于虚拟内存的理解。 内存管理 引入 RAM&#xff08;内存&#xff09;是计算机中非常重要的资源&#xff0c;由于造价的昂贵&…

Linux 用户和用户组

Linux中关于权限的管控级别有2个级别&#xff0c;分别是: 针对用户的权限控制 针对用户组的权限控制 比如&#xff0c;针对某文件&#xff0c;可以控制用户的权限,也可以控制用户组的权限。 1、用户组管理 1.1、创建用户组 groupadd 用户组名 1.2、删除用户组 groupdel 用户…

社交媒体商业禁令冲击:TikTok如何应对印尼政策变化?

随着社交媒体的普及和发展&#xff0c;各国政府开始越来越关注这一领域的监管和控制。印尼政府最近的决定&#xff0c;禁止在社交媒体上进行商品交易&#xff0c;引起了广泛的关注。 这一政策变化对TikTok等社交媒体平台带来了巨大的挑战&#xff0c;要求它们重新审视商业模式…

CFCA证书 申请 流程(一)

跳过科普&#xff0c;可直接进入申请&#x1f449;https://blog.csdn.net/Ximerr/article/details/133169391 CFCA证书 CFCA证书是指由中国金融认证中心颁发的证书&#xff0c;包括普通数字证书、服务器数字证书和预植证书等&#xff0c;目前&#xff0c;各大银行和金融机构都…

网站有反爬机制就爬不了数据?那是你不会【反】反爬

目录 前言 一、什么是代理IP 二、使用代理IP反反爬 1.获取代理IP 2.设置代理IP 3.验证代理IP 4.设置代理池 5.定时更新代理IP 三、反反爬案例 1.分析目标网站 2.爬取目标网站 四、总结 前言 爬虫技术的不断发展&#xff0c;使得许多网站都采取了反爬机制&#xff…

【深度学习】实验12 使用PyTorch训练模型

文章目录 使用PyTorch训练模型1. 线性回归类2. 创建数据集3. 训练模型4. 测试模型 附&#xff1a;系列文章 使用PyTorch训练模型 PyTorch是一个基于Python的科学计算库&#xff0c;它是一个开源的机器学习框架&#xff0c;由Facebook公司于2016年开源。它提供了构建动态计算图…

Linux 线程(thread)

进程线程区别 创建线程 #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); -功能&#xff1a;创建一个子线程&#xff0c;一般情况下main函数所在的线程称为主线程&#xff0c;…

21天学会C++:Day14----模板

CSDN的uu们&#xff0c;大家好。这里是C入门的第十四讲。 座右铭&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;C专题 目录 1. 知识引入 2. 模板的使用 2.1 函数模板 2.2 类模板 3. 模板声明和定义…

kubernetes(k8s)PVC

概念 PVC 的全称是&#xff1a;PersistentVolumeClaim&#xff08;持久化卷声明&#xff09;&#xff0c;PVC 是用户存储的一种声明&#xff0c;PVC 和 Pod 比较类似&#xff0c;Pod 消耗的是节点&#xff0c;PVC 消耗的是 PV 资源&#xff0c;Pod 可以请求 CPU 和内存&#x…

基于Kubernetes的Serverless PaaS稳定性建设万字总结

作者&#xff1a;许成铭&#xff08;竞霄&#xff09; 数字经济的今天&#xff0c;云计算俨然已经作为基础设施融入到人们的日常生活中&#xff0c;稳定性作为云产品的基本要求&#xff0c;研发人员的技术底线&#xff0c;其不仅仅是文档里承诺的几个九的 SLA 数字&#xff0c…

AI助手引领游戏创作革命

近期&#xff0c;Roblox 在其开发者大会&#xff08;RDC&#xff09;上宣布了一款新的对话式 AI 助手&#xff1a;RobloxAssistant。这款助手的本质是简化游戏制作难度&#xff0c;用自然语言代替编程。通过输入文字提示&#xff0c;创作者可以生成游戏场景、3D 模型等操作。该…

自动驾驶中的决策规划

参考: 【干货篇】轻舟智航&#xff1a;自动驾驶中的决策规划技术&#xff08;附视频回放 PPT 下载&#xff09; - AIQ 如图所示, 各模块介绍 定位模块主要负责解答的问题是“车现在在哪里”&#xff0c;是在道路上还是在路口&#xff0c;是在高架桥上还是在停车场里。 感知…

python随手小练

题目&#xff1a; 使用python做一个简单的英雄联盟商城登录界面 具体操作&#xff1a; print("英雄联盟商城登录界面") print("~ * "*15 "~") #找其规律 a "1、用户登录" b "2、新用户注册" c "3、退出系统&quo…

jq弹窗拖动改变宽高

预览效果 <div classtishiMask><div class"tishiEm"><div id"coor"></div><div class"topNew ismove"><span class"ismove">提示</span><p onclick"closeTishi()"></p&…

计算机组成原理——基础入门总结(二)

上一期的路径&#xff1a;基础入门总结&#xff08;一&#xff09; 目录 一.输入输出系统和IO控制方式 二.存储系统的基本概念 三.cache的基本概念和原理 四.CPU的功能和基本结构 五.总线概述 一.输入输出系统和IO控制方式 IO设备又可以被统一称为外部设备~ IO接口&…

Python 根据身高体重计算体质(BMI)指数

""" 根据身高体重计算体质(BMI)指数知识点&#xff1a;1、计算公式&#xff1a;体质指数(BMI) 体重(KG) / (身高(M) * 身高(M))2、变量类型转换3、运算符幂**&#xff0c;例如&#xff1a;3 ** 2 9 <> 3 * 34、更多的运用请参考&#xff1a;https://blo…