基于EasyX库的贪吃蛇游戏——C语言实现

接触编程有段时间了,一直想学习怎么去写个游戏来练练手。在看了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;
}
posted @ 2018-12-19 17:35  滑稽的游戏  阅读(2349)  评论(0)    收藏  举报