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

news2024/10/7 12:25:10

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

最终实现效果如图

一.以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随你定义 这里我是3
    snake.size = 3;
    snake.speed = 5;
    snake.dir = RIGHT;
    //循环 这里是初始化蛇的位置 
    for (int i = 0; i < snake.size; i++) {
        snake.coor[i].x = 40 - 10*i
        snake.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; //随机这个食物的半径 最小半径为5
    food.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的源码放入,感兴趣的同学也可以通过这以上的代码自行输入,会有很多感悟。

谢谢。

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

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

相关文章

超时引发的牛角尖二(hystrix中的超时)

至今我都清楚记得自己负责的系统请求云上关联系统时所报的异常信息。为了解决这个异常&#xff0c;我坚持让这个关联系统的负责人查看&#xff0c;并且毫不顾忌他的嘲讽和鄙视&#xff0c;甚至无视他烦躁的情绪。不过我还是高估了自己的脸皮&#xff0c;最终在其恶狠狠地抛下“…

每日一练:LeeCode-513、找树左下角的值【二叉树】

本文是力扣LeeCode-513、找树左下角的值 学习与理解过程&#xff0c;本文仅做学习之用&#xff0c;对本题感兴趣的小伙伴可以出门左拐LeeCode。 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: …

图数据库(neo4j)在工业控制中的应用

最近看到国外发表的一篇文章&#xff0c;提到将OPC UA 模型映射到neo4j图模型数据库中&#xff0c;通过GraphQL 访问效率很高&#xff0c;顿时感觉自己眼睛一亮&#xff0c;这是一个好主意。 图模型 事物的模型中&#xff0c;除了它自身的某些特征之外&#xff0c;还包括它与其…

第十二讲_JavaScript浏览器对象模型BOM

JavaScript浏览器对象模型BOM 1. 浏览器对象模型介绍2. location2.1 常用的属性2.2 常用的方法 3. navigator3.1 常用的属性 4. history4.1 常用的方法&#xff1a; 5. 本地存储 1. 浏览器对象模型介绍 BOM(Browser Object Model) 是指浏览器对象模型&#xff0c;浏览器对象模…

Unity3D实现坦克大战

一、效果图演示 二、逻辑剖析 从界面上&#xff1a; 需要一个Canvas满屏对着用户&#xff0c;该Canvas上展示用户的游戏数据&#xff0c;比如血条。需要一个Canvas放在蓝色坦克上方&#xff0c;也需要实时对着用户&#xff0c;显示敌人的血条信息两个坦克一个平面Plane放草地…

Nice Touch

Nice Touch是Unity最简单的多点触控输入解决方案,来自Corgi Engine和Infinite Runner Engine的制造商。所有功能完整文档论坛 功能列表: • 超级简单的设置 •兼容Unity的新旧输入系统 • 内置多点触控输入 •适用于所有移动设备 • 虚拟操纵杆 • 动态虚拟操纵杆 • 可重新定…

WebChat——一个开源的聊天应用

Web Chat 是开源的聊天系统&#xff0c;支持一键免费部署私人Chat网页的应用程序。 开源地址&#xff1a;https://github.com/loks666/webchat 目录树 TOC &#x1f44b;&#x1f3fb; 开始使用 & 交流&#x1f6f3; 开箱即用 A 使用 Docker 部署B 使用 Docker-compose…

web前端-------弹性盒子(2)

上一讲我们谈的是盒子的容器实行&#xff0c;今天我们来聊一聊弹性盒子的项目属性&#xff1b; *******************&#xff08;1&#xff09;顺序属性 order属性&#xff0c;用于定义容器中项目的出现顺序。 顺序属性值&#xff0c;为整数&#xff0c;可以为负数&#xff…

由亚马逊云科技 Graviton4 驱动的全新内存优化型实例 Amazon EC2 实例(R8g),现已开放预览

下一代 Amazon Elastic Compute CloudAmazon EC2) 实例的预览版现已公开 提供。全新的 R8g 实例 搭载新式 Graviton4 处理器&#xff0c;其性价比远超任何现有的内存优化实例。对于要求较高的内存密集型工作负载&#xff0c;R8g 实例是不二之选&#xff1a;大数据分析、高性能数…

SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式 基础(持续更新~)

