c语言实现greedy snake(贪吃蛇)

2024-03-25 08:10

本文主要是介绍c语言实现greedy snake(贪吃蛇),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

##第一个小项目  大一学生寒假项目

最终实现效果如图

一.以C语言实现个人小项目

在我们快速学完了一个高级编程语言,就应该写一个小项目来加以巩固自己的学习成果。

所以今天,我们来尝试写一写greedy snake,对于大学生来说也是可以加强能力的存在。事不宜迟,我们开始吧。(Tips:我会加入一些外部链接,这些于编写遇到的问题有关,可以帮助你更好的解决)

外部文件的引入以及一些定义

#include <stdio.h>
#include <graphics.h> //与绘图文件有关
#include <conio.h>    //两个都需要
#include <stdlib.h>
#define SNAKE_NUM 500 //宏定义 规定好蛇的最大节数,以防溢出
enum DIR //枚举初始化方向
{UP,DOWN,LEFT,RIGHT,
};

解释:

我们在第四行引入的头文件是为了产生一个生成随机数的种子(所以我们引入了该头文件)

5函数名称: rand

函数原型: int rand(void);

函数功能: 产生0到32767间的随机整数(0到0x7fff之间)

函数返回: 随机整数

对于第二,第三行的头文件引入。

我在这里放好了它的下载官网,官网有下载说明,不复杂的

easyx文档 点击此处

二.蛇和食物的结构体定义

struct Snake
{int size; //蛇的长度int dir; //蛇的方向int speed; //蛇的速度POINT coor[SNAKE_NUM]; //坐标
}snake;struct food
{int x;int y;int r; //食物大小bool flag; //为后面判断食物是否被吃做准备DWORO color;  //规定食物的颜色
}food;

在这里,我们注意一下 POINT coor[] 是我们引入了相应的头文件,以有表示二维坐标的

函数。 后续创建实体的写法是---> snake[i].x = 坐标点 其中i是它的大小。

并且,这里的坐标轴与数学中的有些不同,y轴的正方向是朝下的,所以我们想让蛇向上移动最好是snake[i].y -= speed .这样蛇就是上移。

对于food(食物处),我们定义的x,y是为后续的随机坐标做好准备的。

三.数据的初始化

void GameInit()
{//init;初始化 graph 图形窗口initgraph(640,480);//设置随机数种子 GetTickCount 获取系统开机到当前运行所经过的时间srand(GetTickCount());//初始化蛇 一开始就有n节 n随你定义 这里我是3snake.size = 3;snake.speed = 5;snake.dir = RIGHT;//循环 这里是初始化蛇的位置 for (int i = 0; i < snake.size; i++) {snake.coor[i].x = 40 - 10*isnake.coor[i].y = 10;}//初始化食物,rand()是随机函数 来自头文件<stdlib.h>//一般把时间作为种子,时间在变化food.x = rand() % 640; // % n ---> 可以得到 0-(n-1)的数food.y = rand() % 480;food.color = RGB(rand() % 256, rand() % 256, rand() % 256);food.r = rand() % 10 + 5; //随机这个食物的半径 最小半径为5food.flag = true;
}

初始化的循环是为了 让蛇排列成行。 下标为0 是蛇头

四.图的绘制

void GameDraw()
{//双缓冲绘图 ---> 原因是会卡频//设置背景颜色setbkcolor(RGB(28,115,119)); //颜色可以按自己喜好的来cleardevice(); //清空绘图设备//绘制蛇setfillcolor(GREEN);for (int i = 0; i < snake.size; i++) {solidcircle(snake.coor[i].x,snake.coor[i].y, 5); //半径为5}//绘制食物if (food.flag){solidcircle(food.x, food.y, food.r);}EndBatchDraw();
}

1.头文件graphics.h包含cleardevice()函数,该函数在图形模式下清除屏幕并将当前位置设置为(0,0)。清除屏幕包括用当前背景色填充屏幕。

2.if条件判断是为了判断食物是否被吃 后刷新食物。

3.EndBatchDraw();---相关官方文档在这easyx文档

五.蛇的移动

//移动蛇
void snakemove()
{//移动是什么发生改变;坐标改变for (int i = snake.size; i > 0 ; i--){snake.coor[i] = snake.coor[i - 1];}//移动是什么发生改变switch (snake.dir){case UP:snake.coor[0].y-=snake.speed;if (snake.coor[0].y+10 <= 0) {snake.coor[0].y = 640;}//超出了上面的边界break;}switch (snake.dir){case DOWN:snake.coor[0].y+=snake.speed;if (snake.coor[0].y - 10 >= 640) {snake.coor[0].y = 0;}break;}switch (snake.dir){case LEFT:snake.coor[0].x-=snake.speed;if (snake.coor[0].x + 10 <= 0) {snake.coor[0].x = 640;}break;}switch (snake.dir){case RIGHT:snake.coor[0].x+=snake.speed;if (snake.coor[0].x - 10 >= 640) {snake.coor[0].x = 0;}break;}}

六.keyborad (键盘控制)

//通过按键操作
void keyControl()
{//判断有无按键if (_kbhit()) //检测是否有按键{//72 80 75 77 上下左右键值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() --->判断是否keyboard被按动 并返回bool值

_getch() ---> 获取按键信息

七.吃食物

void EatFood()
{if (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;}/*可以加一个分数,吃一个食物,加n分*/
}

TIPS:

这里的两个if判断语句

对于第一个if,是判定什么时候什么范围,蛇将这个食物给吃了  可以同过点到圆心的距离

即 d <= r(该圆半径)  (d为距离---为两个圆心的距离) 此时,两个圆相交便为吃了,否则,玩家的操作系数上升,不适宜游玩。

对于第二个if,是为了刷新被吃掉的食物。

八.游戏暂停

void stop()
{//判断是否键盘按动 和 是否为空格键if (_kbhit() && _getch() == ' '){while(1){if (_getch() == ' '){break;}}}
}

原理是:我们写一个死循环 while(1)---来占用进程,以达到暂停效果。 里面还有一个if判断是为了用户在按下一次的空格键下,打破循环,继续游戏。

二.主函数实现最终效果

int main()
{//在主函数调用,出现初始化结果GameInit();//防止闪退while(1) {GameDraw();snakemove();stop();keyControl();EatFood();Sleep(30); //防止太快移动,延迟}return 0;
}

注意,这里的stop()---游戏暂停函数一定要放到前面,否则会达不到暂停的效果。

在我们完成这些代码,F5调试时,可能有些人的蛇无法移动。

解决方案是:在shell(控制面板)来操控蛇的移动。就是那个黑框框。

也有不用在这个shell里面操作的方案,但是操作起来有些麻烦,所以还是用这个简单些的方案好一些。

最后我将这个project的源码放入,感兴趣的同学也可以通过这以上的代码自行输入,会有很多感悟。

谢谢。

这篇关于c语言实现greedy snake(贪吃蛇)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/844365

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja