C语言贪吃蛇

C语言贪吃蛇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

初学C语言,这是我写的第一个C语言的小游戏,给大家奉上,也请各位大佬多多指教。


二、介绍

1.效果:

‘w’,‘a’,‘s’,'d’为方向键,空格为暂停,‘q’,'e’分别为加速减速。
在运行过程中不要改变按全屏,不然输出会乱掉。

2.代码如下:

代码如下:

#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <stdlib.h>

typedef struct SNAKE
{
	int x;
	int y;
	struct SNAKE* next;
}snake;

void Pos(int x, int y);
void makesnake(snake** head);
void movesnake(COORD nhead, snake** head);
COORD findtail(snake* head);
void deltail(snake** head);
void printsnake(snake* head);
void cleantail(COORD tail);
void printmap();
BOOL deal(COORD nhead, snake* head);
COORD food();
COORD makefood(snake* head);
void printfood(COORD food);
void release(snake** head);

void release(snake** head)
{
	snake* temp, * pre;
	temp = *head;
	while (temp != NULL) {
		pre = temp;
		temp = temp->next;
		free(pre);
	}
}
void printfood(COORD food)
{
	Pos(food.X, food.Y);
	printf("o");
}
COORD food()
{
	COORD sfood;
	sfood.X = (rand() % 27 + 1) * 2;
	sfood.Y = rand() % 27 + 1;
	return sfood;
}
COORD makefood(snake* head)
{
	COORD finalfood = food();
	snake* temp;
	temp = head;
	while (temp != NULL)
	{
		if (finalfood.X == temp->x && finalfood.Y == temp->y)
		{
			finalfood = food();//如果与蛇身重复则重置食物。
			temp = head;//重新在历遍链表。
			continue;
		}
		else
		{
			temp = temp->next;
		}//如果不重复的话,检查下一截蛇身。
	}
	return finalfood;
}
BOOL deal(COORD nhead, snake* head)
{
	snake* temp;
	temp = head;
	while (temp != NULL)
	{
		if (nhead.X == temp->x && nhead.Y == temp->y)
		{
			return 1;
		}
		else {
			temp = temp->next;
		}
	}
	return 0;
}
void printmap()
{
	int x, y;
	for (x = 0; x < 60; x += 2)
	{
		Pos(x, 0);
		printf("#");
		Pos(x, 29);
		printf("#");
	}
	for (y = 0; y < 30; y++)
	{
		Pos(0, y);
		printf(" #");
		Pos(59, y);
		printf("#");
	}
}
void cleantail(COORD tail)
{
	Pos(tail.X, tail.Y);
	printf(" ");
}
void printsnake(snake* head)
{
	snake* temp;
	temp = head;
	while (temp != NULL)
	{
		Pos(temp->x, temp->y);
		printf("@");
		temp = temp->next;
	}
}
void deltail(snake** head)
{
	snake* pre, * temp, * last = NULL;
	temp = (*head);
	pre = (*head);

	while (temp != NULL)
	{
		last = pre;
		pre = temp;
		temp = pre->next;
	}
	last->next = NULL;
	free(pre);

}//找到链表尾部,删除蛇尾。
COORD findtail(snake* head)
{
	COORD tail;
	snake* temp, * previous = NULL;
	temp = head;
	while (temp != NULL)
	{
		previous = temp;
		temp = previous->next;
	}
	tail.X = previous->x;
	tail.Y = previous->y;
	return tail;

}
void movesnake(COORD nhead, snake** head)
{
	snake* newhead, * temp;
	newhead = (snake*)malloc(sizeof(snake));
	newhead->x = nhead.X;
	newhead->y = nhead.Y;
	if (*head == NULL)
	{
		(*head) = newhead;
		(*head)->next = NULL;
	}
	else
	{
		temp = (*head);
		(*head) = newhead;
		(*head)->next = temp;
	}
}
void makesnake(snake** head)
{
	snake* temp, * newbody;
	int snakelong = 8;
	while (snakelong)
	{
		newbody = (snake*)malloc(sizeof(snake));
		newbody->x = 14 - snakelong;
		newbody->y = 3;
		if ((*head) != NULL)
		{
			temp = (*head);
			(*head) = newbody;
			newbody->next = temp;
		}
		else
		{
			(*head) = newbody;
			(*head)->next = NULL;
		}
		snakelong -= 2;
	}

}
void Pos(int x, int y)
{
	COORD pos;
	HANDLE output;
	pos.X = x;
	pos.Y = y;
	output = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(output, pos);
}


