接触编程有段时间了,一直想学习怎么去写个游戏来练练手。在看了B站上的教学终于可以自己试试怎么实现贪吃蛇这个游戏了。好了,废话不多说,我们来看看如何用EasyX库来实现贪吃蛇。

一、准备

  • 工具vc++6.0
  • 安装库文件
    • EasyX库安装链接
    • 可以安装任意版本,本人安装的是2018春分版
    • 这是一个简单易学的一个图形库,相信对于大家学习来说应该不成问题
  • 准备工作做好后接下来就得弄清楚游戏工作机制了

二、基本介绍

在这里我们需要明白EasyX库的基本知识,其次我们还有了解游戏的工作原理,不能盲目的直接写代码,需要一步步的思考,比如蛇是如何绘制、移动的;食物是怎么产生的;蛇吃了食物会怎样;死亡机制等等

EasyX库介绍

  1. 首先我们来讲讲EasyX库的坐标概念

    • 物理坐标

      • 简单来说,物理坐标就是以窗口的左上角为原点,以水平向右为x轴,竖直向下为y轴,以像素为单位
    • 逻辑坐标
      • 逻辑坐标和物理坐标是一一对应的,不过逻辑坐标是以点为单位
  2. 颜色概念
  • EasyX库的预定义颜色常量如下:
常量 颜色
BLACK 0
BULE 0xAA0000
GREEN 0x00AA00 绿
CYAN 0xAAAA00
RED 0x0000AA
MAGENTA 0xAA00AA
BROWN 0x0055AA 棕色
LIGHTGRAY 0xAAAAAA 浅灰
DARKGRAY 0x555555 深灰
LIGHTBULE 0xFF5555 亮蓝
LIGHTGREEN 0x55FF55 亮绿
LIGHTCYAN 0xFFFF55 亮青
LIGHTRED 0x5555FF 亮红
LIGHTMAGENTA 0xFF55FF 亮紫
YELLOW 0x55FFFF
WHITE 0xFFFFFF

3.基本函数介绍

  • initgraph(int width,int height,int flag=NULL):初始化绘图环境

    • width:绘图环境的宽度
    • height:绘图环境的高度
    • flag:绘图环境的样式,默认为NULL
  • cleardevice():用于清除屏幕内容
  • setbkcolor(COLORREF color):设置背景颜色
  • setfillcolor(COLORREF color):设置填充颜色
  • setlinecolor(COLORREF color):设置当前画线颜色
  • outtextxy(int x,int y,TCHAR c):用于在指定位置输出字符串
    • x,y表示输出字符串的坐标值
    • c表示待输出的字符
  • fillroundrect(int left,int top,int right,int bottom,int ellipsewidth,int ellipseheight):绘制圆角矩形
    • left:圆角矩形左部 x 坐标
    • top:圆角矩形上部 y 坐标
    • right:圆角矩形右部 x 坐标
    • bottom:圆角矩形下部 y 坐标
    • ellipsewidth:构成圆角矩形的圆角的椭圆的宽度
    • ellipseheight:构成圆角矩形的圆角的椭圆的高度

工作原理

  • 必须先包含头文件,才能运行
#include<graphics.h>
#include<time.h>
#include<stdlib.h>
#include<conio.h>
  • 我们要有窗口才能绘制蛇和食物,因此可以用initgraph()函数来实现
  • 其次我们要弄清楚如何来描述窗口位置,这里我们可以设置一个结构体Coor
struct Coor{
int x;
int y;
};
  • 方向
enum Ch{  //枚举类型表示上下左右键的键值
up=72,
down=80,
left=75,
right=77
};
  • 蛇也是有自己属性的结构体
struct Snake{
//蛇的属性
int n; //蛇当前节数,一节为一个正方形,n个正方形
struct Coor szb[500]; //snake的坐标,存放蛇的坐标,这里设置500,表示蛇能达到的最大长度为500
Ch ch; //蛇的方向
}snake; //变量
  • 食物的结构体
struct Food{
struct Coor fzb; //食物坐标
int flag; //是否被吃
}food;

有了以上的结构体的定义,我们就可以设置函数来完成贪吃蛇的绘制、移动、食物的绘制以及死亡机制等等

  • 函数内容如下

    • InitSnake():包含窗口的初始化,初始化随机种子,初始化蛇的起始坐标
    • DrawSnake():绘制蛇的每个节点
    • MoveSnake():蛇的移动
    • ChangeSnakeCh():通过键盘改变蛇的方向
    • CoorFood():随机生成食物的坐标
    • DrawFood():绘制食物样式
    • EatFood():蛇吃掉食物后的变化
    • KnockWall():撞墙死亡
    • EatSelf():吃到自己死亡
