【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
相关文章:

【c语言】贪吃蛇
当我们不想学习新知识的时候,并且特别无聊,就会突然先看看别人怎么写游戏的,今天给大家分享的是贪吃蛇,所需要的知识有结构体,枚举,以及easy-x图形库的一些基本函数就完全够用了,本来我想插入游…...

【Node.js】定时任务cron:
文章目录 一、文档:【Nodejs 插件】 二、安装与使用【1】安装【2】使用 三、cron表达式:{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}四、案例: 一、文档: 【说明文档】https://www.npmjs.com/package/cron 【Cron表…...
vue3 引入element-plus
1.首先安装element-plus npm install element-plus 2.main.js配置 ... import ElementPlus from element-plus import element-plus/theme-chalk/index.css; //导入图标 import * as ELementPlusIconsVue from "element-plus/icons-vue" ... app.use(ElementPlus) /…...

数据通信——传输层TCP(超时时间选择)
引言 TCP每一次发送报文段,就会对这个报文段设置一次计时器。如果时间到了却没有收到确认报文,那么就要重传该报文。 这个之前在TCP传输的机制中提到过,这个章节就来研究一下超时时间问题。 关于加权的概念 有必要提及一下加权的概念&#x…...
【数据库索引优化】
文章目录 数据库索引优化1. 选择合适的字段创建索引2. 限值每张表上的索引数量3. 被频繁更新的字段应该慎重建立索引4. 尽可能考虑简历联合索引而不是单列索引5. 避免冗余索引6. 字符串类型的字段使用前缀索引代替普通索引7. 避免索引失效8. 删除长期未使用的索引 数据库索引优…...

WebGL 选中物体
目录 前言 如何实现选中物体 示例程序(PickObject.js) 代码详解 gl.readPixels()函数规范 示例效果 前言 有些三维应用程序需要允许用户能够交互地操纵三维物体,要这样做首先就得允许用户选中某个物体。对物体…...

科目二倒车入库
调整座位和后视镜 离合踩到底大腿小腿成130-140 上半身90-100 座椅高度能看到前方全部情况 后视镜调节到能看到后门把手,且后门把手刚好在后视镜上方边缘、离车1/3处。 保持直线: 前进: 车仪表盘中央的原点和地面上的黄线擦边ÿ…...

PostgreSQL如何支持PL/Python过程语言
瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台:Linux x86-64 Red Hat Enterprise Linux 7 版本:10.4 文档用途 本文档主要介绍PostgreSQL如何支持PL/Python过程语言,如何创建plpython扩展。 详细信息 一、PostgreSQL支持python语言…...

【C++】STL之适配器---用deque实现栈和队列
目录 前言 一、deque 1、deque 的原理介绍 2、deque 的底层结构 3、deque 的迭代器 4、deque 的优缺点 4.1、优点 4.2、缺点 二、stack 的介绍和使用 1、stack 的介绍 2、stack 的使用 3、stack 的模拟实现 三、queue 的介绍和使用 1、queue 的介绍 2、queue 的使用 3、qu…...

PHY6230低成本遥控灯控芯片国产蓝牙BLE5.2 2.4G SoC
高性价比的低功耗高性能蓝牙5.2系统级芯片,适用多种PC/手机外设连接场景。 高性能多模射频收发机: 通过硬件模块的充分复用实现高性能多模数字收发机。发射机,最大发射功率10dBm;BLE 1Mbps速率接收机灵敏度达到-96dBm࿱…...

OceanBase杨传辉传递亚运火炬:国产数据库为“智能亚运”提供稳稳支持
9 月 14 日,亚运火炬传递到了浙江台州,OceanBase 的 CTO 杨传辉作为火炬手交接了第 89 棒火炬。 2010 年,杨传辉作为创始成员之一参与自研原生分布式数据库 OceanBase。十年磨一剑,国产数据库 OceanBase 交出了一张优秀的成绩单&a…...
分布式锁实现方法
分布式锁 什么时候需要加锁 有并发,多线程有写操作有竞争关系 场景: 电商系统,下单流程:用户下单–>秒杀系统检查redis商品库存信息–>用户锁定并更新库存(mysql)—>秒杀系统更新redis 问题&…...

软件测试缺陷报告详解
【软件测试行业现状】2023年了你还敢学软件测试?未来已寄..测试人该何去何从?【自动化测试、测试开发、性能测试】 缺陷报告是描述软件缺陷现象和重现步骤地集合。软件缺陷报告Software Bug Report(SBR)或软件问题报告Software Pr…...
pytorch冻结参数训练的坑
由于项目需要训练一个主干网络接多个分支的模型,所以先训练一个主干网络加第一个分支,再用另外的数据训练第二个分支,训练的过程中需要冻结主干网络部分,后面的分支训练过程也一样需要冻结主干网络部分。 冻结模型的方式 for nam…...

P1827 [USACO3.4] 美国血统 American Heritage(前序 + 中序 生成后序)
P1827 [USACO3.4] 美国血统 American Heritage(前序 中序 生成后序) 一、前言 二叉树入门题。涉及到树的基本知识、树的结构、树的生成。 本文从会从结构,到完成到,优化。 二、基础知识 Ⅰ、二叉树的遍历 前序遍历ÿ…...
【四、centOS安装docker】
安装docker sudo yum install -y yum-utils device-mapper-persistent-data lvm2 如果以上报错 备份系统自带yum源配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup进入 /etc/yum.repos.d cd /etc/yum.repos.d删除文件 rm -f *.r…...

想学嵌入式开发,薪资怎么样?
想学嵌入式开发,薪资怎么样? 对于嵌入式工程师来说呢,它重点学习内容就是首先一定要打好基础,如果从编程语言角度来讲,那么可以在语言上选C或者C,你可以选择其中任何一门语言作为你的入门。 最近很多小伙伴…...

SQL死锁进程内容查询语句
1.方式1 SELECT object_name(A.resource_associated_entity_id) as TABLENAME, A.request_session_id AS SPID,DB_NAME(B.dbid) AS DBName,B.blocked,B.dbid,B.program_name,B.waitresource,B.lastwaittype,B.loginame,B.hostname,B.login_time,B.last_batch--,B.* FROM sy…...

Ubuntu 20.04中Nightingale二进制部署
参考博客《【夜莺监控】初识夜莺,强!》 lsb_release -r可以看到操作系统版本是20.04,uname -r可以看到内核版本是5.5.19。 sudo apt-get update进行更新镜像源。 完成之后,如下图: sudo apt-get upgrade更新软件…...
深入探讨Java面试中内存泄漏:如何识别、预防和解决
引言 在编写和维护Java应用程序时,内存泄漏是一个重要的问题,可能导致性能下降和不稳定性。本文将介绍内存泄漏的概念,为什么它在Java应用程序中如此重要,并明确本文的目标,即识别、预防和解决内存泄漏问题。 内存泄…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...

MeshGPT 笔记
[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭!_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...
raid存储技术
1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划,涵盖存储系统的布局、数据存储策略等,它明确数据如何存储、管理与访问,为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...
Electron简介(附电子书学习资料)
一、什么是Electron? Electron 是一个由 GitHub 开发的 开源框架,允许开发者使用 Web技术(HTML、CSS、JavaScript) 构建跨平台的桌面应用程序(Windows、macOS、Linux)。它将 Chromium浏览器内核 和 Node.j…...