首先我们需要下载EasyX(具体的方法在EasyX专栏中有提到)

easyX下载和绘制简单基本图形_小梁今天敲代码了吗的博客-CSDN博客

贪吃蛇这个游戏我们一定都玩过,玩家使用方向键操控一条“蛇”,蛇会朝着一个方向不断移动,玩家可以通过上下左右键改变其运动方向。同时屏幕上随机会出现各种“食物”,玩家要控制蛇去吃掉这些食物,每吃掉一个,蛇的身体就会增长一节。

想要实现这个游戏,我们主要得考虑蛇和食物

蛇:

蛇的移动方向如何实现

蛇的身体长度如何实现增长

食物:

食物如何随机生成

下面我将代码部分拆解做一个简单的说明,后附源码

首先是播放背景音乐:

将音乐的mp3格式与代码放在一个文件夹中,用以下函数调用:

#include<mmsystem.h>//头文件
#pragma comment(lib,"winmm.lib")//库文件//播放音乐 mci media control interface(多媒体设备接口)//Send 发送 String字符串
//音乐需要放在程序同一文件目录中
mciSendString("open 音乐.mp3",0,0,0);
mciSendString("play 音乐.mp3", 0, 0, 0);

创建“精灵类”,它是“蛇类”和“食物类”的父类

这里难理解的地方是:碰撞检测(我们如何去判定蛇能吃到食物?这里采用的方法是当蛇头的左上方x,y坐标完全与食物的左上方x,y坐标相等时,我们认为蛇吃到了食物)

这个函数用于设置当前设备填充颜色。

void setfillcolor(COLORREF color);

这个函数用于画有边框的填充矩形。

void fillrectangle(int left,int top,int right,int bottom
);
//精灵类
class Sprite
{
public:Sprite():Sprite(0,0) {};Sprite(int x, int y) :m_x(x), m_y(y),m_color(RED) {};//绘制精灵virtual void draw(){//设置填充颜色setfillcolor(m_color);//绘制矩形fillrectangle(m_x, m_y, m_x + 10, m_y + 10);}//移动void moveBy(int dx, int dy){m_x += dx;m_y += dy;}//碰撞检测bool collision(const Sprite& other){return m_x == other.m_x && m_y == other.m_y;}
protected:int m_x;int m_y;COLORREF m_color;//颜色
};

蛇类这里移动时,将上一个格子坐标赋值给下一个格子,实现移动

push_back()函数的用法

函数将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素

