贪吃蛇游戏简化版


最近使用 EasyX 图形库在写贪吃蛇,由于是第一次使用加之时间太紧,成品极为简陋,望各路大神轻喷。

基本思路

贪吃蛇问题作为计算机编程的热门问题,大部分人应该都有所接触。基本的思路其实就在于模块化蛇的各种执行步骤,还有就是注意边界情况的判断。由于在很多资料中都有详细说明,不再赘述。

具体实现

下面是代码的具体实现,编译环境为 Visual Studio 2017 Community

建立基本框架

typedef struct node
{
   int x;
   int y;
   struct node *next;
}snake;
struct Position
{
   int x;
   int y;
}position;//用于确定方向是否相反
snake *head,*q,*food;

void init();//初始化
void draw_wall();//生成墙
void move();//移动
void buy();//生成食物
void end_game();//结束函数
int check_game();
void snake_dir();//确定下一步的方向
int eat_self();

int main()
{
   init();
   while (check_game())
   {
   	move();
   }
   end_game();
   return 0;
}

地图与蛇身的初始化

初始化蛇身的时候要注意到不要将尾节点与头节点混淆,以免在以后的操作中出现不便。

void init()
{
	initgraph(640, 480);
	draw_wall();
	snake *tail;
	tail = (snake*)malloc(sizeof(snake));				//申请动态内存并初始化tail节点
	tail->x = 5;
	tail->y = 5;
	position.x = 1;
	position.y = 0;
	tail->next = NULL;
	for (int i = 1; i <= 4; i++)			//此处初始化蛇身
	{
		head = (snake*)malloc(sizeof(snake));
		head->next = tail;
		head->x = 5 + i;
		head->y = 5;
		tail = head;
	}
	while (tail != NULL)			//完善链表
	{
		setcolor(BLUE);
		rectangle(tail->x * 10 - 4, tail->y * 10 - 4, tail->x * 10 + 4, tail->y * 10 + 4);
		tail = tail->next;
	}
	buy();
}

键盘读入与方向确定

void snake_dir()
{
	if (_kbhit())			//读入键盘输入
		switch (_getch())			//在每次的输入都要检查输入的方向与舍得方向是否相反
		{							//如果相反的话则方向不变
		case 'a':
			if (position.x != 1 && position.y != 0)
			{
				position.x = -1;
				position.y = 0;
			}
			break;
		case 'd':
			if (position.x != -1 && position.y != 0)
			{
				position.x = 1;
				position.y = 0;
			}
			break;
		case 'w':
			if (position.x != 0 && position.y != 1)
			{
				position.x = 0;
				position.y = -1;
			}
			break;
		case 's':
			if (position.x != 0 && position.y != -1)
			{
				position.x = 0;
				position.y = 1;
			}
			break;
		}
}

食物生成

void buy()
{
	snake *temp_food;
	temp_food = (snake*)malloc(sizeof(snake));
	srand((unsigned)time(NULL));
	temp_food->x = rand() % 62 + 2;		//注意避免生成在墙上
	temp_food->y = rand() % 46 + 2;
	q = head;
	while (q->next != NULL)			//判断是否与蛇身重叠
	{
		if (q->x == temp_food->x&&q->y == temp_food->y)
		{
			buy();
		}
		q = q->next;
	}
	setcolor(WHITE);
	circle(temp_food->x * 10, temp_food->y * 10, 4);
	food = temp_food;
}

判断是否撞墙

int check_game()			//是否撞墙
{
	if (getpixel(head->x * 10, head->y * 10) == RED)
		return 0;
	else
		return 1;
}

蛇的移动

因为墙,蛇与食物的颜色不尽相同,所以可以通过检查每个位置的点的颜色来判断是否碰触东西。

void move()
{
	Sleep(100);
	snake_dir();			//判断目前前进的方向
	if (getpixel((head->x + position.x) * 10 + 4, (head->y + position.y) * 10 + 4) == BLUE)
		end_game();		//是否咬到自己
	snake * nexthead;
	nexthead = (snake*)malloc(sizeof(snake));
	nexthead->x = head -> x + position.x;
	nexthead->y = head -> y + position.y;
	if (nexthead->x == food->x && nexthead->y == food->y)		//判断是否吃到了食物
	{
		nexthead->next = head;
		head = nexthead;
		q = head;
		setcolor(BLACK);
		circle(food->x * 10, food->y * 10, 4);
		while (q->next != NULL)		//此处是寻找尾节点。实测会有卡顿,
			q = q->next;			//如果使用双向链表则不会有此问题(但是我懒)
		rectangle(q->x * 10 - 5, q->y * 10 - 5, q->x * 10 + 5, q->y * 10 + 5);	//将尾变成黑色
		buy();			//放食物函数
	}
	else
	{
		nexthead->next = head;
		head = nexthead;
		q = head;
		while (q->next->next != NULL)			//后边没什么可说的,正常画蛇
		{
			setcolor(BLUE);
			rectangle(q->x * 10 - 4, q->y * 10 - 4, q->x * 10 + 4, q->y * 10 + 4);
			q = q->next;
		}
		setcolor(BLACK);
		rectangle(q->next->x * 10 - 4, q->next->y * 10 - 4, q->next->x * 10 + 4, q->next->y * 10 + 4);
		free(q->next);
		q->next = NULL;
	}
}

结束游戏