void InitSnake(){
//初始化窗口
srand((unsigned int)time(NULL)); //产生随机种子
initgraph(200,200); //初始化200*200像素的绘图窗口
setbkcolor(GREEN); //设置背景颜色 //初始化蛇
//开始时蛇的节数为1,方向向右
snake.n=1;
snake.ch=right;
snake.szb[0].x=0;
snake.szb[0].y=0;
} //绘制蛇,n节蛇
void DrawSnake(){
setlinecolor(GREEN); //设置蛇边缘的线条颜色
setfillcolor(RED); //设置蛇身的颜色
//遍历数组
for(int i=0;i<snake.n;i++){
fillrectangle(snake.szb[i].x,snake.szb[i].y,snake.szb[i].x+10,snake.szb[i].y+10); //根据蛇的当前长度,创建蛇身,这里设置一节蛇的大小为10*10个像素
}
}
  • 关于蛇的移动其实很简单,只要将前面的节点坐标传递给后面的节点坐标,就能起到移动的效果
//蛇的移动
void MoveSnake(){
for(int i=snake.n-1;i>0;i--){
snake.szb[i].x=snake.szb[i-1].x;
snake.szb[i].y=snake.szb[i-1].y;
}
switch(snake.ch){
case up:
snake.szb[0].y-=10;
break;
case down:
snake.szb[0].y+=10;
break;
case left:
snake.szb[0].x-=10;
break;
case right:
snake.szb[0].x+=10;
break;
}
}
  • 这里需要注意的是:蛇移动时的方向改变规则是在蛇向左/右移动时,蛇只能向上/下移动,同理对于蛇在向上/下移动的情况
//通过键盘控制
void ChangeSnakeCh(){
int move;
move=getch(); //获取键盘传递的字符
switch(move){
case right:
if(snake.ch!=left)
snake.ch=right;
break;
case left:
if(snake.ch!=right)
snake.ch=left;
break;
case up:
if(snake.ch!=down)
snake.ch=up;
break;
case down:
if(snake.ch!=up)
snake.ch=down;
break;
}
}
  • 食物的产生与绘制
void CoorFood(){
food.fzb.x=rand()%20*10; //根据窗口像素来产生食物坐标
food.fzb.y=rand()%20*10;
food.flag=1; 1表示食物没被吃的状态,0表示已吃的状态
}
//绘制食物
void DrawFood(){
//绘制圆角矩形
setfillcolor(YELLOW);
fillroundrect(food.fzb.x,food.fzb.y,food.fzb.x+10,food.fzb.y+10,10,10); }
//蛇吃食物
void EatFood(){
//判断蛇头和食物是否重合
if(snake.szb[0].x==food.fzb.x&&snake.szb[0].y==food.fzb.y){
snake.n++; //蛇身长度加1 food.flag=0; 食物标记为0表示已吃
}
}
  • 死亡机制
//撞墙
int KnockWall(){
for(int i=0;i<snake.n;i++){
if(snake.szb[i].x>200||snake.szb[i].x<0||snake.szb[i].y>200||snake.szb[i].y<0){
//如果蛇头的坐标值超出窗口的坐标值,就返回错误
return 0;
}
}
}
//咬到自己
int EatSelf(){
for(int i=1;i<snake.n;i++){
if(snake.szb[0].x==snake.szb[i].x&&snake.szb[0].y==snake.szb[i].y){
//循环判断蛇头坐标是否与蛇身某部分重合,若重合则放回错误
return 0;
}
}
}
  • 主函数
int main(){
InitSnake(); //初始化
while(1){
while(!kbhit()){ //未改变蛇的方向之前
if(food.flag==0){
CoorFood();
}
cleardevice(); //先清屏,才能保证之前绘制的蛇身不会显示出来
MoveSnake(); //先移动蛇的各个坐标
DrawFood(); //绘制食物
DrawSnake(); //再绘制蛇身
if(!KnockWall()||!EatSelf()) //死亡机制
break;
EatFood(); //吃掉食物后,蛇和食物的变化
Sleep(150); //设置蛇的移动速度
}
while(!KnockWall()||!EatSelf()){
outtextxy(100,100,"YOU DIED!"); //如果蛇吃到自己或撞墙则在窗口显示YOU DIED!
} ChangeSnakeCh(); //通过键盘上下左右键来移动蛇
} return 0;
}

