当前位置: 首页 > news >正文

用c++做贪吃蛇

由于蛇是由多块蛇身组成的,机构体数组或者链表来存储蛇
蛇在运行过程中,如果吃了食物,那么这块食物就可以看作是新的蛇头了,

数组存储


存储新蛇身,在数组的第一个位置插入一个元素。


链表


插入和删除元素效率很高,访问指定元素位置元素
中和上述两种结构的缺点
可以考虑使用队列或者双端队列的方式去存储蛇身
此处我们使用双端队列。

在窗口中绘制出蛇的身子。


函数分析:
·参数:
 将蛇作为函数的参数,用矩形框来代替蛇身的每一块,同时用绿色来表示蛇身。以引用方式传递。
 避免函数值传递过程中对函数参数进行拷贝,造成不必要的开销。
·返回值:无

游戏结束 


游戏结束标志:蛇头碰撞到窗口边界或者蛇头撞到了自己的身体。
函数分析:
· 参数:蛇,一方面要获取到蛇头位置,判断蛇头是否与窗口边界碰撞;另一方面也要获取蛇身,判断蛇头是否碰撞到蛇身。
· 返回值:可以不需要返回值,如果游戏结束,直接在该函数中结束程序即可。


蛇移动


整个蛇放在双端队列中,由于蛇每次超某个方向移动一步,其蛇身位置信息都要改变。不妨将蛇头移动反向的下一个位置的坐标作为新的蛇头,蛇尾部最后一个元素是否需要删除取决于蛇是否迟到了食物:如果没有迟到,则将蛇尾从蛇身中删除;如果吃到了,那么食物的位置就是新的蛇头,由于蛇身长度要加1,则不需要删除蛇尾。然后再重新绘制蛇身。这样一来,蛇就完成了一次移动。

函数分析:
·参数:
  ·将蛇作为函数的参数,
  ·用一个标记来标记蛇是否迟到了食物。
·返回值:无

更改蛇的移动方向


从键盘获取输入的按键,完成轮梗概运动的方向
键盘的W、w、上键均可使蛇向上移动;
键盘的S、s、下键均可使蛇向下移动;
键盘的A、a、左键均可使蛇向左移动;
键盘的D、d、右键均可使蛇向右移动;

捕获键盘按键消息

如果捕获到了上述的按键消息,则更改蛇的移动方向,但是注意不可以反方向更改
函数分析:
· 参数:蛇
·返回值:无

生成食物


在屏种随机位置生成一个食物,但注意不应该生成在蛇身上。
函数分析:
·参数:
     ·食物
     ·蛇
·返回值:无


在屏幕左上角显示得分


检测是否迟到了食物
及判断蛇头是否与食物重合。
函数分析:
· 参数:蛇,食物。
· 返回值:
bool类型,迟到了返回true,否则返回false

代码如下:

#include<easyx.h>
#include<deque>

using namespace std;

#define Wide 640
#define High 480

#define size 20//边长为20的正方形

#define Delay 200//延迟时间

//蛇移动方向
enum Direction
{
    Up,
    Down,
    Left,
    Right
};

//蛇身
struct Snake
{
    int x, y;
    Direction dir;//移动方向
};

//食物
struct Food
{
    int x, y;
};


//绘制蛇身
void drawSnake(deque<Snake>& snake)
{
    //绿色表示(设置填充颜色为绿色)
    setfillcolor(GREEN);
    //遍历蛇身绘制
    for (const auto& body : snake)
    {
        //绘制一个矩形框,四个参数分别是左上角和右下角的横纵坐标
        //用20*20的矩形框表示蛇身
        fillrectangle(body.x*size,body.y*size,(body.x+1)*size,(body.y+1)*size);
    }
    //控制蛇移动的速度
    Sleep(Delay);
}

