用C实现贪吃蛇,看看你的C学得怎样?(四)

写在开始

上一篇博客的链接为:用C实现贪吃蛇,看看你的C学得怎样?(三)

任务清单

本次项目的任务清单暂定如下:
1.创建地图和起始界面(已完成)
2.创建蛇,食物、超级食物投放(已完成)
3.通过键盘控制蛇的移动(已完成)
4.基本功能(蛇吃食物,蛇的增长等)
5.判断游戏是否结束
6.计算游戏时长
7.加入最高纪录功能
8.游戏等级进度
9.游戏重新开始

代码实现

//1.定义头文件
#include<stdio.h> 
#include<conio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>

//2.宏定义声明
#define X 23       //定义地图大小
#define Y 50

#define UP 0              //0为上,1为下,2为左,3为右                       
#define DOWN 1                           
#define LEFT 2                           
#define RIGHT 3

char map[X][Y];          //地图数组
int s[X*Y][2];          //蛇身坐标数组

int sLength;           //蛇的长度
int direction;         //蛇的方向
int delay = 250;     //通过延迟控制蛇的行进速度

int score = 0;          //得分
int level = 1;

bool eated = false;     //标记是否吃到食物

//定义主函数
int main() 
{
	init();                 //初始化
	menu();					//生成界面
	system("cls");          //清除屏幕内容
	draw_map();            //画地图
	food();                     //画食物
	s_food();
	while (1)
	{
		draw_snake();                //画蛇
		Sleep(delay);           //等待一段时间
		key();
		move();                //移动蛇(主要是修改蛇身数组的数据)
		if (map[s[0][0]][s[0][1]] == -1) //如果蛇头碰到食物,就重新投放食物,并且把食物点重置为0
		{
			eated = true;             //标记已经吃到食物
			score += 20;
			sLength++;
			if (game_level() != level)
			{
				delay -= 10;
				level++;
			}
			eated = false;        //设置为false,不然无限变长
			food();
			map[s[0][0]][s[0][1]] = 0;  //去掉食物
		}
		if (map[s[0][0]][s[0][1]] == 2)
		{
			eated = true;
			score += 50;
			sLength += 2;
			if (game_level() != level)
			{
				delay -= 10;
				level++;
			}
			eated = false;        //设置为false,不然无限变长
			s_food();
			map[s[0][0]][s[0][1]] = 0;
		}
		if (gameover())
		{
			system("cls");          //清除屏幕内容
			printf("Game Over\n");
			printf("最终得分:%d\n\n", score);
			break;
		}
	}
}

//定义函数
void init()         //程序开始时的初始化操作
{
	CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);    //隐藏关标
	int i, j;
	for (i = 0; i<X; i++)
	{
		map[i][0] = 1;          //让第一列为1
		map[i][Y - 1] = 1;        //让最后一列为1
	}
	for (j = 0; j<Y; j++)
	{
		map[0][j] = 1;      //让第一行为1
		map[X - 1][j] = 1;    //让最后一行为1
	}
	sLength = 4;          //让蛇的最初长度为4
	s[0][0] = X / 2;
	s[0][1] = Y / 2;        //给蛇头坐标赋值
	for (i = 1; i<4; i++)
	{
		s[i][0] = s[0][0] + i;
		s[i][1] = s[0][1];   //给刚开始的蛇身几个初始坐标
	}
}

void gotoxy(int i, int j)        //移动光标
{
	COORD position = { j, i };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
}

void draw_map()   //创建地图   
{
	gotoxy(0, 0);
	int i, j;
	for (i = 0; i<X; i++)    //两重for循环遍历数组
	{
		for (j = 0; j<Y; j++)         
		{
			if (map[i][j] == 0)          //为0输出空格
				printf(" ");
			else if(map[i][j]==1)       //为1输出#
				printf("#");
		}
		printf("\n");               //别忘了换行
	}
}

void menu()         //初始菜单界面
{
	printf("\n\n\n\n\n\n\t\t\t********************贪吃蛇(实验版)******************\t\t\t\n\n");
	printf("\t\t\t********************欢迎参与游戏测试******************\t\t\t\n\n");
	printf("\t\t\t********************按任意键开始游戏******************\t\t\t\n\n");
	printf("\t\t\t\t\t      职业工具人\n\n");
	printf("\t\t\t\t请先确保处于英语输入法,否则无法进行游戏");
	_getch();    //保持界面获取字符
}

