C语言贪吃蛇代码

1.首先编写贪吃首要要解决贪吃蛇怎么去移动
移动很多方式,可以用一个二位数组去装贪吃蛇的每个身体的坐标:
移动时,先蛇尾处打印空格,清除尾巴,再把前一个身体的坐标给后一个身体
,再把下一次移动点的坐标给蛇头,然后打印蛇,就可以实现蛇的移动。
蛇吃东西长长只要在移动函数中不执行清除尾巴部分就行。


还有一种方法是使用结构体来作为蛇的身体
结构体这样定义
struct snack //蛇结构体
{
int x;
int y;
struct snack *next;
} *snack_body;
并且定义一个结构体指针变量指向蛇的头
结构体蛇移动时只需要先开辟一个结构体空间然后赋予它下次要到达的坐标,
并且打印,然后移动到倒数第二个结构体,用最后一个结构体消除,并释放

最后一个结构体的内存,然后令倒数第二个结构体的next指向NULL。

难点就在与如何移动和吃食物,后续的一些检测是否碰到自己和是否碰到的墙壁都比较容易理解,不过多解释。

代码如下:

/*
贪吃蛇游戏
*/
/*
作者:李金虎
*/
/*
时间:2018-04-06
*/
/*
QQ:1910084514
*/

#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
int a = 1;
int snack_life=1;//1代表游戏继续  0代表游戏结束
int count = 0;//得分
int speed=0;//贪吃蛇的速度
void gotoxy(int x, int y)//光标移动函数,光标想在哪里就在哪里
{
	COORD coord = { x , y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

struct food //食物结构体
{
	int x;
	int y;
	int life;
}Food;

struct snack //蛇结构体
{
	int x;
	int y;
	struct snack *next;
} *snack_body;

void product_food() //产生食物坐标函数
{
	remake:
	struct snack *p;//定义一个临时指针变量 指向snack_body
	p = snack_body;
	srand(time(NULL));
	Food.x = (rand() % 16 + 4)*2;
	Food.y = rand() % 17 + 2;
	Food.life = 1;
	while (p != NULL)  //防止食物生成在蛇所处的位置,如果生成在蛇身体的位置,则重新生成食物
	{
		if (Food.x == p->x&&p->y == Food.y)
			goto remake;
		p = p->next;
	}
	gotoxy(Food.x, Food.y);
	printf("G");
}


void introduce()
{
	system("cls");
	gotoxy(10, 5);
	printf("欢迎来到贪吃蛇的世界\n");
	gotoxy(10, 6);
	printf("我是李金虎,此代码的作者\n");
	gotoxy(10, 7);
	printf("完成时间: 2018-04-09 , 历时7小时\n");
	gotoxy(10, 8);
	printf("初次编写贪吃蛇,代码风格以及逻辑有很多的不足\n");
	gotoxy(10, 9);
	printf("如果有些代码不懂的小伙伴可以加我QQ1910084514私信我,乐意为您效劳\n");
	gotoxy(10, 10);
	printf("希望您游戏愉快\n");

	while (speed<=0||speed>=21)
	{
		gotoxy(10, 11);
		printf("请输入游戏的级别 最快的为20级,最慢为1级,请输入一个整数:");
		scanf_s("%d", &speed);
	}
	system("cls");
	gotoxy(10, 10);
	printf("按任意键盘,确认开始游戏");
	system("pause");
	system("cls");
	
}

void map()  //打印地图函数
{
	for (int i = 0; i < 20; i++)
	{
		gotoxy(i*2, 0);
		printf("〇");
		gotoxy(i * 2, 19);
		printf("〇");
		gotoxy(0, i);
		printf("〇");
		gotoxy(40, i);
		printf("〇");
	}
	gotoxy(50, 8);
	printf("得分:%d", count);
	gotoxy(50, 9);
	printf("游戏难度:%d 级",speed);
	gotoxy(50, 10);
	printf("-----贪吃蛇小游戏-----");
	gotoxy(50, 11);
	printf("--作者--李金虎");
}

void init_snack()//蛇初始化函数
{
	struct snack *p;
	
	p= (struct snack *)(malloc(sizeof(struct snack)));
	p->x = 10;
	p->y = 10;
	snack_body = p;
	p->next = (struct snack *)(malloc(sizeof(struct snack)));
	p = p->next;
	p->x = 10;
	p->y = 9;
	p->next = (struct snack *)(malloc(sizeof(struct snack)));
	p = p->next;
	p->x = 10;
	p->y = 8;
	p->next = (struct snack *)(malloc(sizeof(struct snack)));
	p = p->next;
	p->x = 10;
	p->y = 7;
	p->next = NULL;
	p= snack_body;
	while (p != NULL)
	{
		gotoxy(p->x, p->y);
		printf("G");
		p = p->next;
	}
	
}

int control(void)//蛇的控制函数
{

	int down;
	int left;//左
	int right;//右
	int up;
		down = GetKeyState(VK_DOWN);//获取上箭头键状态   
		if (down < 0&& a!=2 )      //如果上箭头键被按下   a!=2 的作用在于复制头朝下的时候蛇还会往上走
		{
			a = 1;
		}
		up = GetKeyState(VK_UP);//获取下箭头键状态  
		if (up < 0 && a != 1)      //如果下箭头键被按下   
		{
			a = 2;
		}
		left = GetKeyState(VK_LEFT);//获取左箭头键状态   
		if (left < 0 && a != 4)      //如果左箭头键被按下   
		{
			a = 3;
		}
		right = GetKeyState(VK_RIGHT);//获取右箭头键状态   
		if (right < 0 && a != 3)      //如果右箭头键被按下   
		{
			a = 4;
		}
		return a;
}

int is_eat_itself(int x, int y)
{
	struct snack *p;
	p = snack_body;
	p = p->next;//跳过蛇头
	while (p != NULL)
	{
		if (x == p->x &&  y == p->y)//如果蛇咬到自己
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}

void snack_move(int direction )//蛇移动函数  direction为方向    direction的值是1向上 2向下 3向左 4向右
{
	 int y=0;
	 int x=0;
	struct snack *p4=NULL;
	struct snack *p1=NULL;
	struct snack *p2 = NULL;
	p4 = snack_body;
	x = p4->x;//临时储存当前的蛇头坐标
	y = p4->y;
	if (1 == direction)
	{
		
		y=y + (1);
		p1 = (struct snack *)malloc(sizeof(struct snack));//创建了一个结构体然后它的下一及指向旧的蛇头,然后让指向旧蛇头的指针又指向新蛇头
		p1->x = x;
		p1->y = y;
		p1->next = snack_body;
		snack_body = p1;
		p2 = snack_body;
	

		
		if (     !((y < 1 || y > 18) || (x < 2 || x >38)) && !is_eat_itself(x,y))//判断是否撞墙 满足条件就是没撞墙
		{
			gotoxy(snack_body->x, snack_body->y);
			printf("G");//打印新蛇头
			if (x == Food.x&&y == Food.y)
			{
				Food.life = 0;//不清除蛇尾也不释放蛇尾,标志食物被吃
			}
			else
			{
				while (((p2->next)->next) != NULL)//倒数第二个身体
				{
					p2 = p2->next;
				}
				gotoxy(p2->next->x, p2->next->y);
				printf(" ");//清除蛇尾
				free(p2->next);//释放蛇尾
				p2->next = NULL;
				p2 = NULL;
			}
		}
		else
		{
			snack_life = 0;
		}
	}
	else if (2 == direction)
	{

		y=y -(1);
		p1 = (struct snack *)malloc(sizeof(struct snack));//创建了一个结构体然后它的下一及指向旧的蛇头,然后让指向旧蛇头的指针又指向新蛇头
		p1->x = x;
		p1->y = y;
		p1->next = snack_body;
		snack_body = p1;
		p2 = snack_body;
	

	
		if (        !((y < 1 || y > 18) || (x < 2 || x >38)) && !is_eat_itself(x, y))//判断是否撞墙
		{
			gotoxy(snack_body->x, snack_body->y);
			printf("G");//打印新蛇头
			if (x == Food.x&&y == Food.y)
			{
				Food.life = 0;//不清除蛇尾也不释放蛇尾,标志食物被吃
			}
			else
			{
				while (((p2->next)->next) != NULL)//倒数第二个身体
				{
					p2 = p2->next;
				}
				gotoxy(p2->next->x, p2->next->y);
				printf(" ");//清除蛇尾
				free(p2->next);//释放蛇尾
				p2->next = NULL;
				p2 = NULL;
			}
		}
		else
		{
			snack_life = 0;
		}
	}

	else if (3 == direction)
	{

		x=x - (1 * 2);
		p1 = (struct snack *)malloc(sizeof(struct snack));//创建了一个结构体然后它的下一及指向旧的蛇头,然后让指向旧蛇头的指针又指向新蛇头
		p1->x = x;
		p1->y = y;
		p1->next = snack_body;
		snack_body = p1;
		p2 = snack_body;
	

		if (       !(     (y < 1||y > 18) ||  (x < 2||x >38)) && !is_eat_itself(x, y))//判断是否撞墙 
		{
			gotoxy(snack_body->x, snack_body->y);
			printf("G");//打印新蛇头
			if (x == Food.x&&y == Food.y)
			{
				Food.life = 0;//不清除蛇尾也不释放蛇尾,标志食物被吃
			}
			else
			{
				while (((p2->next)->next) != NULL)//倒数第二个身体
				{
					p2 = p2->next;
				}
				gotoxy(p2->next->x, p2->next->y);
				printf(" ");//清除蛇尾
				free(p2->next);//释放蛇尾
				p2->next = NULL;
				p2 = NULL;
			}
		}
		else 
		{
			snack_life = 0;
		}
	}
	
	if (4 == direction)
	{
	
		x = x + (1 * 2);
		p1 = (struct snack *)malloc(sizeof(struct snack));//创建了一个结构体然后它的下一及指向旧的蛇头,然后让指向旧蛇头的指针又指向新蛇头
		p1->x = x;
		p1->y = y;
		p1->next = snack_body;
		snack_body = p1;
		p2 = snack_body;

		if (!   ((y < 1 || y > 18) || (x < 2 || x >38)) && !is_eat_itself(x, y))//判断是否撞墙
		{
			gotoxy(snack_body->x, snack_body->y);
			printf("G");//打印新蛇头
			if (x == Food.x&&y == Food.y)
			{
				Food.life = 0;//不清除蛇尾也不释放蛇尾,标志食物被吃
			}
			else
			{
				while (((p2->next)->next) != NULL)//倒数第二个身体
				{
					p2 = p2->next;
				}
				gotoxy(p2->next->x, p2->next->y);
				printf(" ");//清除蛇尾
				free(p2->next);//释放蛇尾
				p2->next = NULL;
				p2 = NULL;
			}
		}
		else
		{
			snack_life = 0;
		}
	}
}


int main()
{	
	char ch;
restart:
	count = 0;//分数清零
	a = 1;//向下走
	Food.life = 0;//使重新产生食物
	snack_life = 1;//蛇活着
	speed = 0;
	introduce();//自我介绍
	map();
	product_food();
	init_snack();
	while (1)
	{
		
		if (0 == Food.life)//被吃掉就在此产生食物
		{
			count=count+speed;
			gotoxy(55, 8);
			printf("%d", count);
			product_food();
		}
		snack_move(control());
		if (snack_life == 0)
		{
			break; //游戏结束
		}
		Sleep(2100-speed*100);
	}
	
	gotoxy(20,20);
	printf("你撞死了游戏结束!!!\n");
	
	while (1)
	{
		gotoxy(20, 21);
		printf("是否继续:Y/N:");
		scanf_s("%c", &ch);
	
		if ('Y' == ch)
		{
		free(snack_body);//释放上一局游戏内存
		snack_body = NULL;
			goto restart;
		}
		else if('N'==ch)
		{
			
			break;//退出游戏
		}
		
	}
	return 0;
}

用windows api 做的贪吃蛇 #include #include"resource.h" #include"Node.h" #include #include TCHAR szAppname[] = TEXT("Snack_eat"); #define SIDE (x_Client/80) #define x_Client 800 #define y_Client 800 #define X_MAX 800-20-SIDE //点x的范围 #define Y_MAX 800-60-SIDE //点y的范围 #define TIME_ID 1 #define SECOND 100 #define NUM_POINT 10 //点的总个数 #define ADD_SCORE 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; //窗口句柄 MSG msg; //消息 WNDCLASS wndclass; //窗口类 HACCEL hAccel;//加速键句柄 wndclass.style = CS_HREDRAW | CS_VREDRAW; //窗口的水平和垂直尺寸被改变时,窗口被重绘 wndclass.lpfnWndProc = WndProc; //窗口过程为WndProc函数 wndclass.cbClsExtra = 0; //预留额外空间 wndclass.cbWndExtra = 0; //预留额外空间 wndclass.hInstance = hInstance; //应用程序的实例句柄,WinMain的第一个参数 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //设置图标 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //载入预定义的鼠标指针 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置画刷 wndclass.lpszMenuName = szAppname; //设置菜单 wndclass.lpszClassName = szAppname; //设置窗口类的名字 if (!RegisterClass(&wndclass))//注册窗口类 { MessageBox(NULL, TEXT("这个程序需要windows NT!"), szAppname, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppname, TEXT("Snack_eat"),//CreateWindow函数调用时,WndProc将受到WM_CREATE WS_OVERLAPPEDWINDOW&~WS_THICKFRAME& ~WS_MAXIMIZEBOX,//普通的层叠窗口&禁止改变大小&禁止最大化 CW_USEDEFAULT, //初始x坐标(默认) CW_USEDEFAULT, //初始y坐标 x_Client, //初始x方向尺寸 770 y_Client, //初始y方向尺寸 750 NULL, //父窗口句柄 NULL, //窗口菜单句柄 hInstance, //程序实例句柄 WinMain函数中第二个参数 NULL); //创建参数 ShowWindow(hwnd, iCmdShow);//显示窗口,iCmdShow是WinMain的第四个参数,决定窗口在屏幕中的初始化显示形式,例:SW_SHOWNORMAL表示正常显示 UpdateWindow(hwnd);//使窗口客户区重绘,通过向WndProc发送一条WM_PAINT消息而完成的 hAccel = LoadAccelerators(hInstance, szAppname);//加载加速键 while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }/* while (GetMessage(&msg, NULL, 0, 0))//GetMessage函数从消息队列中得到消息,填充msg。如果msg.message等于WM_QUIT,返回0,否则返回非0 { TranslateMessage(&msg);//将msg返回给windows已进行某些键盘消息的转换 DispatchMessage(&msg);//将msg再次返回给windows }*/ return msg.wParam;//msg.wParam是PostQuitMessage函数的参数值,通常是0 } ...
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值