基于EasyX的贪吃蛇游戏

一、预备知识

1.使用EasyX必须要知道的一些基础函数
2.选择结构 if , switch
3.循环结构 for, while
4.多维数组 arr1[N], arr2[N][N] , arr3[N][N][N]
5.函数封装

二、游戏逻辑

想要写出推箱子,首先要知道推箱子游戏都有哪些元素和规则

1.贪吃蛇元素

素材
1.蛇身 2.蛇头 3.墙壁 4.食物
有了素材,首先拿数字对应起来,再来一个加载资源函数Loadimg()

#define SIZE 25
IMAGE img[8];//存放图片变量

enum element
{
	space=0,//空地
	food=-4,//食物
	wall=-1,//墙壁
	head=1, //蛇头
	move_rt=1,//向右
	move_dw=2,//向下
	move_lt=3,//向左
	move_up=4,//向上
};
void Loadimg()
{
	loadimage(&img[0],L"./images/0.jpg",SIZE,SIZE);
	loadimage(&img[1],L"./images/1.jpg",SIZE,SIZE);
	loadimage(&img[2],L"./images/2.jpg",SIZE,SIZE);
	loadimage(&img[3],L"./images/3.jpg",SIZE,SIZE);
	loadimage(&img[4],L"./images/4.jpg",SIZE,SIZE);
	loadimage(&img[5],L"./images/5.jpg",SIZE,SIZE);
	loadimage(&img[6],L"./images/6.jpg",SIZE,SIZE);
	loadimage(&img[7],L"./images/7.jpg",SIZE,SIZE);
}

2.贪吃蛇规则

1.按键可以改变蛇上、下、左、右移动
2.蛇默认沿当前方向移动
3.蛇吃到食物身体边长
4.蛇撞到墙或者自己的身体游戏结束

三、游戏设计

知道游戏元素和规则就可以开始设计游戏了

1.地图设计

地图是一个二维数组,蛇的身体一次用1,2,3,4表示,-1表示墙壁,0表示空地

#define NUM 21

int map[NUM][NUM]=
{
	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-1,
	-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
};

地图初始化好了,开始贴图,根据移动方向的不同,贴不同的蛇头,写个Drawmap()函数

int move=1;//默认向右移动,1向右移动,2向下,3向左,4向右

void Drawmap()
{
	for(int i=0;i<NUM;i++)
	{
		for(int j=0;j<NUM;j++)
		{
			if(map[i][j]==wall)//贴墙
				putimage(j*SIZE,i*SIZE,&img[6]);
			else if(map[i][j]>1)//贴身
				putimage(j*SIZE,i*SIZE,&img[0]);
			else if(map[i][j]==food)//贴食物
				putimage(j*SIZE,i*SIZE,&img[7]);
			else if(map[i][j]==head)//贴头
				if(move==move_rt)//向右移动
					putimage(j*SIZE,i*SIZE,&img[move_rt]);
				else if(move==move_dw)//向下移动
					putimage(j*SIZE,i*SIZE,&img[move_dw]);
				else if(move==move_lt)//向左移动
					putimage(j*SIZE,i*SIZE,&img[move_lt]);
				else if(move==move_up)//向上移动
					putimage(j*SIZE,i*SIZE,&img[move_up]);
		}
	}
}

地图上还需要有蛇吃的食物,用随机函数产生食物,需要包含<time.h>,写个产生食物函数Producefood()

void Producefood()//产生食物
{
	srand((unsigned)time(NULL));//根据时间设置随机数种子
	for(int k=0;k<1; )
	{
		int x=rand()%(NUM-4) +2;//生成2 ~ 18的随机数
		int y=rand()%(NUM-4) +2;//为避免产生相同的坐标,采用下面的方式
		if(map[x][y]==0)
		{//如果是空地
			map[x][y]=food;
			k++;//食物设置成功才加加
		}
	}
}

2.移动设计

上文提到

1.按键可以改变蛇上、下、左、右移动
2.蛇默认沿当前方向移动

但是我们知道,蛇向某个方向移动的时候,不能往该方向的相反方向移动,写一个函数Controlsnake()用键盘控制蛇移动

void Controlsnake()
{
	char ch =_getch();
	if( (ch=='w' || ch=='W' || ch==72) && move!=move_dw)
	//如果想往上移动且现在不在向下移动
		move=move_up;//向上移动
	else if( (ch=='s' || ch=='S' || ch==80) && move!=move_up)
	//如果想往下移动且现在不在向上移动
		move=move_dw;//向下移动
	else if( (ch=='a' || ch=='A' || ch==75) && move!=move_rt)
	//如果想往左移动且现在不在向右移动
		move=move_lt;//向左移动
	else if( (ch=='d' || ch=='D' || ch==77) && move!=move_lt)
	//如果想往右移动且现在不在向左移动
		move=move_rt;//向右移动
}

上文提到

3.蛇吃到食物身体边长
4.蛇撞到墙或者自己的身体游戏结束

