贪吃蛇C语言实现(有源码)

发布时间:2024年01月04日

前言

之前学了一点easyx图形库的使用,掌握一些基本用法后就用贪吃蛇来进行实战了,运行视频放在csdn视频那一栏了,之前的烟花也是。

1.头文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<easyx.h>
#include<conio.h>
#include<time.h>
#include<stdlib.h>
#include<stdbool.h>
#define NODE_HIGHT 40
#define NODE_WIDTH 40
typedef enum direction
{
	up,
	down,
	left,
	right,
}direction;
typedef struct node
{
	int x, y;
}node;

2.源文件

#include"snack.h"
void Paintgrid()
{
	for (int x = 0; x < 800; x += NODE_WIDTH)
		line(x, 0, x, 600);
	for (int y = 0; y < 600; y += NODE_WIDTH)
		line(0, y, 800, y);
}
void PaintSnack(node* nodes, int n)
{
	int left, right, top, bottom;
	for (int i = 0; i < n; i++)
	{
		left = nodes[i].x * NODE_WIDTH;
		top = nodes[i].y * NODE_WIDTH;
		right = (nodes[i].x + 1) * NODE_WIDTH;
		bottom = (nodes[i].y + 1) * NODE_WIDTH;
		solidrectangle(left, top, right, bottom);
	}
}
node* SnackMove(node* nodes, int length, int direction)
{
	node x = nodes[length - 1];
	for (int i = length - 1; i > 0; i--)
	{
		nodes[i] = nodes[i - 1];
	}
	node new_head = nodes[0];
	if (direction == up)
		new_head.y--;
	if (direction == down)
		new_head.y++;
	if (direction == left)
		new_head.x--;
	if (direction == right)
		new_head.x++;
	nodes[0] = new_head;
	return &x;
}
void playerchoice(direction* dir)
{
	if (_kbhit())
		switch (_getch())
		{
		case 'A':
		case'a':
			if (*dir != left)
				*dir = left;
			break;
		case 'd':
		case'D':
			if (*dir != right)
				*dir = right;
			break;
		case 'w':
		case'W':
			if (*dir != up)
				*dir = up;
			break;
		case 's':
		case'S':
			if (*dir != down)
				*dir = down;
			break;
		}
}
void setfood(node* food,node*nodes,int length,int* flag)
{
	srand((unsigned)time(NULL));
	if (*flag == 0)
	{
	again:
		food->x = rand() % (800 / NODE_WIDTH);
		food->y = rand() % (600 / NODE_HIGHT);
		for (int i = 0; i < length; i++)
		{
			if (food->x == nodes[i].x && food->y == nodes[i].y)
				goto again;
		}
		*flag= 1;
	}
	setfillcolor(YELLOW);
	solidrectangle(food->x * NODE_WIDTH, food->y * NODE_HIGHT, (food->x + 1) * NODE_WIDTH, (food->y + 1) * NODE_HIGHT);
	setfillcolor(WHITE);
 }
 bool isover(node* nodes,int length)
{
	 if (nodes->x >= 800/NODE_WIDTH || nodes->x < 0 || nodes->y < 0 || nodes->y>=600/NODE_HIGHT)
		 return true;
	 for (int i = 1; i < length; i++)
		 if (nodes->x == nodes[i].x && nodes->y == nodes[i].y)
			 return true;
	 return FALSE;
}
 void reset(node* nodes, int* length, direction* dir,int*flag)
 {
	 nodes[0] = { 5,7 };
	 nodes[1] = { 4,7 };
	 nodes[2] = { 3,7 };
	 nodes[3] = {2,7};
	 nodes[4] = {1,7};
	 *length = 5;
	 *dir = right;
	 *flag = 0;
 }
 int main()
 {
	 srand((unsigned)time(NULL));
	 initgraph(800, 600);
	 setbkcolor(RGB(164, 225, 202));
	 direction dir = right;
	 int  length = 5;
	 node nodes[100] = { {5,7},{4,7},{3,7},{2,7},{1,7} };//从蛇头到蛇尾
	 node food = { 0 };
	 int flag = 0;
	 while (1)
	 {
		 cleardevice();
		 Paintgrid();//初始化表格

		 setfood(&food, nodes, length, &flag);
		 PaintSnack(nodes, length);
		 Sleep(500);
		 playerchoice(&dir);
		 node* end = SnackMove(nodes, length, dir);
		 if (nodes[0].x == food.x && food.y == nodes[0].y)
		 {
			 length++;
			 nodes[length - 1].x = end->x;
			 nodes[length - 1].y = end->y;
			 flag = 0;
		 }
		 if (isover(nodes, length))
		 {
			 reset(nodes, &length, &dir,&flag);
		 }
	 }
	 closegraph();
	 return 0;
 }

