C语言贪吃蛇—基于EasyX图形库

一、编译环境

1、VS2017(VC++6.0也可以)
2、EasyX库(C/C++的图形库)

 EasyX Library for C++ (Ver:2018春分版)
 http://www.easyx.cn
 graphics.h

在这里插入图片描述

二、代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>

typedef struct body {
	int x, y;   //每节蛇身坐标
	struct body *pre, *next;  //双向链表
}SnakeBody;

typedef struct snake {        //用线性表存储蛇的资料

	SnakeBody  *head, *tail;   //链式线性表
	char headDirection; // sedf  四个键表示左上下右四个方向
	char tailDirection;
	int len;       //表长
} Snake;

Snake * createsanke()   //生成空的蛇
{
	Snake  * s;
	s = (Snake *)malloc(sizeof(Snake));
	s->head = NULL;
	s->tail = NULL;
	s->len = 0;
	return s;
}

void initbeginmap(int width, int height)   //绘制背景
{
	int i = 0, j = 0;
	setlinestyle(PS_SOLID, 1);
	setcolor(BLUE);
	for (i = 0; i <= height; i++)
		line(0, i * 10, 640, i * 10);
	for (i = 0; i <= width; i++)
		line(i * 10, 0, i * 10, 480);
	setcolor(BLACK);
	setfillcolor(BLACK);
	solidrectangle(140,130,150,300);
	solidrectangle(200,80,350,90);
	solidrectangle(400,300,410,130);
	solidrectangle(200,340,350,350);
}


void initSnake(Snake *s, int x, int y, int len)  //生成长度为3,x,y为起点的蛇
{
	int i;
	SnakeBody *newbody;
	s->len = len;
	s->headDirection = 'e';
	//s->tailDirection='e';
	setlinestyle(PS_SOLID, 1);
	setcolor(YELLOW);
	setfillcolor(GREEN);

	for (i = 0; i < len; i++)
	{
		//尾插法创建双向链表(蛇身的数据:坐标)
		newbody = (SnakeBody *)malloc(sizeof(SnakeBody));
		newbody->next = NULL;
		newbody->pre = NULL;
		newbody->x = x;
		newbody->y = y + i;
		if (i == 0)
		{           //第一个节点创建
			s->head = s->tail = newbody;
		}
		else
		{         //其他节点创建
			newbody->pre = s->tail;
			s->tail->next = newbody;
			s->tail = newbody;
		}
		//根据蛇身坐标绘图
		fillrectangle(x * 10 + 1, (y + i) * 10 + 1, x * 10 + 10 - 1, (y + i) * 10 + 10 - 1);

	}

}

void putApple(int x, int y)  //在指定x,y位置放一个苹果
{
	setcolor(BLUE);
	setfillcolor(RED);
	int p = x * 10 + 5,q=y*10+5;
	fillcircle(x * 10 + 5, y * 10 + 5, 5);
}

int eatTest(Snake *s, int m, int n)   //判断前进路上是否碰到苹果
{
	switch (s->headDirection)  //探测下个位置是否是苹果
	{
	case 's':         //蛇向左运动,则前一个位置如果是苹果,则可以吃到,返回1
		if (s->head->x - 1 == m && s->head->y == n)
			return 1;
		break;
	case 'e':
		if (s->head->x == m && s->head->y - 1 == n)
			return 1;
		break;
	case 'd':
		if (s->head->x == m && s->head->y + 1 == n)
			return 1;
		break;
	case 'f':
		if (s->head->x + 1 == m && s->head->y == n)
			return 1;
		break;
	}
	return 0;
}

int moveSnake(Snake *s, int m, int n) {
	//按照蛇的运行方向移动一个位置
	SnakeBody * p;
	int flag = 0;
	if (eatTest(s, m, n) == 1)
	{               //创建新的蛇头节点
		p = (SnakeBody *)malloc(sizeof(SnakeBody));
		p->x = m;
		p->y = n;
		flag = 1;
	}
	else
	{
		p = s->tail;         //删除尾节点
		s->tail = p->pre;
		s->tail->next = NULL;
		setcolor(YELLOW);
		setfillcolor(GREEN);
		fillrectangle(p->x * 10 + 1, (p->y) * 10 + 1, p->x * 10 + 10 - 1, (p->y) * 10 + 10 - 1);
	}
	s->head->pre = p;
	p->pre = NULL;
	p->next = s->head;
	s->head = p;

	//	p->derect=s->headDirection; 
		//根据蛇的运动方向,设置蛇头(p指向的节点)坐标
	if (s->headDirection == 's')
	{
		p->x = p->next->x - 1;
		p->y = p->next->y;
	}
	else if (s->headDirection == 'e')
	{
		p->x = p->next->x;
		p->y = p->next->y - 1;
	}
	else if (s->headDirection == 'd')
	{
		p->x = p->next->x;
		p->y = p->next->y + 1;
	}
	else if (s->headDirection == 'f')
	{
		p->x = p->next->x + 1;
		p->y = p->next->y;
	}
	//画蛇头
	setcolor(YELLOW);
	setfillcolor(GREEN);
	fillrectangle(p->x * 10 + 1, (p->y) * 10 + 1, p->x * 10 + 10 - 1, (p->y) * 10 + 10 - 1);

	return flag;
}