下面就要划重点了,我们如何让蛇在二维数组上移动呢?
此并非我自己想出来的,来源mooc,详情见下方链接

假设小蛇元素为54321,其中1为蛇头、5432为蛇身、最大值5为蛇尾。首先将所有大于0的元素加1,得到65432;将最大值6变为0,即去除了原来的蛇尾;再根据对应移动方向,将2对应方向的元素由0变成1;如此即实现了小蛇的移动。小蛇向上移动的双应流程如图3-14所示。

mooc
基于以上的描述,我们就可以写出蛇的移动函数Snakemove()

int oldheadx,oldheady,newheadx,newheady,tailx,taily;
int score=0,speed=150;//当前得分,和蛇的移动速度,越小速度越快
TCHAR s[100];//存放消息提示语句

void Snakemove()
{
	//遍历地图把地图上正数全+1
	for(int i=0;i<NUM;i++)
	{
		for(int j=0;j<NUM;j++)
		{
			if(map[i][j]>0)
				map[i][j]++;
		}
	}
	//最大数是尾巴,找到最大数坐标,移动后变成0
	int max=0;
	for(int a=0;a<NUM;a++)
	{
		for(int b=0;b<NUM;b++)
		{
			if(map[a][b]==2)
			{
				oldheadx=a;
				oldheady=b;//旧蛇头坐标
			}
			if(map[a][b]>max)
			{
				max=map[a][b];
				tailx=a;
				taily=b;//蛇尾坐标
			}
		}
	}
	//根据移动方向计算新蛇头坐标的位置
	if(move==move_rt)//如果向右移动
	{
		newheadx=oldheadx;
		newheady=oldheady+1;
	}
	else if(move==move_dw)//如果向下移动
	{
		newheadx=oldheadx+1;
		newheady=oldheady;
	}
	else if(move==move_lt)//如果向左移动
	{
		newheadx=oldheadx;
		newheady=oldheady-1;
	}
	else if(move==move_up)//如果向上移动
	{
		newheadx=oldheadx-1;
		newheady=oldheady;
	}

	if(map[newheadx][newheady]==food)
	{//如果吃到食物
		PlaySound(L"./images/eat.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放吃到食物音效
		score++;//得分增加
		Producefood();//产生新的食物
		//尾部不变
	}
	else if(map[newheadx][newheady]==wall || map[newheadx][newheady]>0 )
	{//如果撞墙或撞自己
		mciSendString(_T("close ./images/bg.mp3"), 0, 0, 0);//关闭背景音乐
		PlaySound(L"./images/over.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放结束音效
		_stprintf_s(s, _T("游戏结束,你的得分:%d分"), score);
		MessageBox(NULL,s,_T("游戏提示"),MB_OK | MB_SYSTEMMODAL) ;//显示得分
		system("pause");
	}
	else
	{//没吃到食物 游戏没结束
		map[tailx][taily]=0;//尾巴变成0
	}
	map[newheadx][newheady]=1;//新的蛇头是1
	oldheadx=newheadx;
	oldheady=newheady;//新头坐标变为旧坐标
}

3.速度设计

我们用Sleep()函数来控制蛇移动的速度,写一个根据得分改变速度函数Changespeed()

void Changespeed()
{
	if(score>=5 && score<10)
		speed=130;
	else if(score>=10 && score<15)
		speed=110;
	else if(score>=15 && score<20)
		speed=90;
	else if(score>=20 && score<25)
		speed=70;
	else if(score>=25 && score<30)
		speed=50;
	else if(score>=30)
		speed=30;
	Sleep(speed);
}

4.整体设计

下面把上面的函数组合起来就是贪吃蛇游戏,再来点音乐

#include<time.h>
#include<easyx.h>//图形库
#include<conio.h>//按键
#include<mmsystem.h>//音乐
#pragma comment(lib,"winmm.lib")//库文件

int main()
{
	initgraph(NUM*SIZE,NUM*SIZE);//创建地图大小的窗口
	Loadimg();//加载资源
	setbkcolor(WHITE);//设置背景白色
	Producefood();//产生食物
	//循环播放背景音乐
	mciSendString(L"open ./images/bg.mp3 ", 0, 0, 0);
	mciSendString(_T("play ./images/bg.mp3 repeat"), 0, 0, 0);
	while(true){
		//绘制界面
		BeginBatchDraw();//批量绘图开始
		cleardevice();//清理屏幕
		Drawmap();//绘制地图
		EndBatchDraw();//批量绘图结束
		if (_kbhit())//获取按键消息
		{
			Controlsnake();//改变蛇的移动
		}	
		Snakemove();//蛇默认移动
		Changespeed();//根据得分改变速度
	}
	return 0;
}

把上面所有代码复制到一个cpp文件里,再把素材改好命名放到images文件夹里,images文件夹在cpp文件旁边,就可以编译运行了!

图片音乐素材及可执行程序需要的点击下载

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值