欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于easyx和C语言的简易贪吃蛇游戏源码

程序员文章站 2024-03-18 10:04:10
...

一、描述

	基于easyx和C语言的简易贪吃蛇游戏源码。

二、程序要求

	1、蛇可以穿墙移动
	2、随机生成食物
	3、显示分数
	4、蛇撞到身体即死亡

三、程序设计及思路

基于easyx和C语言的简易贪吃蛇游戏源码
根据上图,我们需要:
1、创建图形窗口并设置背景颜色(根据个人选择,可以使用默认黑色背景)。
2、蛇的结构体
3、食物的结构体
4、蛇的移动、吃食物变长
5、食物重新生成
6、死亡判定
7、绘制分数等

一)蛇和食物的结构体属性

struct Snake
{
	int speed;		//蛇的移动速度
	int dir;		//蛇的方向
	int r;			//蛇的大小
	int size;		//蛇的长度
	POINT num[MAX];	//每一节蛇的坐标
	int score;		//分数
	int flag;		//存在标志
}snake;

struct  Food
{
	int x;			//食物的坐标
	int y;
	int r;			//实物的大小
	COLORREF color;	//实物的颜色

二)初始化

//游戏初始化
void GameInit()
{
	mciSendString("close DIE", 0, 0, 0);
	mciSendString("open ./ress/snake_bgm.mp3 alias BGM", 0, 0, 0);
	mciSendString("play BGM repeat", 0, 0, 0);
	srand(GetTickCount());			//设置随机数种子
	initgraph(WIDTH, HEIGHT);
	setbkcolor(RGB(140, 186, 236));	//设置背景颜色
	settextcolor(BLACK);			//设置字体颜色及样式
	settextstyle(30, 0, "黑体");
	//蛇初始化
	snake.dir = UP;
	snake.speed = 16;
	snake.r = 8;
	snake.size = 3;
	snake.num[0] = { WIDTH / 2, HEIGHT / 2 };
	snake.num[1] = { WIDTH / 2, HEIGHT / 2 + 16};
	snake.num[2] = { WIDTH / 2, HEIGHT / 2 + 32 };
	snake.score = 0;
	snake.flag = 1;
	//食物初始化
	food.x = rand() % WIDTH;
	food.y = rand() % HEIGHT;
	food.r = 8;
	food.color = RGB(rand() % 255, rand() % 255, rand() % 255);
}

三)游戏绘制

//游戏绘制
void GameDraw()
{
	BeginBatchDraw();
	cleardevice();

	//绘制分数
	char score[100] = "";
	sprintf(score, "分数:%d", snake.score);
	outtextxy(0, 0, score);

	//绘制蛇
	if (snake.flag)
	{
		for (int i = 0; i < snake.size; i++)
		{
			setfillcolor(BLACK);
			solidcircle(snake.num[i].x, snake.num[i].y, snake.r);
		}
	}
	
	//绘制食物
	setfillcolor(food.color);
	solidcircle(food.x, food.y, food.r);
		
	EndBatchDraw();
}

四)蛇的移动

//蛇移动
void SnakeMove()
{
	//移动蛇身
	for (int i = snake.size - 1; i > 0; i--)
	{
		snake.num[i] = snake.num[i - 1];
	}
	//移动蛇头
	switch (snake.dir)
	{
	case UP:
		snake.num[0].y -= snake.speed;
		if (snake.num[0].y < 0)
		{
			snake.num[0].y = HEIGHT;
		}
		break;
	case DOWN:
		snake.num[0].y += snake.speed;
		if (snake.num[0].y > HEIGHT)
		{
			snake.num[0].y = 0;
		}
		break;
	case LEFT:
		snake.num[0].x -= snake.speed;
		if (snake.num[0].x < 0)
		{
			snake.num[0].x = WIDTH;
		}
		break;
	case RIGHT:
		snake.num[0].x += snake.speed;
		if (snake.num[0].x > WIDTH)
		{
			snake.num[0].x = 0;
		}
		break;
	}	
}

五)方向控制

//方向控制
void SnakeDir()
{
	if ((GetAsyncKeyState('w') || GetAsyncKeyState('W') || GetAsyncKeyState(VK_UP)) && snake.dir!=DOWN)
	{
		snake.dir = UP;
	}
	if ((GetAsyncKeyState('s') || GetAsyncKeyState('S') || GetAsyncKeyState(VK_DOWN)) && snake.dir != UP)
	{
		snake.dir = DOWN;
	}
	if ((GetAsyncKeyState('a') || GetAsyncKeyState('A') || GetAsyncKeyState(VK_LEFT)) && snake.dir != RIGHT)
	{
		snake.dir = LEFT;
	}
	if ((GetAsyncKeyState('d') || GetAsyncKeyState('D') || GetAsyncKeyState(VK_RIGHT)) && snake.dir != LEFT)
	{
		snake.dir = RIGHT;
	}
}

六)吃食物和死亡判定

//吃食物
void EatFood()
{
	if (snake.num[0].x > food.x - 16 && snake.num[0].x<food.x + 16 &&
		snake.num[0].y>food.y - 16 && snake.num[0].y < food.y + 16)
	{
		mciSendString("close FOOD", 0, 0, 0);
		mciSendString("open ./ress/eatfood.mp3 alias FOOD", 0, 0, 0);
		mciSendString("play FOOD", 0, 0, 0);
		food.x = rand() % WIDTH;
		food.y = rand() % HEIGHT;
		food.color = RGB(rand() % 255, rand() % 255, rand() % 255);
		snake.size++;
		snake.score++;
	}
}
//死亡判定(蛇头撞到蛇身)
void Die()
{
	for (int i = 4; i < snake.size; i++)	//蛇头不可能撞到第4节(头是第一节),所以从第五节开始判定
	{
		if (snake.num[0].x == snake.num[i].x &&
			snake.num[0].y == snake.num[i].y)
		{
			mciSendString("close BGM", 0, 0, 0);
			mciSendString("open ./ress/die.mp3 alias DIE", 0, 0, 0);
			mciSendString("play DIE", 0, 0, 0);
			snake.flag = 0;
		}
		if (snake.flag == 0)
		{
			int isok=MessageBox(GetHWnd(), "你输了,垃圾!~", "提示", MB_OKCANCEL);
			if (isok == IDOK)
			{
				GameInit();
			}
			else
			{
				exit(0);
			}
		}
	}
}

总结

	编程前,画一幅草图能帮助你理清自己的思路,将项目细分就能很好的找到切入点。另外,一定要函数专用,
绘图的函数就只干绘图的事,移动的函数就只干移动的事,这样在出现bug时才能快速的找到问题所在。