具体操作&#xff1a; day2: 作用&#xff1a; 出现跨域问题 配相对应进行配置即可解决&#xff1a; IDEA连接的&#xff0c;在url最后加参数?useSSLfalse注意链接密码是123&#xff08;docker中mysql密码&#xff09; 注意&#xff0c;虚拟机中设置的密码和ip要和主机上…

代码随想录算法训练营第17天 | 110.平衡二叉树, 257. 二叉树的所有路径 ,404.左叶子之和

二叉树理论基础&#xff1a; https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE 110.平衡二叉树 题目链接&#xff1a;https://leetcode.cn/problems/balanced-binary-tree…

2024最新最详细【接口测试总结】

序章 ​ 说起接口测试&#xff0c;网上有很多例子&#xff0c;但是当初做为新手的我来说&#xff0c;看了不不知道他们说的什么&#xff0c;觉得接口测试&#xff0c;好高大上。认为学会了接口测试就能屌丝逆袭&#xff0c;走上人生巅峰&#xff0c;迎娶白富美。因此学了点开发…

林浩然与杨凌芸的Java奇缘:一场继承大戏

林浩然与杨凌芸的Java奇缘&#xff1a;一场继承大戏 Lin Haoran and Yang Lingyun’s Java Odyssey: A Tale of Inheritance 在一个充满代码香气的午后&#xff0c;我们故事的男主角——林浩然&#xff0c;一个热衷于Java编程的程序员&#xff0c;正在和他的“梦中女神”、同样…

【蓝桥杯选拔赛真题64】python数字塔 第十五届青少年组蓝桥杯python 选拔赛比赛真题解析

python数字塔 第十五届蓝桥杯青少年组python比赛选拔赛真题 一、题目要求 (注:input()输入函数的括号中不允许添加任何信息) 提示信息: 数字塔是由 N 行数堆积而成,最顶层只有一个数,次顶层两个数,以此类推。相邻层之间的数用线连接,下一层的每个数与它上一层左上…

JS第二天、原型、原型链、正则

☆☆☆☆ 什么是原型&#xff1f; 构造函数的prototype 就是原型 专门保存所有子对象共有属性和方法的对象一个对象的原型就是它的构造函数的prototype属性的值。prototype是哪来的&#xff1f;所有的函数都有一个prototype属性当函数被创建的时候&#xff0c;prototype属性…

机器学习超参数优化算法(贝叶斯优化)

文章目录 贝叶斯优化算法原理贝叶斯优化的实现&#xff08;三种方法均有代码实现&#xff09;基于Bayes_opt实现GP优化基于HyperOpt实现TPE优化基于Optuna实现多种贝叶斯优化 贝叶斯优化算法原理 在贝叶斯优化的数学过程当中&#xff0c;我们主要执行以下几个步骤&#xff1a; …

前端 - 基础 列表标签 - 自定义列表 详解

使用场景 &#xff1a; 常用于对术语或名词进行解释和描述&#xff0c;定义列表的列表前没有任何项目符号。 在 HTML 标签中&#xff0c; < dl > 标签用于定义 描述列表 &#xff08; 或定义列表 &#xff09; 该标签会与 <dt> ( 定义项目/名字 ) 和 <dd…

vue不同环境配置不同打包命令

这个需求非常普遍&#xff0c;通常情况我们在开发的时候一般会有三个环境&#xff1a;开发环境、测试环境、生产环境&#xff0c;我们一步步来看下。 vue环境变量是什么&#xff1f; 指的是在不同地方&#xff08;开发环境、测试环境、生产环境&#xff09;&#xff0c;变量就…

【教学类-46-04】吉祥字门贴4.0(华文彩云 文本框 空心字涂色 建议简体)

作品展示 背景需求&#xff1a; 1、制作了空心字的第1款 华光通心圆_CNKI &#xff0c;发现它不能识别某些简体字&#xff0c;但可以识别他们的繁体字&#xff08;繁体为准&#xff09; 【教学类-46-01】吉祥字门贴1.0&#xff08;华光通心圆_CNKI 文本框 空心字涂色&#xf…

3D Line Mapping Revisited论文阅读

1. 代码地址 GitHub - cvg/limap: A toolbox for mapping and localization with line features. 2. 项目主页 3D Line Mapping Revisited 3. 摘要 提出了一种基于线的重建算法&#xff0c;Limap&#xff0c;可以从多视图图像中构建3D线地图&#xff0c;通过线三角化、精心…