C语言——贪吃蛇游戏&超详细注释(部分细节还在完善)

实现效果如图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
目前得分代码还有问题不能正确输出,且改颜色也未完善,其他功能正常,有问题待改进。
代码如下:

#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#define height 28	//方块高度 
#define width 60	//方块宽度,必须为偶数

//--------------函数声明---------------------
void GameStare();			//启动画面
void GameOver();			//结束画面
void draw_cube();			//画边框
void initialization();		//初始化蛇身
void gotoxy(int x, int y); 	//移动坐标
void move();				//蛇身移动
void p_move();				//处理蛇头移动后蛇身指针的移动
void food();				//产生食物
void judge_head();			//判断蛇头的位置
void static_info();			//静态信息,如游戏侧栏文字提示
void dynamic_info();		//动态信息,如游戏得分
//--------------------------------------------

//--------------全局变量-----------------------
struct snake
{
	int x, y;				//坐标
	struct snake* next;		// 
}*head = NULL, * scan = NULL, * pf = NULL, * pb = NULL;

int speed = 300;				//移动速度(毫秒)
int length = 4;				//初始蛇长
char direction = 'd';			//蛇头方向:w/s/a/d
int food_x, food_y;			//食物坐标
int tail_x, tail_y;			//蛇尾坐标
int snake_xy[1024];			//存储蛇身上每一个节点的坐标
short score = 0;				//游戏得分
short music = 1;				//吃到食物后响铃
//------------------------------------------------

//---------------函数定义区-----------------------	 
void draw_cube()
{
	int i;
	for (i = 1;i <= height;i++)//左右方框
	{
		gotoxy(0, i);		printf("■");
		gotoxy(width, i);	printf("■");
	}
	for (i = 0;i <= width + 1;i += 2)//上下方框
	{
		gotoxy(i, 0);		printf("■");
		gotoxy(i, height + 1);	printf("■");
	}
}

void initialization()		//游戏开始后的初始界面绘制
{
	int i;
	draw_cube();			//画方格框架
	for (i = 1;i <= length;i++)	//画出初始蛇身
	{
		pb = (struct snake*)malloc(sizeof(struct snake));
		pb->y = 17;			//初始纵坐标y=17
		pb->x = 28;		//初始横坐标x=28

		if (i == 1)			//打印蛇头
		{
			head = scan = pf = pb;//保存蛇头纵坐标
			gotoxy(pb->x, pb->y);//移动光标
			printf("■");		//绘制蛇头
		}
		else				//打印初始蛇身
		{
			pb->x = pf->x - 2;	//x轴上"■"占2个坐标位置
			gotoxy(pb->x, pb->y);
			printf("■");		//绘制蛇身
			pf->next = pb;		//指向下一个蛇的肢体
		}

		pf = pb;
		pf->next = NULL;
	}
}

void gotoxy(int x, int y)		//移动光标函数
{
	COORD coord;				//声明该类型的变量
	coord.X = x;
	coord.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
	//设置光标位置
}

void GameStart()				//游戏启动界面绘制函数
{
	draw_cube();
	gotoxy(25, 10);	printf("贪吃蛇游戏!");
	gotoxy(22, 17);
	system("pause");
}

void GameOver()					//游戏结束界面绘制函数
{
	system("cls");				//清除屏幕
	draw_cube();
	gotoxy(25, 10);	printf("Game Over!");
	gotoxy(25, 12); printf("得分:%d");
	gotoxy(22, 17);
	printf("请按任意键继续...");
	getch();
	exit(0);
}
void static_info()			//静态信息绘制函数
{
	gotoxy(width + 4, 2);	printf("←↑↓→进行控制");
	gotoxy(width + 4, 3);	printf("按任意键暂停");
	gotoxy(width + 4, 4);	printf("F1加速,F2减速");
	gotoxy(width + 4, 5);	printf("F3开关声音");
	gotoxy(width + 4, 8);	printf("得分:");
	gotoxy(width + 4, 10);	printf("蛇头位置:");
	gotoxy(width + 4, 12);	printf("食物位置:");
	gotoxy(width + 4, 14);	printf("声音:");
	gotoxy(width + 4, 16);	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_RED | FOREGROUND_INTENSITY);printf("F4:■");//红色
	gotoxy(width + 4, 18);	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);printf("F5:■");//黄色
	gotoxy(width + 4, 20);	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_GREEN | FOREGROUND_INTENSITY);printf("F6:■");//绿色
	gotoxy(width + 4, 22);	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);printf("F7:■");//紫色
	gotoxy(width + 4, 24);	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);printf("F8:■");//亮白色
	gotoxy(width + 4, 26);	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
		FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);printf("F9:■");//灰色

}
void dynamic_info()			//动态信息绘制函数
{

	gotoxy(width + 9, 8);	printf("%d", score);			  //输出成绩
	gotoxy(width + 13, 10);	printf("%2d,%2d", head->x, head->y);//输出蛇头位置
	gotoxy(width + 13, 12);	printf("%2d,%2d", food_x, food_y);  //输出食物位置
	gotoxy(width + 9, 14);	music == 1 ? printf("开") : printf("关");//音乐开关
}