//蛇类
class Snake : public Sprite
{
public:Snake():Snake(0,0) {}Snake(int x,int y):Sprite(x,y),dir(VK_RIGHT){//初始化三节蛇nodes.push_back(Sprite(20, 0));nodes.push_back(Sprite(10, 0));nodes.push_back(Sprite(0, 0));}void draw() override{for (int i = 0; i < nodes.size(); i++){nodes[i].draw();}}//蛇的身体移动void bodyMove(){//身体跟着蛇头移动for (size_t i = nodes.size()-1; i >0; i--){nodes[i] = nodes[i - 1];}//移动蛇头switch (dir){case VK_UP:nodes[0].moveBy(0,-10);break;case VK_DOWN:nodes[0].moveBy(0,10);break;case VK_LEFT:nodes[0].moveBy(-10, 0);break;case VK_RIGHT:nodes[0].moveBy(10, 0);break;}}bool collision(const Sprite& other){return nodes[0].collision(other);}//蛇增加一节void incrment(){nodes.push_back(Sprite());}
private://蛇只有一节吗?std::vector<Sprite> nodes;//蛇的所有节点public:int dir;//蛇的方向
};

食物:

为了使程序在每次执行时都能生成一个新序列的随机值,我们通常通过为随机数生成器提供一粒新的随机种子。函数srand()可以为随机数生成器播散种子。随机生成食物时,我们需要它的坐标为10的整数倍,因为蛇的身体我们设定的占10个像素,所以只能吃到坐标为10的整数倍的食物

//食物
class Food :public Sprite
{
public:Food() :Sprite(0, 0) {changePos();}void draw()override{setfillcolor(m_color);solidellipse(m_x, m_y, m_x + 10, m_y + 10);}//改变食物的坐标void changePos(){//随机生成坐标m_x = rand() % 64 * 10;m_y = rand() % 48 * 10;}
};

游戏场景:

这里引用的函数是什么意思基本已经在代码中进行了标注

这里的switch代码是在蛇的移动过程中,让它不能掉头

switch (msg.vkcode){case VK_UP:if (snake.dir != VK_DOWN)snake.dir = msg.vkcode;break;case VK_DOWN:if (snake.dir != VK_UP)snake.dir = msg.vkcode;break;case VK_LEFT:if (snake.dir != VK_RIGHT)snake.dir = msg.vkcode;break;case VK_RIGHT:if (snake.dir != VK_LEFT)snake.dir = msg.vkcode;break;}

ExMessage这个结构体用于保存鼠标消息

WM_KEYDOWN EX_KEY 按键按下消息

BeginBatchDraw()这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。

void BeginBatchDraw();

cleardevice()这个函数使用当前背景色清空绘图设备。

void cleardevice();
/*游戏场景*/
class GameScene
{
public:GameScene() {};void run(){BeginBatchDraw();//双缓冲绘图 防止屏幕闪烁cleardevice();//清屏snake.draw();food.draw();EndBatchDraw();//移动蛇,改变蛇的坐标snake.bodyMove();snakeEatFood();//获取消息ExMessage msg = { 0 };while (peekmessage(&msg, EX_KEY)){onMsg(msg);}}//改变蛇的移动方向 获取键盘按键 _getch() //响应消息:鼠标消息 键盘消息void onMsg(const ExMessage& msg){//如果有键盘消息(有没有按键按下)if (msg.message == WM_KEYDOWN){//判断具体的是哪个按键按下 virtual key code 虚拟键码switch (msg.vkcode){case VK_UP:if (snake.dir != VK_DOWN)snake.dir = msg.vkcode;break;case VK_DOWN:if (snake.dir != VK_UP)snake.dir = msg.vkcode;break;case VK_LEFT:if (snake.dir != VK_RIGHT)snake.dir = msg.vkcode;break;case VK_RIGHT:if (snake.dir != VK_LEFT)snake.dir = msg.vkcode;break;}//std::cout << msg.vkcode << std::endl;}}//判断蛇能否吃到食物void snakeEatFood(){if (snake.collision(food))//如果蛇和食物产生了碰撞{//蛇的节数增加snake.incrment();//食物重新产生在别的地方food.changePos();}}
private:Snake snake;Food food;};

最后源码如下:

#include<iostream>//标准输入输出头文件
#include<graphics.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
#include<easyx.h>
#include<vector> //顺序表
#include<ctime>
//精灵类
class Sprite
{
public:Sprite():Sprite(0,0) {};Sprite(int x, int y) :m_x(x), m_y(y),m_color(RED) {};//绘制精灵virtual void draw(){//设置填充颜色setfillcolor(m_color);//绘制矩形fillrectangle(m_x, m_y, m_x + 10, m_y + 10);}//移动void moveBy(int dx, int dy){m_x += dx;m_y += dy;}//碰撞检测bool collision(const Sprite& other){return m_x == other.m_x && m_y == other.m_y;}
protected:int m_x;int m_y;COLORREF m_color;//颜色
};//蛇类
class Snake : public Sprite
{
public:Snake():Snake(0,0) {}Snake(int x,int y):Sprite(x,y),dir(VK_RIGHT){//初始化三节蛇nodes.push_back(Sprite(20, 0));nodes.push_back(Sprite(10, 0));nodes.push_back(Sprite(0, 0));}void draw() override{for (int i = 0; i < nodes.size(); i++){nodes[i].draw();}}//蛇的身体移动void bodyMove(){//身体跟着蛇头移动for (size_t i = nodes.size()-1; i >0; i--){nodes[i] = nodes[i - 1];}//移动蛇头switch (dir){case VK_UP:nodes[0].moveBy(0,-10);break;case VK_DOWN:nodes[0].moveBy(0,10);break;case VK_LEFT:nodes[0].moveBy(-10, 0);break;case VK_RIGHT:nodes[0].moveBy(10, 0);break;}}bool collision(const Sprite& other){return nodes[0].collision(other);}//蛇增加一节void incrment(){nodes.push_back(Sprite());}
private://蛇只有一节吗?std::vector<Sprite> nodes;//蛇的所有节点public:int dir;//蛇的方向
};
//食物
class Food :public Sprite
{
public:Food() :Sprite(0, 0) {changePos();}void draw()override{setfillcolor(m_color);solidellipse(m_x, m_y, m_x + 10, m_y + 10);}//改变食物的坐标void changePos(){//随机生成坐标m_x = rand() % 64 * 10;m_y = rand() % 48 * 10;}
};
/*游戏场景*/
class GameScene
{
public:GameScene() {};void run(){BeginBatchDraw();//双缓冲绘图 防止屏幕闪烁cleardevice();//清屏snake.draw();food.draw();EndBatchDraw();//移动蛇,改变蛇的坐标snake.bodyMove();snakeEatFood();//获取消息ExMessage msg = { 0 };while (peekmessage(&msg, EX_KEY)){onMsg(msg);}}//改变蛇的移动方向 获取键盘按键 _getch() //响应消息:鼠标消息 键盘消息void onMsg(const ExMessage& msg){//如果有键盘消息(有没有按键按下)if (msg.message == WM_KEYDOWN){//判断具体的是哪个按键按下 virtual key code 虚拟键码switch (msg.vkcode){case VK_UP:if (snake.dir != VK_DOWN)snake.dir = msg.vkcode;break;case VK_DOWN:if (snake.dir != VK_UP)snake.dir = msg.vkcode;break;case VK_LEFT:if (snake.dir != VK_RIGHT)snake.dir = msg.vkcode;break;case VK_RIGHT:if (snake.dir != VK_LEFT)snake.dir = msg.vkcode;break;}//std::cout << msg.vkcode << std::endl;}}//判断蛇能否吃到食物void snakeEatFood(){if (snake.collision(food))//如果蛇和食物产生了碰撞{//蛇的节数增加snake.incrment();//食物重新产生在别的地方food.changePos();}}
private:Snake snake;Food food;};
int main()
{//初始化窗口界面initgraph(640,480,EW_SHOWCONSOLE);GameScene scene;scene.run();//设置随机数种子srand(time(nullptr));//播放音乐 mci media control interface(多媒体设备接口)//Send 发送 String字符串mciSendString("open 音乐.mp3",0,0,0);mciSendString("play 音乐.mp3", 0, 0, 0);Snake snake;snake.draw();while (true){scene.run();Sleep(100);}getchar();//防止程序闪退return 0;
}

至此我们就实现了简单的贪吃蛇游戏,它可以上下左右移动,并在吃到食物后增长一格身体

贪吃蛇小游戏(C++)相关推荐