int check(int ii, int jj)        //判断这个点能不能放食物,可以放返回1,不能放返回0
{
	if (map[ii][jj] == 1)        //如果有障碍物,返回0
		return 0;
	int i;
	for (i = 0; i<sLength; i++)
	{
		if (ii == s[i][0] && jj == s[i][1])      //如果和其中一个蛇身重合,就返回0
			return 0;
	}
	if (ii == 0 || ii == X - 1 || jj == 0 || jj == Y - 1)      //如果在边界上面,返回0
		return 0;
	if(map[ii][jj]==-1)             //若该点有食物,则不生成超级食物                
		return 0;
	return 1;                       //最后筛选 过后的是符合条件的点
}

void food()  //生成食物
{
	int i, j;
	do
	{
		i = rand() % X;                 //生成0~X-1之间的一个数
		j = rand() % Y;                 //生成0~Y-1之间的一个数
	} 
	while (check(i, j) == 0);           //生成点直到满足条件
	map[i][j] = -1;                     //标记为食物
	gotoxy(i, j);
	printf("*");                    //画出食物
}

void s_food()  //生成超级食物
{
	int i, j;
	do
	{
		i = rand() % X;
		j = rand() % Y;
	} 
	while (check(i, j) == 0);
	map[i][j] = 2;
	gotoxy(i, j);
	printf("$");
}

void draw_snake()                //画蛇
{
	int i;
	for (i = 0; i<sLength; i++)
	{
		gotoxy(s[i][0], s[i][1]);        //移动关标到蛇的坐标
		printf("@");                    //在这个位置画蛇
	}
}

void key()       //定义key,用于接受按键键值
{
	if (_kbhit() != 0)          //如果有键盘输入
	{
		char in;
		while (!_kbhit() == 0)  //如果玩家输入了多个按键,以最后一个按键为准
			in = _getch();
		switch (in)
		{
		case 'w':
		case 'W':
			if (direction != DOWN)         //不能后退
				direction = UP;
			break;
		case 's':
		case 'S':
			if (direction != UP)
				direction = DOWN;
			break;
		case 'a':
		case 'A':
			if (direction != RIGHT)
				direction = LEFT;
			break;
		case 'd':
		case 'D':
			if (direction != LEFT)
				direction = RIGHT;
			break;
		}
	}
}

void move()                    //控制蛇的移动
{
	int i;
	gotoxy(s[sLength - 1][0], s[sLength - 1][1]);
	printf(" ");                            //在尾巴上面画空格以擦除尾巴
	for (i = sLength - 1; i > 0; i--)  //从尾巴开始,每一个点的位置等于它前面一个点的位置
	{
		s[i][0] = s[i - 1][0];
		s[i][1] = s[i - 1][1];
	}
	switch (direction)
	{
	case UP:
		s[0][0]--;
		break;
	case DOWN:
		s[0][0]++;
		break;
	case LEFT:
		s[0][1]--;
		break;
	case RIGHT:
		s[0][1]++;
		break;
	}
}

bool gameover()             //判断是不是结束游戏
{
	int sX = s[0][0], sY = s[0][1];      //蛇头的x坐标和y坐标
	if (sX == 0 || sX == X - 1 || sY == 0 || sY == Y - 1)
		GameOver = true;
	for (int i = 1; i<sLength; i++)    //判断有没有吃到自己
	{
		if (s[i][0] == sX && s[i][1] == sY)
			GameOver = true;
	}
	return GameOver;
}

int game_level()   //速度等级构建
{
	int Level = score / 100 + 1;
	return Level;
}

总结

本次主要是完善了蛇的移动速度、蛇吃到食物以后的变化、游戏的终止条件,到此为止,整个贪吃蛇的基本功能已经完成了。

接下来就是完善一些细节的功能,让功能更加完善!

结语

如果说这篇文章有让你学到一定的知识的话,不妨点个赞和关注,让博主能够看到,如果讲解中有什么错误和疏忽,也劳烦在评论中指出或提问,博主会第一时间进行更新和答复,谢谢!

发布了24 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44018540/article/details/104156092