基于c语言和easyx库的贪吃蛇程序的实现

```基于c语言和easyx库的贪吃蛇程序的实现

大学课程中所编写的贪吃蛇游戏

游戏界面截图
基于c语言和easyx库的贪吃蛇程序的实现_第1张图片

/********************************************************************************
* @File name: Snake
* @Description:基于c语言和easyx库的贪吃蛇程序的实现
* @Author: Sky_Codes
* @Version: 0.51
* @Date: 2019-12-01
********************************************************************************/


#include
#include
#include//easyx图形库
#include//媒体库
#include
#include
#include
#pragma comment (lib,"Winmm.lib")


#define INIT_X  800//初始化界面宽度
#define INIT_Y  480//初始化界面高度
#define SNAKE_LEN 3 //初始化小蛇长度

/*声明结构体*/
typedef enum ch  //枚举 按键的数值
{
	up = 119,  //向上 W
	down = 115,//向下 S
	left = 97, //向左 A
	right = 100,//向右 D
	esc = 27,  //退出 ESC
	addSpeed = 113,//加速 Q
	subSpeed = 101,//减速 E
	stop = 32  //暂停 space空格
}Ch;


struct  coor //坐标
{
	int x; int y;//x、y坐标数值
};


struct food  //食物结构体
{
	struct coor fcr;//食物的坐标
	int flag;//判断食物是否被吃,被吃后置反
}Food;


struct snake  //小蛇结构体
{
	struct coor scr[100];//蛇身长度限制
	int len;//小蛇实际长度
	Ch ch;//小蛇当前的朝向
	int score;//得分
	int speed;//速度

}Snake;

/*声明函数*/
void playMusic();/*播放背景音乐*/
void initGame();//初始化游戏界面
void initWelcome();//初始化进入页面
void playWhile();//游戏中循环函数
void initSnake();//初始化小蛇
void snakeMove(); //小蛇的移动
void snakeDraw();//画出小蛇
void getKey();//得到键值
void randFood();//随机食物
void foodDraw();//画出食物
void eatFood();//吃到食物
int eatSelforWall();//吃到自己或者撞墙
void getFlagKey();//按键去除移动其他按键的功能实现
void gameEnd();//死亡后是否结束游戏或者再开始
void gameOver();  //游戏结束
void againInit();//死亡后再进行游戏,进行初始化
void display_msg();//展示信息


/*声明所需各个需求变量*/
char scroe_s[100] = {'0'};//分转换字符数组中间变量
char font[2][10] = { "宋体","黑体" };//字体选择
char goder[20] = "【作者】SKY";//欢迎界面信息
char vision[20] = "【版本】0.51";//欢迎界面信息
char gameName[20] = "C---贪吃蛇";//欢迎界面标题
char songBgm[2][30] = { "open BGM.mp3 alias ACE" ,"play ACE repeat" };//背景音乐
char speak[5][20] = { "【得分】","【速度】","【长度】" };//游戏界面的数据展示
char speak2[5][20] = { "【最高得分】","【最快速度】","【最佳长度】" };//游戏界面的数据展示
int flagKey = 0;//判断除去方向按键其他按键的选择标识符
int speed = 100;//小蛇速度
int maxScore = 0, maxSpeed = 100, maxLen = 3;//保留最佳成绩


/*******************************************************
*
* Function name :main
* Description   : 程序主函数
* Return          :0 正常退出
**********************************************************/

int main()
{	
	playMusic();//播放音乐

	initWelcome();//欢迎界面
	system("pause");//用户按任意键进入游戏
	cleardevice();//清除界面
	closegraph();//关闭此画布

	initgraph(INIT_X, INIT_Y);//初始化游戏窗口大小900*600
	initGame();//初始化画布
	initSnake();//初始化小蛇
	Food.flag = 1;//置食物标识符为1,去生成第一个随即食物*/
	
	playWhile();//游戏进行期间

	return 0;

}


/*******************************************************
*
* Function name :initWelcome
* Description   : 初始化进入页面,向玩家展示操作规则
* Return          :无
**********************************************************/

void initWelcome()
{

	initgraph(INIT_X,INIT_Y);//建立画布
	setfillcolor(RGB(255,200, 215));//调节画布颜色

	solidrectangle(0, 0, INIT_X,INIT_Y/2);//提取画布上半部矩形区域
	setcolor(RGB(120, 200, 150));
	settextstyle(40, 20, font[0]);//设置字体属性
	setbkmode(TRANSPARENT);//设置背景为透明

	outtextxy(110, 50, gameName);//在具体位置输出相关文字
	settextstyle(20, 10, font[1]);
	outtextxy(110, 100, goder);
	outtextxy(110, 130, vision);

	setfillcolor(RGB(255,200, 215));//调节画布颜色
	solidrectangle(0, INIT_Y/2, INIT_X, INIT_Y);//提取画布下半部矩形区域ju

	RECT r = {0,INIT_Y/2,400,INIT_Y};//得到在下半部分矩形中的部分区域
	settextcolor(BLACK);//设置字体颜色
	settextstyle(15, 0, "仿宋");//设置字体大小、风格
	drawtext(_T("【功能按键】\n W->上 S->下 \n A->左 D->右\n Q->加速 E->减速\n 空格->暂停 ESC->退出\n"), &r, DT_LEFT);//在r矩阵中展示的语句

	RECT r2= { 0,INIT_Y/2+100,400,INIT_Y};
	settextcolor(BLACK);
	settextstyle(20, 0, "仿宋");//设置字体大小、风格
	drawtext(_T("【提示】\n此游戏在英文输入法下进行操控\n按任意键进入游戏\n"), &r2, DT_LEFT);//展示的语句


}

/*******************************************************
*
* Function name :initGame
* Description   : 初始化游戏界面,在界面中设置游戏进程中向玩家展示的语句
* Return          :无
**********************************************************/

void initGame()
{
	/*裁剪得到非游戏区域*/
	setfillcolor(0xe6b8af);//设置填充颜色
	solidrectangle(600, 0, 800, 480);//绘制矩形在裁剪区
	//setbkcolor(RGB(200, 150, 120));
	setcolor(RED);//设置颜色

	settextstyle(30, 15, font[0]);//设置字体大小、风格
	setbkmode(TRANSPARENT);//设置背景为透明
	outtextxy(625, 50, gameName);//设置游戏名称

	/*提示语句区域*/
	RECT r = { 625, 100, 780, 200 };//创建一个矩形放置语句
	settextstyle(15, 0, font[1]);//设置字体大小、风格
	drawtext(_T("简单的贪吃蛇小游戏\n祝你好运\n"), &r, DT_CENTER);//展示的语句
	sprintf(scroe_s, "%d", Snake.score);
	outtextxy(600, 150, speak[0]);
	outtextxy(680, 150, scroe_s);
	sprintf(scroe_s, "%d", Snake.speed);
	outtextxy(600, 180, speak[1]);
	outtextxy(680, 180, scroe_s);
	sprintf(scroe_s, "%d", Snake.len + 1);
	outtextxy(600, 210, speak[2]);
	outtextxy(680, 210, scroe_s);

	RECT r2 = { 600, 240, 780, 480 };//创建一个矩形放置语句
	settextstyle(15, 0, font[1]);//设置字体大小、风格
	drawtext(_T("【功能按键】\n W->上 S->下 \n A->左 D->右\n Q->加速 E->减速\n 空格->暂停 ESC->退出\n"), &r2, DT_LEFT);//展示的语句

	/*游戏区域的属性设置,背景颜色、区域大小*/
	setfillcolor(0xf4cccc);
	solidrectangle(0, 0, 600, 480);//绘制矩形

}

/*******************************************************
*
* Function name :againInit
* Description   : 小蛇死亡后再进行游戏,进行相关属性的初始化
* Return          :无
**********************************************************/
void againInit()
{
	initGame();//初始化画布
	initSnake();//初始化小蛇
	Food.flag = 1;//置食物标识符为1,去生成第一个随即食物*/
	playWhile();//进入游戏

}

/*******************************************************
*
* Function name :playWhile
* Description   : 玩家游戏中循环函数,在玩家游戏时做出相应的动作响应玩家
* Return          :无
**********************************************************/
void playWhile()
{
	while (1)
	{
		while (!_kbhit())//判断是否有按键输入
		{
			snakeMove();//小蛇的移动
			eatFood();//判断是否吃到食物
			if (Food.flag == 1)//标识符为1
			{
				randFood(); //生成随机食物坐标
			}
			if (eatSelforWall())//函数返回值为1,游戏结束
			{
				gameEnd();//死亡后是否结束游戏或者再开始
			}
			foodDraw();//画出食物
			Sleep(speed);//延时
			//cleardevice();//以背景色清空画布
			//initGame();	
			display_msg();//展示此时小蛇的属性信息
		}
		getKey();//玩家键值的输入
	}

}

/*******************************************************
*
* Function name :display_msg
* Description   : 玩家游戏过程中,对小蛇属性的及时的刷新展示
* Parameter     :无
* Return          :无
**********************************************************/
void display_msg()
{
	/*写入一个新的矩形,覆盖之前的矩形,再写入小蛇的属性数据*/
	setfillcolor(0x90b1e8);
	solidrectangle(600,150,800,230);
	settextcolor(BLACK);
	sprintf(scroe_s, "%d", Snake.score);
	outtextxy(600, 150, speak[0]);
	outtextxy(680, 150, scroe_s);
	sprintf(scroe_s, "%d", Snake.speed);
	outtextxy(600, 180, speak[1]);
	outtextxy(680, 180, scroe_s);
	sprintf(scroe_s, "%d", Snake.len + 1);
	outtextxy(600, 210, speak[2]);
	outtextxy(680, 210, scroe_s);

}


/*******************************************************
*
* Function name :initSnake
* Description   :对小蛇的各项属性进行初始化
* Parameter         :无
* Return          :无
**********************************************************/
void initSnake()
{
	//设置小蛇的属性
	setcolor(WHITE);
	setfillcolor(WHITE);
	fillroundrect(200, 100, 210, 110,8,6);
	Snake.len = SNAKE_LEN;
	Snake.scr[0].x = 200;
	Snake.scr[0].y = 100;
	Snake.ch = down;
	Snake.score = 0;
	Snake.speed = 100;
}


/*******************************************************
*
* Function name :snakeMove
* Description   : 小蛇移动时,方向的确定和改变小蛇每个关节的坐标
*					并且将蛇尾消影
* Parameter      :无
* Return          :无
**********************************************************/
void snakeMove()
{
	int i;

	setfillcolor(0xf4cccc);	//对蛇尾进行消影处理
	//fillrectangle(Snake.scr[Snake.len].x,Snake.scr[Snake.len].y, Snake.scr[Snake.len].x+10, Snake.scr[Snake.len].y+10 );
	solidrectangle(Snake.scr[Snake.len].x,Snake.scr[Snake.len].y, Snake.scr[Snake.len].x+10, Snake.scr[Snake.len].y+10 );

	for (i = Snake.len; i > 0; i--)	//改变小蛇的各个节位坐标,使之移动
	{
		Snake.scr[i].x = Snake.scr[i - 1].x;
		Snake.scr[i].y = Snake.scr[i - 1].y;
	}

	switch (Snake.ch)	//判断小蛇此时的方向,使之相应的坐标变化
	{
	case up:  Snake.scr[0].y -= 10;
		break;
	case down:Snake.scr[0].y += 10;
		break;
	case left:Snake.scr[0].x -= 10;
		break;
	case right:Snake.scr[0].x += 10;
		break;
	}
	snakeDraw();//画出改变后的小蛇
	
}

/*******************************************************
*
* Function name :snakeDraw
* Description   : 画出位置改变后的小蛇,并随机改变小蛇每节的颜色
* Return          :无
**********************************************************/
void snakeDraw()
{
	srand((unsigned)time(NULL));
	int i,color;
	for (i = Snake.len; i >= 0; i--)
	{
		color = rand()%4;	//随机选择设置小蛇每节颜色
		switch(color)
		{
			case 0:setfillcolor(RGB(30, 144, 255)); break;
			case 1:setfillcolor(RGB(245, 5, 90)); break;
			case 2:setfillcolor(RGB(125, 62, 74)); break;
			case 3:setfillcolor(RGB(20, 7, 9)); break;
		}
		//fillrectangle(Snake.scr[i].x, Snake.scr[i].y, Snake.scr[i].x + 10, Snake.scr[i].y + 10);
		fillroundrect(Snake.scr[i].x, Snake.scr[i].y, Snake.scr[i].x + 10, Snake.scr[i].y + 10,8,6);
	}
}

/*******************************************************
*
* Function name :getKey
* Description   : 对于玩家输入的按键处理,进行相应的响应
* Parameter     :无
* Return        :无
**********************************************************/
void getKey()
{
	int getkey;
	getkey = _getch();//此处使用了c++改变后的_getch()语句,得到玩家输入的键值,无需敲打回车

	switch (getkey)//判断玩家输入的键值,如果与小蛇此时的方向相反,不给予响应
	{
	case up: if (Snake.ch != down) Snake.ch = up;
		break;
	case down:if (Snake.ch != up) Snake.ch = down;
		break;
	case left:if (Snake.ch != right) Snake.ch = left;
		break;
	case right:if (Snake.ch != left) Snake.ch = right;
		break;
	case esc:flagKey = 1;
		break;
	case addSpeed:flagKey = 2;
		break;
	case subSpeed:flagKey = 3;
		break;
	case stop:flagKey = 4;
		break;
	}
	getFlagKey();//除去方向按键其他功能性按键的实现
}

/*******************************************************
*
* Function name :randFood
* Description   : 随机生成食物坐标
* Parameter     :无
* Return          :函数返回值的说明
**********************************************************/
void randFood()
{
	srand((unsigned)time(NULL));//种子
	//得到的随机数应为10的倍数
	Food.fcr.x = rand() % (600 / 10) * 10;
	Food.fcr.y = rand() % (480 / 10) * 10;
	Food.flag = 1;//重新将食物标识符设为1,表示已生成一个食物

}


/*******************************************************
*
* Function name :foodDraw
* Description   : 在画布中画出食物
* Parameter     :无
* Return          :函数返回值的说明
**********************************************************/
void foodDraw()
{
	//cleardevice();
	fillrectangle(Food.fcr.x, Food.fcr.y, Food.fcr.x + 10, Food.fcr.y + 10);//画出食物
	Food.flag = 0;//食物标识符置反
}

/*******************************************************
*
* Function name :函数名称
* Description   : 小蛇吃到食物进行蛇身的加长和得分的增加和食物的标识符变化
* Parameter     :无
* Return          :无
**********************************************************/
void eatFood()
{
	if (Snake.scr[0].x == Food.fcr.x && Snake.scr[0].y == Food.fcr.y)//蛇头与食物相遇的判断
	{
		Snake.len++;//小蛇长度加1
		Snake.score += 10;//增加得分
		Food.flag = 1;//置食物标识符
	}
}


/*******************************************************
*
* Function name :eatSelforWall
* Description   : 判断是否吃到自己或者撞墙
* Return        :返回1 撞墙或者蛇头与自身相遇 返回0 游戏继续
**********************************************************/
int eatSelforWall()
{
	int i;//循环使用变量
	//是否撞墙
	if (Snake.scr[0].x == 0 || Snake.scr[0].y == 480 || Snake.scr[0].x == 600 || Snake.scr[0].y == 0)
		return 1;
	//是否吃到自己
	for (i = 1; i < Snake.len; i++)
	{
		if (Snake.scr[0].x == Snake.scr[i].x && Snake.scr[0].y == Snake.scr[i].y)
			return 1;
	}
	return 0;
}


/*******************************************************
*
* Function name :getFlagKey
* Description   : 除去方向按键其他功能性按键的实现
* Return        :无
**********************************************************/
void getFlagKey()
{
	if (flagKey == 1)	//退出 ESC
	{
		flagKey = 0; closegraph(); exit(0);
	}

	else if (flagKey == 2)	//加速 Q
	{
		flagKey = 0; speed -= 10; Snake.speed += 10;
		if (speed <= 50) { speed = 50; Snake.speed = 150; }
	}
	
	else if (flagKey == 3)//减速 E
	{
		flagKey = 0; speed += 10; Snake.speed -= 10;
		if (speed >= 150) { speed = 150; Snake.speed = 50; }
	}
	
	else if (flagKey == 4)//space空格 
	{ flagKey = 0; system("pause"); }
}


/*******************************************************
*
* Function name :gameEnd
* Description   : 死亡后是否结束游戏或者再开始
* Parameter     :无
* Return          :无
**********************************************************/
void gameEnd()
{
	/*得到每次游戏后的各项指标的最大值*/
	maxScore = maxScore > Snake.score ? maxScore : Snake.score;
	maxLen = maxLen > Snake.score ? maxLen : Snake.len;
	maxSpeed = maxSpeed > Snake.speed ? maxSpeed : Snake.speed;
	
	/*输出提示信息*/
	RECT r3 = { 100,100,400,300 };
	setbkmode(TRANSPARENT);//设置背景为透明
	settextcolor(WHITE);
	settextstyle(50, 25, "黑体");
	drawtext(_T("游 戏 结 束"), &r3, DT_CENTER);

	RECT r4 = { 100,300,400,600 };

	settextstyle(30, 15, "仿宋");
	drawtext(_T("【双击】\nE【再来一局】\nQ【退出游戏】\n"),&r4,DT_LEFT);
	system("pause");
	int getKey;
	getKey = _getch();//得到玩家键值,反馈相应信息
	switch (getKey)
	{
		
		case 113: gameOver();//退出
			break;
		
		case 101: againInit();//再来一局
			break;
	}

}


/*******************************************************
*
* Function name :gameOver
* Description   : 游戏结束函数
* Return        :无
**********************************************************/
void gameOver()
{

	//system("pause");
	cleardevice();//清空并关闭画布
	closegraph();
	initgraph(500,200);//建立结束画布

	int x=400, y=20, speed=0,r=50,flag=0;//设置跳动小球的参数
	while (1)/*输出本次游戏的最佳成绩和小球弹跳动画*/
	{
		
		setfillcolor(RGB(47, 79, 79));
		settextstyle(40, 20, font[0]);
		outtextxy(120, 50, "游戏结束");
		settextcolor(RGB(255, 255, 224));
		settextstyle(20, 10, font[1]);
		sprintf(scroe_s, "%d", maxScore);
		outtextxy(80, 100, speak2[0]);
		outtextxy(200, 100, scroe_s);
		sprintf(scroe_s, "%d", maxSpeed);
		outtextxy(80, 140, speak2[1]);
		outtextxy(200, 140, scroe_s);
		sprintf(scroe_s, "%d", maxLen+1);
		outtextxy(80, 180, speak2[2]);
		outtextxy(200, 180, scroe_s);


		/*小圆运动动画*/
		circle(x, y, 30);
		Sleep(50);
		if (y > 180) { flag = 1; speed = -speed; }
		if (y < 20) { flag = 0; speed = -speed; }
		printf("%d %d\n", speed,y);

		y = y + speed++;
		if (y < 12) y = 20;
		cleardevice();
	}


}


/*******************************************************
*
* Function name :playMusic
* Description   : 循环播放背景音乐
* Return        :无
**********************************************************/
void playMusic()
{
	//调用函数,播放音乐
	mciSendString(songBgm[0], NULL, 0, NULL);
	mciSendString(songBgm[1], NULL, 0, NULL);
}

你可能感兴趣的:(基于c语言和easyx库的贪吃蛇程序的实现)