3.解析

0.创建环境

我使用的是vs编译环境和easyx图形库,貌似easyx也支持Dev,具体的下载方法可以去吧站搜索,easyx的使用在吧站也有相关?教程,包括vs的下载都有很详细的视频教程,所以就不再赘述了。

我们由于要用到随机数所以使用了<time.h><stdlib.h>头文件

关于随机数的使用若是不了解可以看看这篇博客

C语言rand函数,srand函数,time函数实现随机数,及猜数字小游戏-CSDN博客

图形库的使用需要<easyx.h>头文件

第一行的宏定义想必用vs的都知道,用来避免报错的

两个结构体是用来记录蛇的移动方向和坐标的。

#define _CRT_SECURE_NO_WARNINGS 1
#include<easyx.h>
#include<conio.h>
#include<time.h>
#include<stdlib.h>
#include<stdbool.h>
#define NODE_HIGHT 40
#define NODE_WIDTH 40
typedef enum direction
{
?? ?up,
?? ?down,
?? ?left,
?? ?right,
}direction;
typedef struct node
{
?? ?int x, y;
}node;

我们只要知道以下几点就可以

1.把地图画出来

void Paintgrid()
{
?? ?for (int x = 0; x < 800; x += NODE_WIDTH)
?? ??? ?line(x, 0, x, 600);
?? ?for (int y = 0; y < 600; y += NODE_WIDTH)
?? ??? ?line(0, y, 800, y);
}

2.初始化并记录蛇的每个节点的坐标

void PaintSnack(node* nodes, int n)
{
?? ?int left, right, top, bottom;
?? ?for (int i = 0; i < n; i++)
?? ?{
?? ??? ?left = nodes[i].x * NODE_WIDTH;
?? ??? ?top = nodes[i].y * NODE_WIDTH;
?? ??? ?right = (nodes[i].x + 1) * NODE_WIDTH;
?? ??? ?bottom = (nodes[i].y + 1) * NODE_WIDTH;
?? ??? ?solidrectangle(left, top, right, bottom);
?? ?}
}

3.随机产生食物

void setfood(node* food,node*nodes,int length,int* flag)
{
?? ?srand((unsigned)time(NULL));
?? ?if (*flag == 0)
?? ?{
?? ?again:
?? ??? ?food->x = rand() % (800 / NODE_WIDTH);
?? ??? ?food->y = rand() % (600 / NODE_HIGHT);
?? ??? ?for (int i = 0; i < length; i++)
?? ??? ?{
?? ??? ??? ?if (food->x == nodes[i].x && food->y == nodes[i].y)
?? ??? ??? ??? ?goto again;
?? ??? ?}
?? ??? ?*flag= 1;
?? ?}
?? ?setfillcolor(YELLOW);
?? ?solidrectangle(food->x * NODE_WIDTH, food->y * NODE_HIGHT, (food->x + 1) * NODE_WIDTH, (food->y + 1) * NODE_HIGHT);
?? ?setfillcolor(WHITE);
?}

4.蛇移动坐标随之变化