  1. 100行代码,使用 Pygame 制作一个贪吃蛇小游戏!

    作者 | 周萝卜 来源 | 萝卜大杂烩 相信我们大家都玩过贪吃蛇游戏,今天我们就从头一起来写一个贪吃蛇小游戏,只需要100多行的代码就完成了. 用到的 Pygame 函数 贪吃蛇小游戏用到的函数 功能 ...

  2. Python实现贪吃蛇小游戏(双人模式)

    这篇文章主要为大家详细介绍了Python实现双人模式的贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 简单用py写了一个贪吃蛇游戏,有单人.双人模式,比较简 ...

  3. GUI编程---贪吃蛇小游戏开发

    学习链接:狂神说Java–1小时开发贪吃蛇小游戏 ①初识理论 帧:时间片足够小=>就是动画,1秒30帧.连起来是动画,拆开就是静态的图片! 键盘监听 定时器Timer 游戏图片素材:GUI之贪吃 ...

  4. python 贪吃蛇小游戏代码_10分钟再用Python编写贪吃蛇小游戏

    Python编写贪吃蛇 前不久我们公众号发布了一篇C++编写贪吃蛇小游戏的推文,反响空前.看来大家对这类简单易上手小游戏还是很喜爱的. 恰逢2018年IEEE Spectrum编程语言排行榜新鲜出炉, ...

  5. python100行代码程序-100行python代码,轻松完成贪吃蛇小游戏

    大家小时候都玩过贪吃蛇吧?小编小时候可喜欢拿爸妈的手机玩了,厉害着呢!今天,小编就来用100行代码实现一个简易版的贪吃蛇.在网上,贪吃蛇教程蛮多的,但要安装蛮多库的,而且也不够清晰,今天的代码比较短, ...