void move()
{
	short a, b;					//接受上下左右键
	char key_direction = 'd';	//蛇头初始移动方向
	while (!kbhit())			//判断是否有按键输入;蛇身移动
	{
	loop:						//循环跳转标志
		gotoxy(food_x, food_y);	//绘制食物
		printf("■");
		switch (direction)
		{
		case 'w':gotoxy(scan->x, scan->y - 1);	printf("■");
			p_move();head->y = head->y - 1;break;
		case 'a':gotoxy(scan->x - 2, scan->y);	printf("■");
			p_move();head->x = head->x - 2;break;
		case 's':gotoxy(scan->x, scan->y + 1);	printf("■");
			p_move();head->y = head->y + 1;break;
		case 'd':gotoxy(scan->x + 2, scan->y);	printf("■");
			p_move();head->x = head->x + 2;break;
		}
		dynamic_info();				//动态信息输出
		scan = head;
		judge_head();				//判断蛇头状态
		Sleep(speed);				//速度控制
	}
	scan = head;
	a = getch();
	b = getch();
	switch (a)						//控制蛇移动方向
	{
	case 224:switch (b)				//相反方向不可移动
	{
	case 72:key_direction = 'w';if (direction == 's')key_direction = 0;break;
	case 75:key_direction = 'a';if (direction == 'd')key_direction = 0;break;
	case 80:key_direction = 's';if (direction == 'w')key_direction = 0;break;
	case 77:key_direction = 'd';if (direction == 'a')key_direction = 0;
	}break;
	case 0:switch (b)
	{
	case 59:speed -= 20;break;
	case 60:speed += 20;break;
	case 61:music = music == 1 ? 0 : 1;break;
	}break;

	dafault:goto loop;
	}

	if (key_direction)
		direction = key_direction;
	else
		goto loop;
	goto loop;
}

void p_move()			//处理蛇头移动后蛇身指针的移动
{
	short i = 0;
	while (scan->next != NULL)
		scan = scan->next;	//scan最终指向蛇尾
	gotoxy(scan->x, scan->y);printf("  ");//消去蛇尾,即走过的位置为空
	scan = head;		//scab指向原来的蛇头位置

	while (scan->next != NULL)	//存储从蛇头到蛇尾的前一个节点坐标
	{
		snake_xy[i] = scan->x;
		i++;
		snake_xy[i] = scan->y;
		i++;
		scan = scan->next;
	}
	//存储蛇尾坐标,为在吃到食物时,给坐标输出(+)方块
	tail_x = scan->x;
	tail_y = scan->y;
	i = 0;
	scan = head->next;
	while (scan->next != NULL)//把存储的坐标逐个赋值给蛇头位置之后的结点,直至蛇尾结束
	{
		scan->x = snake_xy[i];
		i++;
		scan->y = snake_xy[i];
		i++;
		scan = scan->next;
	}
	scan->x = snake_xy[i];
	i++;
	scan->y = snake_xy[i];
	i++;
}

void food()						//随机生产食物
{
	short i = 0;
	srand((unsigned)time(NULL));
	do
	{
		food_x = rand() % (width - 3) + 2;
	} while (food_x % 2);
		food_y = rand() % (height - 1) + 1;
	gotoxy(food_x, food_y);
	printf("■");
	scan = head;
}

void judge_head()				//判断蛇头状态
{
	short i = 0;
	if (head->x == 0 || head->x == width || head->y == 0 || head->y == height + 1)	//是否撞墙
		GameOver();

	while (scan->next != NULL)
	{
		if (head->x == snake_xy[i])
			if (head->y == snake_xy[++i])
				GameOver();
			else
				i++;
		else
			i += 2;
		scan = scan->next;
	}
	if (head->x == snake_xy[i])				//是否直接咬到自己
		if (head->y == snake_xy[++i])
			GameOver();

	if (head->x == food_x && head->y == food_y)//如果吃到食物,给尾巴加上一节
	{
		if (music)
			putchar(7);	//响铃
		score += 10;
		pb = (struct snake*)malloc(sizeof(struct snake));
		pf->next = pb;
		pb->next = NULL;
		pf = pb;
		pb->x = tail_x;
		pb->y = tail_y;
		gotoxy(pb->x, pb->y);
		printf("■");
		food();
	}
	scan = head;
}

//-------------------------------------
//main主函数
int main()
{
	system("mode con:cols =80 lines=31");		//设置成80列,30行
	GameStart();
	system("cls");
	initialization();					//初始化蛇身
	food();
	static_info();
	move();
	system("pause");
	return 0;
}



已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页