node* SnackMove(node* nodes, int length, int direction)
{
?? ?node x = nodes[length - 1];
?? ?for (int i = length - 1; i > 0; i--)
?? ?{
?? ??? ?nodes[i] = nodes[i - 1];
?? ?}
?? ?node new_head = nodes[0];
?? ?if (direction == up)
?? ??? ?new_head.y--;
?? ?if (direction == down)
?? ??? ?new_head.y++;
?? ?if (direction == left)
?? ??? ?new_head.x--;
?? ?if (direction == right)
?? ??? ?new_head.x++;
?? ?nodes[0] = new_head;
?? ?return &x;
}
void playerchoice(direction* dir)
{
?? ?if (_kbhit())
?? ??? ?switch (_getch())
?? ??? ?{
?? ??? ?case 'A':
?? ??? ?case'a':
?? ??? ??? ?if (*dir != left)
?? ??? ??? ??? ?*dir = left;
?? ??? ??? ?break;
?? ??? ?case 'd':
?? ??? ?case'D':
?? ??? ??? ?if (*dir != right)
?? ??? ??? ??? ?*dir = right;
?? ??? ??? ?break;
?? ??? ?case 'w':
?? ??? ?case'W':
?? ??? ??? ?if (*dir != up)
?? ??? ??? ??? ?*dir = up;
?? ??? ??? ?break;
?? ??? ?case 's':
?? ??? ?case'S':
?? ??? ??? ?if (*dir != down)
?? ??? ??? ??? ?*dir = down;
?? ??? ??? ?break;
?? ??? ?}
}

5.蛇吃到食物会长长

//主函数中

?if (nodes[0].x == food.x && food.y == nodes[0].y)
?{
?? ? length++;
?? ? nodes[length - 1].x = end->x;
?? ? nodes[length - 1].y = end->y;
?? ? flag = 0;
?}

6.碰到边界或自己会死,并设置游戏重开功能

?bool isover(node* nodes,int length)
{
?? ? if (nodes->x >= 800/NODE_WIDTH || nodes->x < 0 || nodes->y < 0 || nodes->y>=600/NODE_HIGHT)
?? ??? ? return true;
?? ? for (int i = 1; i < length; i++)
?? ??? ? if (nodes->x == nodes[i].x && nodes->y == nodes[i].y)
?? ??? ??? ? return true;
?? ? return FALSE;
}

//主函数中

?if (isover(nodes, length))
?{
?? ? reset(nodes, &length, &dir,&flag);
?}

7.主函数调用函数

?? ? srand((unsigned)time(NULL));
?? ? initgraph(800, 600);
?? ? setbkcolor(RGB(164, 225, 202));
?? ? direction dir = right;
?? ? int ?length = 5;
?? ? node nodes[100] = { {5,7},{4,7},{3,7},{2,7},{1,7} };//从蛇头到蛇尾
?? ? node food = { 0 };
?? ? int flag = 0;
?? ? while (1)
?? ? {
?? ??? ? cleardevice();
?? ??? ? Paintgrid();//初始化表格

?? ??? ? setfood(&food, nodes, length, &flag);
?? ??? ? PaintSnack(nodes, length);
?? ??? ? Sleep(500);
?? ??? ? playerchoice(&dir);
?? ??? ? node* end = SnackMove(nodes, length, dir);
?? ??? ? if (nodes[0].x == food.x && food.y == nodes[0].y)
?? ??? ? {
?? ??? ??? ? length++;
?? ??? ??? ? nodes[length - 1].x = end->x;
?? ??? ??? ? nodes[length - 1].y = end->y;
?? ??? ??? ? flag = 0;
?? ??? ? }
?? ??? ? if (isover(nodes, length))
?? ??? ? {
?? ??? ??? ? reset(nodes, &length, &dir,&flag);
?? ??? ? }
?? ? }
?? ? closegraph();

总结

一直想写个小游戏玩玩,现在也算是小小的玩了一把,可惜最近要复习,没有时间学图形库了,不然真希望继续做点东西。最后祝愿还没考的同学考出好成绩,考完的寒假快乐,工作的早点放假,

若是觉得这篇博客对你有帮助就点个赞支持一下博主吧,感谢!

文章来源:https://blog.csdn.net/2301_79551553/article/details/135377334
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。