  6. python小游戏编程实例-10分钟教你用Python写一个贪吃蛇小游戏,适合练手项目

    另外要注意:光理论是不够的.这里顺便总大家一套2020最新python入门到高级项目实战视频教程,可以去小编的Python交流.裙 :七衣衣九七七巴而五(数字的谐音)转换下可以找到了,还可以跟老司机交 ...

  7. python100行代码-怎样写贪吃蛇小游戏?用100行python代码轻松解决!

    大家小时候都玩过贪吃蛇吧?小编小时候可喜欢拿爸妈的手机玩了,厉害着呢!今天,小编就来用100行代码实现一个简易版的贪吃蛇.在网上,贪吃蛇教程蛮多的,但要安装蛮多库的,而且也不够清晰,今天的代码比较短, ...

  8. python编程小游戏-10分钟用Python编写一个贪吃蛇小游戏,简单

    贪吃蛇,大家应该都玩过.小编当初第一次接触贪吃蛇的时候 ,还是能砸核桃的诺基亚上,当时玩的不亦乐乎.今天,我们用Python编程一个贪吃蛇游戏,下面我们先看看效果: 好了,先介绍一个思路 所有的游戏最 ...

  9. 再来一次的C语言贪吃蛇小游戏(三)

    8.游戏的不同界面 为了便于实现主要功能,之前我们所有的状态控制都是放在游戏中,但实际上我们应该把这些状态控制抽离出来,通过菜单来控制,以便在不同游戏界面间切换. 菜单界面 游戏界面 排行榜 游戏结束 ...

  10. 基于stm32、0.96寸OLED实现的贪吃蛇小游戏(详细源码注释)

    简介:本实验基于stm32最小系统.0.96寸OLED(68*128)和摇杆实现一个经典的贪吃蛇小游戏.项目源码地址:点击下载. 硬件设计: 普通摇杆,0.96寸OLED 单色屏幕(SPI协议通讯), ...

最新文章

  1. React JSX 实例图解
  2. java.lang.NoClassDefFoundError: org/springframework/boot/context/embedded/FilterRegistrationBean
  3. python 图片地址_python解码data:image开头的图片地址
  4. aix磁盘挂载到linux,AIX下文件系统挂载点相互调换方案
  5. VS2013在Release情况下使用vector有时候会崩溃的一个可能原因
  6. 开源管理项目管理_避免开源项目管理中的不良做法
  7. 获取指定路径下所有PDF文件的总页数
  8. 微信模板消息发送帮助类
  9. 4、Android下实现Google街景
  10. 推荐几部好看的漫画,漫迷们不容错过的动漫新番哦
  11. 一个屌丝程序猿的人生(五十七)
  12. C语言简单程序——解二元一次方程
  13. 汉诺塔问题解法心路历程及C语言学习请教
  14. python股票网格交易_不知道哪位交易员可以解释下网格交易法?
  15. 初学实体框架EF(Entity Framework)
  16. 互联网快讯:华为正式开启二手机业务;法院审理认定阿卡索赔猿辅导20万;极米高性能投影产品获用户青睐;谷歌Pixel 6 Pro首次放弃使用高通基带
  17. Hydra教程——非常详细
  18. 高校版MATLAB license checkout failed问题及解决
  19. php解析json转数组,php json转数组出错
  20. Nav2极简笔记01-安装与试用

热门文章

  1. linux fvwm作用_使用FVWM自定义Linux桌面
  2. iOS版本的APP已上线,但是AppStore里面按钮显示的是打开
  3. 计算机术语表-主板术语
  4. IT民工系列——c#操控海康威视视屏监控卡(海康威视 4路视频捕捉卡 DS-4004HC)...
  5. 如何进行链路捆绑(详细实验流程)
  6. 真正牛逼的员工,是让领导又爱又怕
  7. Unity-场景-Terrain
  8. 定出公式对应的c语言表达式,代数式到c语言表达式和常用的c语言数学库函数_pow_sqrt_exp_fabs_abs...
  9. 通过ArcGIS对GlobeLand30影像镶嵌拼接并去除黑边
  10. 家具防霉方案(适用于家具厂)