基于EasyX库的贪吃蛇游戏——C语言实现
接触编程有段时间了,一直想学习怎么去写个游戏来练练手。在看了B站上的教学终于可以自己试试怎么实现贪吃蛇这个游戏了。好了,废话不多说,我们来看看如何用EasyX库来实现贪吃蛇。
一、准备
- 工具vc++6.0
- 安装库文件
- EasyX库安装链接
- 可以安装任意版本,本人安装的是2018春分版
- 这是一个简单易学的一个图形库,相信对于大家学习来说应该不成问题
- 准备工作做好后接下来就得弄清楚游戏工作机制了
二、基本介绍
在这里我们需要明白EasyX库的基本知识,其次我们还有了解游戏的工作原理,不能盲目的直接写代码,需要一步步的思考,比如蛇是如何绘制、移动的;食物是怎么产生的;蛇吃了食物会怎样;死亡机制等等
EasyX库介绍
- 首先我们来讲讲EasyX库的坐标概念
- 物理坐标
- 简单来说,物理坐标就是以窗口的左上角为原点,以水平向右为x轴,竖直向下为y轴,以像素为单位
- 逻辑坐标
- 逻辑坐标和物理坐标是一一对应的,不过逻辑坐标是以点为单位
- 物理坐标
- 颜色概念
- 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语言实现的更多相关文章
- 贪吃蛇游戏——C语言双向链表实现
采用了双向链表结点来模拟蛇身结点: 通过C语言光标控制函数来打印地图.蛇身和食物: /************************** *************************** 贪吃 ...
- easyx图形库做贪吃蛇游戏
编程总是对着一个黑窗口,可以说是非常乏味了,于是喵喵就翻出来了以前用easyx图形库做图形界面的贪吃蛇游戏. 不过大家只是当做提高编程的乐趣来学习吧,想进一步做的话可以学习QT,还有其他的框架. 这是 ...
- 贪吃蛇游戏C语言源代码学习
源代码下载地址为:www.clang.cc 阅读学习了源代码,并做了简单的注释和修改,里面只用了链表数据结构,非常适合C语言入门者学习阅读. 程序可在VS2013下编译运行. #include< ...
- 基于React的贪吃蛇游戏的设计与实现
代码地址如下:http://www.demodashi.com/demo/11818.html 贪吃蛇小游戏(第二版) 一年半前层用react写过贪吃蛇小游戏https://github.com/ca ...
- Qt 学习之路 2(34):贪吃蛇游戏(4)
Qt 学习之路 2(34):贪吃蛇游戏(4) 豆子 2012年12月30日 Qt 学习之路 2 73条评论 这将是我们这个稍大一些的示例程序的最后一部分.在本章中,我们将完成GameControlle ...
- WebGL实现HTML5的3D贪吃蛇游戏
js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...
- 100行JS实现HTML5的3D贪吃蛇游戏
js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...
- Qt 学习之路 2(31):贪吃蛇游戏(1)
Qt 学习之路 2(31):贪吃蛇游戏(1) 豆子 2012年12月18日 Qt 学习之路 2 41条评论 经过前面一段时间的学习,我们已经了解到有关 Qt 相当多的知识.现在,我们将把前面所讲过的知 ...
- Linux平台下贪吃蛇游戏的运行
1.参考资料说明: 这是一个在Linux系统下实现的简单的贪吃蛇游戏,同学找帮忙,我就直接在Red Hat中调试了一下,参考的是百度文库中"maosuhan"仁兄的文章,结合自己的 ...
随机推荐
- EXCHANGE 2013 队列
每当咱在Exchange里查看队列的时候,我们会看到队列分成好几个组,每个邮箱数据库都有自己的目标队列,DAG.AD站点也是,AD林也是一个队列,最后最多的就是外部SMTP域队列. 当传输服务处理队列 ...
- Docker简介与搭建
Docker定义 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相 ...
- 关于Linq中First、FirstOrDefault;Single、SingleOrDefault等方法的说明
关于Linq中First.FirstOrDefault:Single.SingleOrDefault等方法的说明 这里以First.FirstOrDefault进行说明,其他类似. 1.First:取 ...
- java list.remove移除失败
1. resultList.remove(i) 移除失败说明 当i为Integer类型时,通过观察源码发现当找不到该类型时就会自动去找Object类型,即remove(object),因为集合中不存在 ...
- 【[SCOI2016]背单词】
这是一道贪心题 刚开始yy出来一个比较\(sb\)的贪心 之后发现它错了 首先这道题得先把题面翻译成人话 如果存在一个单词是它的后缀,且当前没被填入,代价为\(n*n\): 如果不存在一个单词是它的后 ...
- POJ3041 Asteroids(匈牙利算法)
嘟嘟嘟 虽然我已经会网络流了,但是还是学了一个匈牙利算法. --就跟我会线段树,但还是学了树状数组一样. 其实匈牙利算法挺暴力的.简单来说就是先贪心匹配,然后如果左部点\(i\)匹配不上了,就尝试更改 ...
- 【vue.js】入门
慕课网视频学习笔记:http://www.imooc.com/learn/694 1.将html.js.css写到一个后缀名.vue的文件中,区分这三种类型是通过<template>.&l ...
- ubuntu中phpstorm和sublime快速启动
ubuntu gnome桌面 + dash to dock扩展 下载安装包手动安装phpstorm会遇到无法固定到dash上的情况(运行软件时在dash右击未出现Add to Favoriates) ...
- spring boot 2.x拦截器导致静态资源404终极解决办法
首先添加application文件static路径,我的是yml文件 spring: mvc: static-path-pattern: /static/**然后注册拦截器类如下方法; @Overri ...
- python codecs模块 ---处理数据写入文件时会有编码不统一的问题
我们用open方法打开文件有时候会有一些问题,因为open打开文件只能写入str类型,而不会管字符串是什么编码方式. 示例: >>> fr = open('test.txt','a' ...