//判断游戏是否结束
void isOver(deque<Snake>& snake)
{
    //检测碰撞
    //遍历蛇身,使用迭代器遍历,从蛇头后面一个元素开始遍历
    for (auto iter = snake.begin() + 1; iter != snake.end(); ++iter)
    {
        if ((snake.front().x == iter->x && snake.front().y == iter->y)//蛇头撞到了自己,游戏结束
            ||(snake.front().x <0)||(snake.front().x >= Wide/size)    //越界,游戏结束
            || (snake.front().y < 0) || (snake.front().y >= High / size)
            )
        {
            //设置当前文字颜色为白色
            settextcolor(RED);
            //设置当前文字样式,指定高度100,宽度0表示自适应。_T支持Unicode编码C
            settextstyle(100,0,_T("楷体"));
            TCHAR str[100];
            _stprintf_s(str, _T("游戏结束!!!"));
            //在指定位置输出字符串。
            outtextxy(Wide / size, High / size, str);
            //停留三秒
            Sleep(3000);

            closegraph();//关闭窗口
            //直接结束程序
            exit(0);
        }
    }
}

//蛇移动 grow表示是否迟到了食物,该参数用来区分蛇普通移动和吃到食物
void moveSnake(deque<Snake>& snake,bool grow=false)
{
    //获取蛇头
    Snake newHead = snake.front();
    //判断蛇移动方向
    switch (newHead.dir)
    {
    case Up:
        newHead.y--;
        break;
    case Down:
        newHead.y++;
        break;
    case Left:
        newHead.x--;
        break;
    case Right:
        newHead.x++;
        break;
    
    }
    //将新位置作为新蛇头
    snake.push_front(newHead);
    //每移动一次都要判断游戏是否结束了
    isOver(snake);
    if (!grow)
    {
        //没吃到食物
        //grow=true表示吃到了食物 grow=false表示普通移动
        clearrectangle(snake.back().x * size, snake.back().y * size, (snake.back().x + 1) * size, (snake.back().y + 1) * size);
        //将双端队列最后一个元素去除
        snake.pop_back();
    }
    //绘制蛇身
    drawSnake(snake);
}

//更改蛇移动方向
void changeDirection(deque<Snake>& snake)
{
    ExMessage msg = { 0 };
    //捕获按键消息
    peekmessage(&msg, EX_KEY);
    //当某个键被按下
    if (msg.message == WM_KEYDOWN)
    {
        //判断输入的按键
        switch (msg.vkcode)
        {
        case'w':
        case'W':
        case VK_UP:
            if (snake.front().dir != Down)
                snake.front().dir = Up;
            break;
        case's':
        case'S':
        case VK_DOWN:
            if (snake.front().dir != Up)
                snake.front().dir = Down;
            break;
        case 'a':
        case'A':
        case VK_LEFT:
            if (snake.front().dir != Right)
                snake.front().dir = Left;
            break;
        case 'd':
        case'D':
        case VK_RIGHT:
            if (snake.front().dir != Left)
                snake.front().dir = Right;
            break;
        }
    }
}

//生成食物,不能生成在蛇身上
void generateFood(Food& food, deque<Snake>& snake)
{
    //一直生成,知道生成的食物为止不在蛇身上
    while (true)
    {
        //随机生成
        //将整个窗口看做一个是数组,每个数组元素占的空间大小为20*20个像素点
        food.x = rand() % (Wide / size);
        food.y = rand() % (High / size);
        //用一个变量存储生成的位置是否重合
        bool overlap=false;
        //遍历蛇身,范围for循环
        for (const auto& body : snake)
        {
            //食物位置与蛇身重合
            if (food.x == body.x && food.y == body.y)
            {
                //已经与蛇身重合了,不必再遍历,跳出for循环,再while循环中重新生成
                overlap = true;
                break;
                
            }
        }
        //如果不重合,则食物生成成功,可以结束while循环了
        if (!overlap)
        {
            break;
        }
    }
}