这个部分存在 bug ,博主并不能成功输出 drawtext 函数,希望有大神可以帮忙解释一下。

void end_game()
{
	RECT r = { 0, 0, 640, 480 };
	drawtext(_T("Game Over"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	_getch();
	closegraph();
}

完整代码

#include<graphics.h>
#include<conio.h>
#include<time.h>
#include<math.h>

typedef struct node
{
	int x;
	int y;
	struct node *next;
}snake;
struct Position
{
	int x;
	int y;
}position;//用于确定方向是否相反
snake *head,*q,*food;

void init();//初始化
void draw_wall();//生成墙
void move();//移动
void buy();//生成食物
void end_game();//结束函数
int check_game();
void snake_dir();//确定下一步的方向

void init()
{
	initgraph(640, 480);
	draw_wall();
	snake *tail;
	tail = (snake*)malloc(sizeof(snake));
	tail->x = 5;
	tail->y = 5;
	position.x = 1;
	position.y = 0;
	tail->next = NULL;
	for (int i = 1; i <= 4; i++)//初始长度为4
	{
		head = (snake*)malloc(sizeof(snake));
		head->next = tail;
		head->x = 5 + i;
		head->y = 5;
		tail = head;
	}
	while (tail != NULL)
	{
		setcolor(BLUE);
		rectangle(tail->x * 10 - 4, tail->y * 10 - 4, tail->x * 10 + 4, tail->y * 10 + 4);
		tail = tail->next;
	}
	buy();
}

void draw_wall()
{
	for (int i = 1; i <= 64; i++)
	{
		setcolor(RED);
		rectangle(i * 10 - 10, 0, i * 10, 10);
		rectangle(i * 10 - 10, 470, i * 10, 480);
	}
	for (int i = 1; i <= 48; i++)
	{
		setcolor(RED);
		rectangle(0 , i * 10 - 10, 10, i * 10);
		rectangle(630, i * 10 - 10, 640, i * 10);
	}
}

void snake_dir()
{
	if (_kbhit())
		switch (_getch())
		{
		case 'a':
			if (position.x != 1 && position.y != 0)
			{
				position.x = -1;
				position.y = 0;
			}
			break;
		case 'd':
			if (position.x != -1 && position.y != 0)
			{
				position.x = 1;
				position.y = 0;
			}
			break;
		case 'w':
			if (position.x != 0 && position.y != 1)
			{
				position.x = 0;
				position.y = -1;
			}
			break;
		case 's':
			if (position.x != 0 && position.y != -1)
			{
				position.x = 0;
				position.y = 1;
			}
			break;
		}
}

void move()
{
	Sleep(100);
	snake_dir();
	if (getpixel((head->x + position.x) * 10 + 4, (head->y + position.y) * 10 + 4) == BLUE)
		end_game();
	snake * nexthead;
	nexthead = (snake*)malloc(sizeof(snake));
	nexthead->x = head -> x + position.x;
	nexthead->y = head -> y + position.y;
	if (nexthead->x == food->x && nexthead->y == food->y)
	{
		nexthead->next = head;
		head = nexthead;
		q = head;
		setcolor(BLACK);
		circle(food->x * 10, food->y * 10, 4);
		while (q->next != NULL)
		{
			/*setcolor(BLUE);
			rectangle(q->x * 10 - 5, q->y * 10 - 5, q->x * 10 + 5, q->y * 10 + 5);*/
			q = q->next;
		}
		rectangle(q->x * 10 - 5, q->y * 10 - 5, q->x * 10 + 5, q->y * 10 + 5);
		buy();
	}
	else
	{
		nexthead->next = head;
		head = nexthead;
		q = head;
		while (q->next->next != NULL)
		{
			setcolor(BLUE);
			rectangle(q->x * 10 - 4, q->y * 10 - 4, q->x * 10 + 4, q->y * 10 + 4);
			q = q->next;
		}
		setcolor(BLACK);
		rectangle(q->next->x * 10 - 4, q->next->y * 10 - 4, q->next->x * 10 + 4, q->next->y * 10 + 4);
		free(q->next);
		q->next = NULL;
	}
}

void buy()
{
	snake *temp_food;
	temp_food = (snake*)malloc(sizeof(snake));
	srand((unsigned)time(NULL));
	temp_food->x = rand() % 62 + 2;
	temp_food->y = rand() % 46 + 2;
	q = head;
	while (q->next != NULL)
	{
		if (q->x == temp_food->x&&q->y == temp_food->y)
		{
			buy();
		}
		q = q->next;
	}
	setcolor(WHITE);
	circle(temp_food->x * 10, temp_food->y * 10, 4);
	food = temp_food;
}

int check_game()
{
	if (getpixel(head->x * 10, head->y * 10) == RED)
		return 0;
	else
		return 1;
}

void end_game()
{
	RECT r = { 0, 0, 640, 480 };
	drawtext(_T("Game Over"), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	_getch();
	closegraph();
}
int main()
{
	init();
	while (check_game())
	{
		move();
	}
	end_game();
	return 0;
}

就到这里结束了,写的很乱,大家凑合着看吧。如果有什么问题的话,大佬们多提意见吧!!!感激!!!

发布了2 篇原创文章 · 获赞 4 · 访问量 135

猜你喜欢

转载自blog.csdn.net/weixin_43960134/article/details/84861311