int main()
{

	system("mode con cols=60 lines=31");
	Pos(18, 8);
	printf("********************");
	Pos(18, 9);
	printf("|**欢迎来到贪吃蛇**|");
	Pos(18, 10);
	printf("|***作者:YUXUAN***|");
	Pos(18, 11);
	printf("|按任意建开始游戏…|");
	Pos(18, 12);
	printf("********************");
	Pos(4, 13);
	printf("'w','a','s','d','空格','q','e',分别为上下左右暂停,q为加速,e为减速.\n输入其他字符直接退出游戏。");
	_getch();
again:
	int snakelong = 4, speed = 400, speedup = 0,ask=1;
	snake* head = NULL;
	COORD nhead, tail, food;
	char dir = 'd', temp = 'd',Q;
	makesnake(&head);
	food = makefood(head);
	system("cls");
	printmap();
	Pos(0, 30);
	printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup*50));
	printfood(food);
	while (temp == 'w' || temp == 'a' || temp == 's' || temp == 'd' || temp == ' ' || temp == 'q' || temp == 'e') 
	{
		Sleep(speed + (speedup*50));
		while (_kbhit())
		{
			temp = _getch();
			if (((dir == 'w' && temp != 'w') && (dir == 'w'&& temp != 's')) && ((dir == 's' && temp != 's') && (dir == 's' && temp != 'w')) && ((dir == 'a' && temp != 'a') && (dir == 'a'&&  temp != 'd')) && ((dir == 'd' && temp != 'd') && (dir == 'd' && temp != 'a')) && temp != 'q' && temp != 'e')
			{
				if (temp == 'w' || temp == 'a' || temp == 's' || temp == 'd' || temp == ' ')
				{
					break;
				}
			}//检测到如果得到有用的键入时,就退出。
			else
			{
				if (temp == 'q' || temp == 'e'||temp ==' ')
				{
					if (temp == 'q')
					{
						if (((speedup - 1) * 50 + speed) >= 50)
						{
							speedup--;
						}//防止减到零。
						temp = dir;
						Pos(0, 30);
						printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup * 50));
					}
					if (temp == 'e')
					{
						speedup++;
						temp = dir;
						Pos(0, 30);
						printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup * 50));
					}
				}
				else 
				{
					continue;
				}
			}
		}
		if (temp == ' ')
		{
			temp = dir;
			Pos(1, 1);
			printf("暂停!");
			_getch();
			Pos(1, 1);
			printf("#     ");

		}
		else
		{
			if (dir == 'w' && temp != 's' || dir == 's' && temp != 'w' || dir == 'a' && temp != 'd' || dir == 'd' && temp != 'a') {
				dir = temp;
			}
		}//按键输入。

		switch (dir) {
		case 'w':
			nhead.X = head->x;
			nhead.Y = head->y - 1;
			break;
		case 's':
			nhead.X = head->x;
			nhead.Y = head->y + 1;
			break;
		case 'a':
			nhead.X = head->x - 2;
			nhead.Y = head->y;
			break;
		case 'd':
			nhead.X = head->x + 2;
			nhead.Y = head->y;
			break;
		}
		if (nhead.X <= 0 || nhead.Y <= 0 || nhead.X >= 59 || nhead.Y >= 29 || deal(nhead, head))
		{
			Pos(1, 1);
			printf("您失败了!");
			Pos(1, 2);
			printf("请问是否再玩一遍?(y/n)");
			while (ask)
			{
				Q = _getch();
				if ('n' == Q)
				{
					system("cls");
					release(&head);//释放链表。
					exit(1);
				}
				else
				{
					if ('y' == Q) {
						release(&head);
						goto again;
					}
					else
					{
						ask = 1;
					}
				}
			}
		}//判断是否撞到了墙壁。
		else
		{
			movesnake(nhead, &head);//移动蛇,头插法,插入新的蛇头。
			tail = findtail(head);//寻找蛇尾。
			if (nhead.X == food.X && food.Y == nhead.Y) {
				printsnake(head);//输出蛇身。
				cleantail(tail);//在原本蛇尾的位置输出空格。
				food = makefood(head);
				printfood(food);
				snakelong++;
				
				if (((speedup) * 50 + speed-1) >= 50)
				{
					speed--;
					Pos(0, 30);
					printf("蛇长度为%3d,速度为%5.2f格/秒", snakelong, 1000.0 / (speed + speedup * 50));//蛇速度随蛇长度的变化而改变。
				}//防止减到零。
				if(snakelong == 784)
				{
					Pos(20, 15);
					printf("你成功了!");
					Pos(20, 16);
					printf("还想在玩一遍吗?(y/n)");

					while (ask)
					{
						Q = _getch();
						if ('n' == Q)
						{
							system("cls");
							release(&head);//释放链表。
							exit(1);
						}
						else
						{
							if ('y' == Q) {
								release(&head);
								goto again;
							}
							else
							{
								ask = 1;
							}
						}
					}
				}
			}//吃到了食物不用删除蛇尾,重新生成食物。
			else {
				deltail(&head);//删除蛇尾。
				printsnake(head);//输出蛇身。
				cleantail(tail);//在原本蛇尾的位置输出空格。
			}//没有吃到食物,删除食物。

		}


	}
	return 0;
}







//17:09 2021/2/12

总结

如果还有需要什么改进的,请大佬们多多指教。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值