基于EasyX库的贪吃蛇游戏——C语言实现的更多相关文章

  1. 贪吃蛇游戏——C语言双向链表实现

    采用了双向链表结点来模拟蛇身结点: 通过C语言光标控制函数来打印地图.蛇身和食物: /************************** *************************** 贪吃 ...

  2. easyx图形库做贪吃蛇游戏

    编程总是对着一个黑窗口,可以说是非常乏味了,于是喵喵就翻出来了以前用easyx图形库做图形界面的贪吃蛇游戏. 不过大家只是当做提高编程的乐趣来学习吧,想进一步做的话可以学习QT,还有其他的框架. 这是 ...

  3. 贪吃蛇游戏C语言源代码学习

    源代码下载地址为:www.clang.cc 阅读学习了源代码,并做了简单的注释和修改,里面只用了链表数据结构,非常适合C语言入门者学习阅读. 程序可在VS2013下编译运行. #include< ...

  4. 基于React的贪吃蛇游戏的设计与实现

    代码地址如下:http://www.demodashi.com/demo/11818.html 贪吃蛇小游戏(第二版) 一年半前层用react写过贪吃蛇小游戏https://github.com/ca ...

  5. Qt 学习之路 2(34):贪吃蛇游戏(4)

    Qt 学习之路 2(34):贪吃蛇游戏(4) 豆子 2012年12月30日 Qt 学习之路 2 73条评论 这将是我们这个稍大一些的示例程序的最后一部分.在本章中,我们将完成GameControlle ...

  6. WebGL实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  7. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  8. Qt 学习之路 2(31):贪吃蛇游戏(1)

    Qt 学习之路 2(31):贪吃蛇游戏(1) 豆子 2012年12月18日 Qt 学习之路 2 41条评论 经过前面一段时间的学习,我们已经了解到有关 Qt 相当多的知识.现在,我们将把前面所讲过的知 ...

  9. Linux平台下贪吃蛇游戏的运行

    1.参考资料说明: 这是一个在Linux系统下实现的简单的贪吃蛇游戏,同学找帮忙,我就直接在Red Hat中调试了一下,参考的是百度文库中"maosuhan"仁兄的文章,结合自己的 ...

随机推荐

  1. EXCHANGE 2013 队列

    每当咱在Exchange里查看队列的时候,我们会看到队列分成好几个组,每个邮箱数据库都有自己的目标队列,DAG.AD站点也是,AD林也是一个队列,最后最多的就是外部SMTP域队列. 当传输服务处理队列 ...

  2. Docker简介与搭建

    Docker定义 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相 ...

  3. 关于Linq中First、FirstOrDefault;Single、SingleOrDefault等方法的说明

    关于Linq中First.FirstOrDefault:Single.SingleOrDefault等方法的说明 这里以First.FirstOrDefault进行说明,其他类似. 1.First:取 ...

  4. java list.remove移除失败

    1. resultList.remove(i) 移除失败说明 当i为Integer类型时,通过观察源码发现当找不到该类型时就会自动去找Object类型,即remove(object),因为集合中不存在 ...

  5. 【[SCOI2016]背单词】

    这是一道贪心题 刚开始yy出来一个比较\(sb\)的贪心 之后发现它错了 首先这道题得先把题面翻译成人话 如果存在一个单词是它的后缀,且当前没被填入,代价为\(n*n\): 如果不存在一个单词是它的后 ...

  6. POJ3041 Asteroids(匈牙利算法)

    嘟嘟嘟 虽然我已经会网络流了,但是还是学了一个匈牙利算法. --就跟我会线段树,但还是学了树状数组一样. 其实匈牙利算法挺暴力的.简单来说就是先贪心匹配,然后如果左部点\(i\)匹配不上了,就尝试更改 ...

  7. 【vue.js】入门

    慕课网视频学习笔记:http://www.imooc.com/learn/694 1.将html.js.css写到一个后缀名.vue的文件中,区分这三种类型是通过<template>.&l ...

  8. ubuntu中phpstorm和sublime快速启动

    ubuntu gnome桌面 + dash to dock扩展 下载安装包手动安装phpstorm会遇到无法固定到dash上的情况(运行软件时在dash右击未出现Add to Favoriates) ...

  9. spring boot 2.x拦截器导致静态资源404终极解决办法

    首先添加application文件static路径,我的是yml文件 spring: mvc: static-path-pattern: /static/**然后注册拦截器类如下方法; @Overri ...

  10. python codecs模块 ---处理数据写入文件时会有编码不统一的问题

    我们用open方法打开文件有时候会有一些问题,因为open打开文件只能写入str类型,而不会管字符串是什么编码方式. 示例: >>> fr = open('test.txt','a' ...