//检测是否与食物重合
bool checkCollision(deque<Snake>& snake, Food& food)
{
    //蛇头与食物重合
    if (snake.front().x == food.x && snake.front().y == food.y)
    {
        return true;
    }
    //检测是否与蛇身的位置重叠(可以不用,因为蛇头没经过的位置,蛇身必然不会经过)
    for (auto iter = snake.begin() + 1; iter != snake.end(); ++iter)
    {
        if (iter->x == food.x && iter->y== food.y)
        {
            return true;
        }
    }
    return false;
}
int main()
{

    initgraph(Wide, High);//绘制窗口,两个参数分别为窗口的宽度和长度

    //定义一条蛇
    deque<Snake> snake;
    //初始化蛇
    //双端队列头部插入一个元素作为蛇头
    snake.push_front(Snake{ Wide/size/2,High/size/2,Right });

    
    Food food;
    generateFood(food, snake);
    //绘制食物
    setfillcolor(RED);
    fillrectangle(food.x * size, food.y * size, (food.x + 1) * size, (food.y + 1) * +size);
    drawSnake(snake);
    //分数初始为0
    int score = 0;
    while (true)
    {
        //蛇移动
        moveSnake(snake);
        //更改蛇移动方向
        changeDirection(snake);
        //检测是否与食物重合
        if (checkCollision(snake, food))
        {
            //蛇吃到食物
            score++;
            //生成新的食物
            generateFood(food, snake);
            //true,增加蛇的长度
            moveSnake(snake, true);
        }
        //绘制食物 红色表示食物
        setfillcolor(WHITE);
        fillrectangle(food.x*size, food.y*size, (food.x +1)* size, (food.y+1)* + size);
        //设置当前文字颜色
        settextcolor(GREEN);
        //设置当前文字样式,指定高度20,宽度0表示自适应。_T支持Unicode编码Consolas表示字体
        settextstyle(20,0,_T("楷体"));
        TCHAR strScore[16];
        _stprintf_s(strScore, _T("得分:%d"), score);
        //在指定位置输出字符串。
        outtextxy(10, 10, strScore);

    }


    system("pause");//防止窗口打开即关闭,一闪而过,让其先停一会
    closegraph();//关闭窗口
    return 0;
}

相关文章:

用c++做贪吃蛇

由于蛇是由多块蛇身组成的&#xff0c;机构体数组或者链表来存储蛇 蛇在运行过程中&#xff0c;如果吃了食物&#xff0c;那么这块食物就可以看作是新的蛇头了&#xff0c; 数组存储 存储新蛇身&#xff0c;在数组的第一个位置插入一个元素。 链表 插入和删除元素效率很高&…...

【UE5.1 角色练习】08-传送技能

前言 在上一篇&#xff08;【UE5.1 角色练习】07-AOE技能&#xff09;基础上继续实现人物通过鼠标点击然后传送技能的功能。 效果 步骤 1. 首先需要显示鼠标光标&#xff0c;我们可以在玩家控制器中勾选“显示鼠标光标” 2. 在项目设置中添加一个操作映射&#xff0c;设置按…...

