c语言编写游戏贪吃蛇以及部分easyx函数的使用

前言


游戏贪吃蛇的主要代码可以分为三个部分:

  1. 绘制地图、小蛇与食物
  2. 游戏的初始化
  3. 小蛇的移动

代码与部分函数解析

1.绘制地图、小蛇与食物

void show()//绘制函数
{
	cleardevice();
	int i, j;
	for (i = 0; i < HEIGHT; i++)
	{
		for (j = 0; j < WIDTH; j++)
		{
			if (blocks[i][j] > 0)//元素大于0表示是蛇
				setfillcolor(HSVtoRGB(blocks[i][j] * 10, 0.9, 1));//设置蛇身为渐变色
			else
				setfillcolor(RGB(150, 150, 150));//元素为0表示为空,设置为灰色
			fillrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE,
				(j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE);
		}
	}
	setfillcolor(RGB(0, 255, 0));//设置食物颜色为绿色
	fillrectangle(food_j * BLOCK_SIZE, food_i * BLOCK_SIZE,
		(food_j + 1) * BLOCK_SIZE, (food_i + 1) * BLOCK_SIZE);
	if (isfailure)//判断游戏是否失败
	{
		setbkmode(TRANSPARENT);//设置文字字体透明
		settextcolor(RGB(221, 160, 221));//设置文字颜色
		settextstyle(80, 0, _T("宋体"));//设置文字大小与样式
		outtextxy(240, 220, _T("游戏失败"));//输出文字内容
	}
	FlushBatchDraw();
}
  • fillrectangle函数的使用方法如下:
void fillrectangle(
	int left,
	int top,
	int right,
	int bottom
);

其中,left等分别表示矩形框的左侧横坐标、上侧纵坐标、右侧横坐标与下侧纵坐标。

  • FlushBatchDraw语句表示批量绘制,意为一次性完成所有绘图任务

2.游戏的初始化

void startup()//初始化函数
{
	int i;
	blocks[HEIGHT / 2][WIDTH / 2] = 1;
	for (i = 1; i <= 4; i++)
		blocks[HEIGHT / 2][WIDTH / 2 - i] = i + 1;//向左四个蛇身,分别为2,3,4,5
	movedirection = 'd';//默认按d键,初始向右移动
	food_i = rand() % (HEIGHT - 5) + 2;
	food_j = rand() % (WIDTH - 5) + 2;//食物位置随机
	initgraph(WIDTH * BLOCK_SIZE, HEIGHT * BLOCK_SIZE);//展开画面
	setlinecolor(RGB(200, 200, 200));
	BeginBatchDraw();//
}
  • BeginBatchDraw语句表示批量绘制
  • 展开画面部分不参与循环,属于初始化部分,因此不放入show函数中

3.小蛇的移动

首先,我们需要通过遍历blocks数组以找出小蛇(数组元素大于0,下文称此部分为“小蛇数组”)的位置,
并且确定蛇头(小蛇数组整体自加后数值为2,详见代码部分)、蛇尾(小蛇数组中值最大的元素);
其次,根据用户输入确定新蛇头的位置,如果蛇头超过边界或者蛇头碰到蛇身,则判定失败(isfailure);
如果蛇头碰到食物,则刷新食物位置,不处理蛇尾(相当于长度+1);
如果没有碰到食物,则旧蛇尾变成空白。
代码如下:

void movesnake()
{
	int i, j;
	for (i = 0; i < HEIGHT; i++)
		for (j = 0; j < WIDTH; j++)
			if (blocks[i][j] > 0)
				blocks[i][j]++;//小蛇数组自加运算
	int oldtail_i, oldtail_j, oldhead_i, oldhead_j;
	int max = 0;//记录最大值
	for (i = 0; i < HEIGHT; i++)
		for (j = 0; j < WIDTH; j++)//找蛇头与蛇尾
		{
			if (max < blocks[i][j])
			{
				oldtail_i = i;
				oldtail_j = j;
				max = blocks[i][j];
			}
			if (blocks[i][j] == 2)
			{
				oldhead_i = i;
				oldhead_j = j;
			}
		}
	int newhead_i = oldhead_i;
	int newhead_j = oldhead_j;
	//根据按键确定新蛇头的位置
	if (movedirection == 'w')
		newhead_i = oldhead_i - 1;
	else if (movedirection == 's')
		newhead_i = oldhead_i + 1;
	else if (movedirection == 'a')
		newhead_j = oldhead_j - 1;
	else if (movedirection == 'd')
		newhead_j = oldhead_j + 1;
	if (newhead_i >= HEIGHT || newhead_j >= WIDTH || newhead_i < 0 || newhead_j < 0
		|| blocks[newhead_i][newhead_j]>0)//判断游戏是否失败
	{
		isfailure = 1;
		return;
	}
	blocks[newhead_i][newhead_j] = 1;
	if (newhead_i == food_i && newhead_j == food_j)//吃到食物
	{
		food_i = rand() % (HEIGHT - 5) + 2;
		food_j = rand() % (WIDTH - 5) + 2;
	}
	else
		blocks[oldtail_i][oldtail_j] = 0;
}

4.后期细节处理与补充

在贪吃蛇游戏中,用户不进行输入小蛇位置也会发生移动,因此我们需要分别写与输入有关的函数和与输入无关的函数。

void withoutinput()//与输入无关
{
	if (isfailure)
		return;
	static int wait = 1;
	wait++;
	if (wait == 10)
	{
		movesnake();
		wait = 1;
	}
}
void withinput()//与输入有关
{
	if (_kbhit() && isfailure == 0)//有输入且不失败
	{
		char input = _getch();
		if (input == 'w' || input == 'a' || input == 's' || input == 'd')
		{
			movedirection = input;
			movesnake();
		}
	}
}
  • “wait”初始化为1,每10帧移动一次
  • _kbhit为判断键盘有无输入的函数
    最后附上主函数代码:
int main()
{
	startup();
	while (1)
	{
		show();
		withoutinput();
		withinput();
	}
	return 0;
}
posted @ 2021-01-22 22:14  Rose&Whisky  阅读(297)  评论(0)    收藏  举报