int issnakedead(Snake *s)
{
	int x = s->len;
	SnakeBody * p;
	p = s->head->next;
	if (s->head->x >= 64 || s->head->x < 0 || s->head->y >= 48 || s->head->y < 0		 //判断是否碰到了边框
		|| (s->head->x >= 14 && s->head->x < 15 && s->head->y >= 13 && s->head->y < 30)  //是否碰到了障碍物(下面四个都是)
		|| (s->head->x >= 40 && s->head->x < 41 && s->head->y >= 13 && s->head->y < 30) 
		|| (s->head->x >= 20 && s->head->x < 35 && s->head->y >= 8 && s->head->y < 9)
		|| (s->head->x >= 20 && s->head->x < 35 && s->head->y >= 34 && s->head->y < 35)) 
		return 1;
	else if(x!=0){
		while (p)
		{
			if (s->head->x == p->x&&s->head->y ==p-> y)		//判断是否头尾相撞
				return 1;
			p = p->next;
			x--;
		}
	}
	else return 0;
}
int main()
{
	Snake *snake = NULL;
	int score = 0;
	int k = 0;
	int m, n, flag = 0;
	char fenshu[50];
	initgraph(640, 600);
	srand((int)time(0));
	setbkcolor(YELLOW);
	cleardevice();
	initbeginmap(64, 48);     //设置背景
	setwritemode(R2_XORPEN); // 设置 XOR 绘图模式
	m = rand() % 32 + 1;
	n = rand() % 20 + 1;
	snake = createsanke();  //创建空蛇
	initSnake(snake, 32, 24, 3);  // 初始化长度为3的蛇	
	putApple(m, n);     //设定一个固定的苹果 
	char c = ' ';
	int speed = 250;
	outtextxy(0, 550, "当前速度:");
	outtextxy(300, 550, "s:向左");
	outtextxy(380, 550, "f:向右");
	outtextxy(460, 550, "e:向上");
	outtextxy(540, 550, "d:向下");
	outtextxy(300, 520, "1-7:变速");
	outtextxy(380, 520, "空格:暂停");
	outtextxy(480, 520, "ESC:结束游戏");
	settextcolor(RED);
	outtextxy(80, 550, '3');
	int pause = 0;
	while (1)    //27为ESC键
	{
		// 获取按键
		if (_kbhit())
		{
			c = _getch();

			if (c == 27) break;

			// 根据按键设置蛇的运动方向
			switch (c)
			{
			case 's':   //向左,原方向为上下才可以变
				if (snake->headDirection == 'e' || snake->headDirection == 'd')	snake->headDirection = c; break;
			case 'f':   //向右,原方向为上下才可以变
				if (snake->headDirection == 'e' || snake->headDirection == 'd')	snake->headDirection = c; break;
			case 'e':   //向上,原来为左右才变化
				if (snake->headDirection == 's' || snake->headDirection == 'f')	snake->headDirection = c; break;
			case 'd':   //向下,原来为左右才变化
				if (snake->headDirection == 's' || snake->headDirection == 'f')	snake->headDirection = c; break;
			case ' ':   //向下,原来为左右才变化
					outtextxy(200, 500, "已暂停,按任意键继续...");
					system("pause");
					outtextxy(200, 500, "                                                    ");
					break;
					//改变蛇的移动速度(1-7)
			case '1': speed = 350; outtextxy(80, 550, '1'); break;
			case '2': speed = 300; outtextxy(80, 550, '2'); break;
			case '3': speed = 250; outtextxy(80, 550, '3'); break;
			case '4': speed = 200; outtextxy(80, 550, '4'); break;
			case '5': speed = 150; outtextxy(80, 550, '5'); break;
			case '6': speed = 100; outtextxy(80, 550, '6'); break;
			case '7': speed = 50;  outtextxy(80, 550, '7'); break;
			}
		}
		flag = moveSnake(snake, m, n);   //按照蛇的运动方向移动
		settextcolor(BLUE);
		outtextxy(0, 520, "得分:");
		sprintf(fenshu, "%d", k);
		settextcolor(RED);
		outtextxy(80, 520, fenshu);
		if (flag == 1)
		{
			setcolor(BLUE);
			setfillcolor(RED);
			fillcircle(m * 10 + 5, n * 10 + 5, 5);
			m = rand() % 62;
			n = rand() % 30;
			if ((m == 14 && n >= 13 && n <= 30)
			|| (m == 40 && n >= 13 && n <= 30)
			|| (n == 8 && m >= 20 && m <= 35)
			|| (n == 34 && m >= 20 && m <= 35))
			{
				m = m + 1;
				n = n + 1;
			}
			putApple(m, n);
			flag = 0;
			k++;
			sprintf(fenshu, "%d", k--);
			settextcolor(YELLOW);
			outtextxy(80, 520, fenshu);
			sprintf(fenshu, "%d", k++);
			settextcolor(RED);
			outtextxy(80, 520, fenshu);
		}

		// 延时
		Sleep(speed - k * 10);
		if (issnakedead(snake) == 1)
		{

			outtextxy(200, 500, "Game Over!");
			outtextxy(200, 550, "按任意键退出");
			_getch();
			break;
			if (_kbhit())
				exit(0);
		}
	}

	closegraph();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42852559/article/details/107751710