力扣283题:移动零(快慢指针)

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: [0…...

Java面试精粹:高级问题与解答集锦(一)

Java 高级面试问题及答案 问题1&#xff1a;Java中如何实现多线程&#xff0c;以及有哪些线程同步机制&#xff1f; 答案&#xff1a; Java实现多线程主要有两种方式&#xff1a;继承 Thread 类和实现 Runnable 接口。通过继承 Thread 类&#xff0c;可以重写 run() 方法来定…...

Yourpassword does not satisfy the current policyrequirements

mysql 新增数据库用户失败 解决方法&#xff1a; 修改校验密码策略等级 set global validate_password.policyLOW;...

解决vue3 vite打包报Root file specified for compilation问题

解决方法&#xff1a; 修改package.json打包命令 把 "build": "vue-tsc --noEmit && vite build" 修改为 "build": "vite build" 就可以了 另外关于allowJs这个问题&#xff0c;在tsconfig.json文件中配置"allowJs&qu…...

Java Swing + MySQL图书借阅管理系统

系列文章目录 Java Swing MySQL 图书管理系统 Java Swing MySQL 图书借阅管理系统 文章目录 系列文章目录前言一、项目展示二、部分代码1.Book2.BookDao3.DBUtil4.BookAddInternalFrame5.Login 三、配置 前言 项目是使用Java swing开发&#xff0c;界面设计比较简洁、适合作…...

ssm招聘信息管理系统-计算机毕业设计源码78049

摘 要 由于数据库和数据仓库技术的快速发展&#xff0c;招聘客户管理系统建设越来越向模块化、智能化、自我服务和管理科学化的方向发展。招聘客户系统对处理对象和服务对象&#xff0c;自身的系统结构&#xff0c;处理能力&#xff0c;都将适应技术发展的要求发生重大的变化。…...

eBPF可观测之网络流量控制和管理traffic control浅尝

目录 工程背景 环境准备 安装工具​​​ 安装依赖包 安装C依赖库 操作步骤 目录结构 代码展示 效果展示 拓展提升 工程背景 首先发表一个"暴论" eBPF在可观测方面的应用&#xff0c;就是各种google。 不需要学习内核&#xff0c;只要掌握ebpf开发套路。…...

Java技术精粹:高级面试问题与解答指南(二)

Java面试问题及答案 1. 什么是Java中的集合框架&#xff1f;请简述其主要接口和类。 答案&#xff1a; Java中的集合框架是一个设计用来存储和操作大量数据的统一架构。它主要由以下几个接口及其实现类组成&#xff1a; Collection: 它是最基本的集合接口&#xff0c;所有单列…...

地下停车场FM信号覆盖系统技术原理用与应用

随着我国城市化水平的快速推进与房地产的快速发展&#xff0c;城市停车场称为每栋建筑物的硬性配套建筑&#xff0c;尤其是商业综合体、医院、政府机关、机场、高铁站等场所出现了超大规模停车场&#xff0c;停放车辆可达数千辆&#xff0c;停车场的智能化与信息化水平也越来越…...

idea 出现 cpu占用100%

一、IDEA的CPU占用率过高 二、解决办法 idea安装路径bin目录 修改idea64.exe.vmoptions配置文件 原来的 -Xms128m -Xmx750m -XX:ReservedCodeCacheSize240m -XX:UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB50 修改为(IDEA优化内存配置) -Xms2048m -Xmx4096m -XX:Reser…...

如何学到数据库从入门到入土(MySQL篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…...

安卓手机APP开发__Wi-Fi扫描概述

安卓手机APP开发__Wi-Fi扫描概述 目录 概述 Wi-Fi的扫描过程 限制 权限 Android 8.0 and Android 8.1: Android 9: Android 10 (API 级别 29) 和 更高版本: 扫描频率的限制 Android 8.0 and Android 8.1: Android 9: Android 10 and higher: 概述 你能使用Wi-Fi的…...

深入理解二叉树及其在C语言中的实现

一、引言 二叉树是数据结构中一种非常基础且重要的树形结构&#xff0c;它的每个节点最多有两个子节点&#xff0c;通常被称为左子节点和右子节点。二叉树在计算机科学中有着广泛的应用&#xff0c;如搜索、排序、存储数据等。本文将详细介绍二叉树的基本概念、特性以及在C语言…...

基于ssm+vue图书管理系统

基于ssmvue图书管理系统 ssm477图书管理系统 相关技术 javassmmysqlvueelementui...

高防ip能防护变异CC攻击吗

高防ip能防护变异CC攻击吗&#xff1f;随着互联网的不断发展&#xff0c;网络安全问题也日益突出&#xff0c;各类网络攻击层出不穷&#xff0c;其中CC攻击&#xff08;Challenge Collapsar攻击&#xff09;及其变种——变异CC攻击&#xff0c;更是让众多企业和个人网站头疼不已…...

从多站点到多活,XEOS 对象数据容灾能力再提升

近日&#xff0c; XSKY SDS V6.4 新版本发布&#xff0c;其中 XEOS V6.4 全新升级并完善了统一命名空间功能&#xff0c;更进一步增强和完善了异地容灾方案&#xff0c;配合强一致代理读&#xff0c;可以实现异地多活&#xff1b;同时大幅降低管理复杂度&#xff0c;有效降低容…...

3D开发工具HOOPS在BIM系统中的应用

建筑信息模型是一种革命性的建筑设计、施工和管理方法。它通过创建和利用数字信息来优化建筑项目的设计、施工和运营过程。在这个过程中&#xff0c;3D开发工具HOOPS扮演着至关重要的角色&#xff0c;为BIM系统提供了强大的技术支持和丰富的功能。HOOPS中文网http://techsoft3d…...

适合下班做的副业兼职、1天挣300,7天涨粉2万

最近小红书上有类视频火了&#xff01; 周周近财&#xff1a;让网络小白少花冤枉钱&#xff0c;赚取第一桶金 利用AI制作的漫画解说历史小说视频。视频以《明朝那些事儿》为蓝本&#xff0c;一上线就疯狂吸粉&#xff0c;多条视频内容都大爆了。 就是这个账号&#xff0c;仅仅…...

新能源汽车热管理核心技术解析:冬季续航提升40%的行业方案

新能源汽车热管理核心技术解析&#xff1a;冬季续航提升40%的行业方案 摘要&#xff1a;突破续航焦虑的关键在热能循环&#xff01; &#x1f449; 本文耗时72小时梳理行业前沿方案&#xff0c;含特斯拉/比亚迪等8家车企热管理系统原理图 一、热管理为何成新能源车决胜关键&am…...

[蓝桥杯]采油

采油 题目描述 LQ 公司是世界著名的石油公司&#xff0c;为世界供应优质石油。 最近&#xff0c;LQ 公司又在森林里发现了一大片区域的油田&#xff0c;可以在这个油田中开采 nn 个油井。 LQ 公司在这 nn 个油井之间修建了 n−1n−1 条道路&#xff0c;每条道路连接两个油井…...

十三、【核心功能篇】测试计划管理:组织和编排测试用例

【核心功能篇】测试计划管理&#xff1a;组织和编排测试用例 前言准备工作第一部分&#xff1a;后端实现 (Django)1. 定义 TestPlan 模型2. 生成并应用数据库迁移3. 创建 TestPlanSerializer4. 创建 TestPlanViewSet5. 注册路由6. 注册到 Django Admin 第二部分&#xff1a;前端…...

OS11.【Linux】vim文本编辑器

目录 1.四种模式 命令模式 几个命令 插入模式 底行模式 一图展示三种模式之间的关系 2.分屏(多文件操作) 3.配置vim的原理 4.脚本一键配置vim CentOS 7 x86_64 其他发行版 5.NeoVim(推荐) vim文本编辑器是一个多模式的编辑器,因此先介绍它的四种模式 附vim的官网:…...

arc3.2语言sort的时候报错:(sort < `(2 9 3 7 5 1)) 需要写成这种:(sort > (pair (list 3 2)))

arc语言sort的时候报错&#xff1a;(sort < (2 9 3 7 5 1)) arc> (sort < (2 9 3 7 5 1)) Error: "set-car!: expected argument of type <pair>; given: 9609216" arc> (sort < (2 9 3 )) Error: "Function call on inappropriate object…...

SpringBoot 系列之集成 RabbitMQ 实现高效流量控制

系列博客专栏&#xff1a; JVM系列博客专栏SpringBoot系列博客 Spring Boot 2.2.1 集成 RabbitMQ 实现高效流量控制 在分布式系统中&#xff0c;消息队列是实现异步通信、解耦服务的重要组件。RabbitMQ 作为一款成熟的开源消息队列&#xff0c;广泛应用于各类项目中。本文将…...

4G网络中频段的分配

国内三大运营商使用的4G网络频段及对应关系如下&#xff1a; &#x1f4f6; 一、中国移动&#xff08;以TD-LTE为主&#xff09; 主力频段 Band 38&#xff08;2570-2620MHz&#xff09;&#xff1a;室内覆盖Band 39&#xff08;1880-1920MHz&#xff09;&#xff1a;广覆盖&am…...

解决获取视频第一帧黑屏问题

文章目录 解决获取视频第一帧黑屏问题核心代码 解决获取视频第一帧黑屏问题 废话不多说&#xff0c;直接上代码&#xff1a; <script setup> const status ref(请点击“添加视频”按钮添加视频) const videoElement ref(document.createElement(video)) const curren…...

嵌入式学习笔记-freeRTOS taskENTER_CRITICAL(_FROM_ISR)跟taskEXIT_CRITICAL(_FROM_ISR)函数解析

一 函数taskENTER_CRITICAL&#xff0c;taskEXIT_CRITICAL 函数taskENTER_CRITICAL最终实现如下&#xff1a; 第①处按照系统设定的configMAX_SYSCALL_INTERRUPT_PRIORITY值对中断进行屏蔽 第②处调用一次自增一次 第③处检查中断状态寄存器位&#xff0c;如果有任何中断位置…...

【科研绘图系列】R语言绘制和弦图(Chord diagram plot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理相关性计算和弦图系统信息介绍 本文介绍了一个基于R语言的数据分析和可视化流程,主要用于生成和弦图(Chord Diagram)。和弦图是一种用于展示…...