C/Cpp贪吃蛇(数组)

在长度已知的情况下,创建一个int型变量lenth来确定数组的上限比用链表查找到NULL要简单一些。

#include <iostream>
#include <cstring>
#include <Windows.h>
#include <conio.h>
#include <time.h>
using namespace std;

int score = 0;                                                                         //初始分数与长度
int lenth = 3;
int food_line, food_colu;                                                              //食物所在的行列(没有写x,y,因为x和图上的行是反的,不便于理解)
typedef struct
{
	int line;                                                                          //line行,column为列,此处简写colu
	int colu;
}Body;
Body snake[1000];                                                                      //蛇身上限为1000

void Gotoxy(int x, int y);                                                             //光标移动函数
void Color(int x);                                                                     //颜色改变函数
void Gotoprint(int x, int y);                                                          //移动到指定坐标,然后打印■
void Gotodelete(int x, int y);                                                         //移动到指定坐标,然后打印" "(空格),实现删除
void Color_change(int scores);                                                         //打印分数的时候改变分数的颜色
void Welcome();                                                                        //欢迎界面
void Clean_welcome();                                                                  //清除欢迎界面
void Initialize();                                                                     //初始化函数
void Play();                                                                           //游戏运行函数
void Creat_fence();                                                                    //创造墙
void Creat_score();                                                                    //创造分数
bool Judge();                                                                          //判断游戏是否结束
void Move();                                                                           //身体移动
void Turn(char click);                                                                 //身体转向
void Print_body();                                                                     //打印身体函数
void Wait();                                                                           //根据分数选择Sleep()的时间
void Creat_food();                                                                     //创造食物
bool Food_exist();                                                                     //判断食物是否被吃了
void Body_extend();                                                                    //身体变长函数
void End();                                                                            //结束界面
//打印■时,需要占据两个水平单位的大小,即■只能打印在偶数横坐标上,否则无法显示,因此蛇的身体的横坐标也必须为偶数

int main()
{
	Welcome();
	Initialize();
	Creat_fence();
	Play();
	End();
}

void Gotoxy(int x, int y)                                                              //具体内容参考百度百科
{
	COORD pos;
	HANDLE hOutput;
	pos.X = x;
	pos.Y = y;
	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOutput, pos);
}

void Color(int x)	                                                                   //自定义函根据参数改变颜色 
{
	if (x >= 0 && x <= 15)                                                             //参数在0-15的范围颜色
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);	               //只有一个参数,改变字体颜色   
	}
	else                                                                               //默认的颜色白色    	
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
	}
}

void Gotoprint(int x, int y)
{
	Gotoxy(x, y);
	cout << "■";
}

void Gotodelete(int x, int y)
{
	Gotoxy(x, y);
	cout << " ";
	Gotoxy(x + 1, y);
	cout << " ";
}

void Color_change(int scores)
{
	if (scores > 250)
	{
		Color(13);
	}
	else if (scores > 200)
	{
		Color(12);
	}
	else if (scores > 150)
	{
		Color(9);
	}
	else if (scores > 100)
	{
		Color(10);
	}
	else if (scores > 50)
	{
		Color(14);
	}
	else
	{
		Color(7);
	}
}

void Welcome()
{
	Gotoxy(15, 10); Color(7);
	cout << "---------------------------------";
	Gotoxy(15, 11); Color(11);
	cout << "Welcome come to paly this game!";
	Gotoxy(15, 12);
	cout << "Press any key to continue";
	Gotoxy(15, 13); Color(7);
	cout << "---------------------------------";
	Gotoxy(60, 12); Color(12);
	cout << "Created by Morning";
	_getch();
	Clean_welcome();
}

void Clean_welcome()
{
	Gotoxy(15, 10);
	cout << "                                          ";
	Gotoxy(15, 11);
	cout << "                                          ";
	Gotoxy(15, 12);
	cout << "                                          ";
	Gotoxy(15, 13);
	cout << "                                          ";
	Gotoxy(60, 12);
	cout << "                                          ";
}

void Initialize()
{
	memset(snake, -1, sizeof(snake));                                                  //身体部分的初始化
	snake[0].line = 16;
	snake[0].colu = 16;
	snake[1].line = 16;
	snake[1].colu = 17;
	snake[2].line = 16;
	snake[2].colu = 18;
	Print_body();
	Creat_food();                                                                      //食物的初始化
}

void Creat_fence()
{
	Color(11);
	int i = 0;
	for (i = 0; i <= 50; i += 2)                                                       //打印上下边框
	{
		Gotoprint(i, 0);
		Gotoprint(i, 25);
	}
	for (i = 1; i <= 25; ++i)                                                          //打印左右边框
	{
		Gotoprint(0, i);
		Gotoprint(50, i);
	}
	Gotoxy(57, 11); Color(7);
	cout << "-----  Your Score is";
	Gotoxy(81, 11);
	cout << "-----";
	Gotoxy(63, 13);
	cout << "Press WASD to move";
	Gotoxy(63, 14);
	cout << "                                  ";
	Gotoxy(63, 14);
	cout << "Press P to pause";
}

void Creat_score()
{
	Gotoxy(78, 11); Color_change(score);
	cout << score;
	Color(11);
}

void Play()
{
	while (Judge() == true)
	{
		Creat_fence();
		Creat_score();                                                                 //创建分数
		if (_kbhit())                                                                  //如果有键盘输入则转向,_kbhit为非阻塞函数,_getch为阻塞函数,区别详见百度
		{
			char click = _getch();
			Turn(click);
		}
		else                                                                           //没有输入则向前移动
		{
			Move();                                                                    //身体移动
		}
		if (Food_exist() == false)
		{
			Gotodelete(food_line, food_colu);                                          //清除原先食物
			Body_extend();                                                             //身体长长
			Creat_food();                                                              //创建新食物
			score += 10;                                                               //分数+10
		}
	}
}

bool Judge()
{
	int re = true;
	if (snake[0].colu <= 0 || snake[0].colu >= 25)                                        //碰到上下墙
	{
		re = false;
	}
	else if (snake[0].line <= 0 || snake[0].line >= 50)                                   //碰到左右墙
	{
		re = false;
	}
	else
	{
		for (int i = 1; i <= lenth - 1; ++i)                                              //遍历自身,判断身体中是否有部位与头部相接
		{
			if (snake[i].colu == snake[0].colu && snake[i].line == snake[0].line)         //吃到自己
			{
				re = false;
				break;
			}
		}
	}
	return (re);
}

void Move()
{
	for (int i = 0; i <= lenth - 1; ++i)                                                  //身体图像的清除,通过清除原先图像再打印新图像实现动画效果
	{
		Gotodelete(snake[i].line, snake[i].colu);
	}
	Body swap[1000];
	for (int i = 0; i <= lenth - 1; ++i)                                                  //用另一个数组存放原来身体的数据
	{
		swap[i] = snake[i];
	}

	int line = snake[0].line - snake[1].line;                                             //line用于判断头部和第二节的位置关系
	int colu = snake[0].colu - snake[1].colu;
	if (line < 0)                                                                         //如果头在第二节的左边,则头部向左移动两个单位
	{
		snake[0].line -= 2;                                                               //移动头部,其余部分移至其前一节
		for (int i = 0; i <= lenth - 2; ++i)
		{
			snake[i + 1] = swap[i];
		}
	}
	else if (line > 0)                                                                    //如果头在第二节右边,则头部向右移动两个单位
	{
		snake[0].line += 2;
		for (int i = 0; i <= lenth - 2; ++i)
		{
			snake[i + 1] = swap[i];
		}
	}
	else if (colu < 0)                                                                    //如果头在第二节上边(即上一行),则头部向上移动一个单位
	{
		snake[0].colu -= 1;
		for (int i = 0; i <= lenth - 2; ++i)
		{
			snake[i + 1] = swap[i];
		}
	}
	else                                                                                  //如果头在第二节下边,则头部向下移动一个单位
	{
		snake[0].colu += 1;
		for (int i = 0; i <= lenth - 2; ++i)
		{
			snake[i + 1] = swap[i];
		}
	}
	Print_body();                                                                         //打印新身体
	Wait();
}

void Turn(char click)
{
	for (int i = 0; i <= lenth - 1; ++i)                                                  //身体图像的清除
	{
		Gotodelete(snake[i].line, snake[i].colu);
	}
	Body swap[1000];
	for (int i = 0; i <= lenth - 1; ++i)                                                  //用另一个数组存放原来身体的数据
	{
		swap[i] = snake[i];
	}
	int line = snake[0].line - snake[1].line;
	int colu = snake[0].colu - snake[1].colu;

	switch (click)
	{
	case 'A':
	case 'a':
		if (line < 0 || line>0)                                                           //左移或右移时,只能向上或向下转动
		{
			break;
		}
		else
		{
			snake[0].line -= 2;
			for (int i = 0; i <= lenth - 2; ++i)
			{
				snake[i + 1] = swap[i];
			}
			break;
		}
	case 'D':
	case 'd':
		if (line < 0 || line>0)
		{
			break;
		}
		else
		{
			snake[0].line += 2;
			for (int i = 0; i <= lenth - 2; ++i)
			{
				snake[i + 1] = swap[i];
			}
			break;
		}
	case 'W':
	case 'w':
		if (colu < 0 || colu>0)                                                           //上移或下移时,只能向左或向右转动
		{
			break;
		}
		else
		{
			snake[0].colu -= 1;
			for (int i = 0; i <= lenth - 2; ++i)
			{
				snake[i + 1] = swap[i];
			}
			break;
		}
	case 'S':
	case 's':
		if (colu < 0 || colu>0)
		{
			break;
		}
		else
		{
			snake[0].colu += 1;
			for (int i = 0; i <= lenth - 2; ++i)
			{
				snake[i + 1] = swap[i];
			}
			break;
		}
	case 'P':                                                                             //按p暂停
	case 'p':
		Gotoxy(63, 14); Color(7);
		cout << "Press any key to continue";
		Color(11);
		Print_body();
		_getch();
	}
	Print_body();
}

void Print_body()
{
	for (int i = 0; i <= lenth - 1; ++i)
	{
		Gotoprint(snake[i].line, snake[i].colu);
	}
}

void Wait()
{
	if (score > 180)
	{
		Sleep(50);
	}
	else if (score > 150)
	{
		Sleep(100);
	}
	else if (score > 120)
	{
		Sleep(150);
	}
	else if (score > 90)
	{
		Sleep(200);
	}
	else if (score > 60)
	{
		Sleep(250);
	}
	else
	{
		Sleep(300);
	}
}

void Creat_food()
{
A:
	srand((int)time(NULL));
	food_line = rand() % (48 - 1 + 1) + 1;
	food_colu = rand() % (23 - 2 + 1) + 2;
	if (food_line % 2 != 0)                                                           //一个■需要占两个水平方向单位长度,判断其是否在双数位上,若在单数位上则不显示
	{
		food_line++;
	}
	for (int i = 0; i <= lenth - 1; ++i)                                              //判断食物是否在蛇身上
	{
		if (snake[i].colu == food_colu && snake[i].line == food_line)
		{
			goto A;                                                                   //如果在蛇身上则重新生成(偷个懒,写了个goto)
		}
	}
	Color(12);                                                                        //打印前切换为红色,打印后切换回青色
	Gotoxy(food_line, food_colu);
	printf("⊙");
	Color(11);
}

bool Food_exist()
{
	int re;
	if (snake[0].colu == food_colu && snake[0].line == food_line)
	{
		re = false;
	}
	else
	{
		re = true;
	}
	return (re);
}

void Body_extend()
{
	int line = snake[lenth - 1].line - snake[lenth - 2].line;
	int colu = snake[lenth - 1].colu - snake[lenth - 2].colu;
	if (line < 0)                                                                      //如果倒数第一节在倒数第二节的左边
	{
		snake[lenth].line = snake[lenth - 1].line - 2;                                 //那么新的一节就在倒数第一节的左边一个单位
		snake[lenth].colu = snake[lenth - 1].colu;
	}
	else if (line > 0)
	{
		snake[lenth].line = snake[lenth - 1].line + 2;
		snake[lenth].colu = snake[lenth - 1].colu;
	}
	else if (colu < 0)
	{	
		snake[lenth].line = snake[lenth - 1].line;
		snake[lenth].colu = snake[lenth - 1].colu - 1;
	}
	else
	{
		snake[lenth].line = snake[lenth - 1].line;
		snake[lenth].colu = snake[lenth - 1].colu + 1;
	}
	++lenth;
	Print_body();
}

void End()
{
	for (int i = 0; i <= lenth - 1; ++i)                                               //清除蛇身
	{
		Gotodelete(snake[i].line, snake[i].colu);
	}
	int i = 0;
	for (i = 0; i <= 50; i += 2)                                                       //清除上下边框
	{
		Gotodelete(i, 0);
		Gotodelete(i, 25);
	}
	for (i = 1; i <= 25; ++i)                                                          //清除左右边框
	{
		Gotodelete(0, i);
		Gotodelete(50, i);
	}
	Gotodelete(food_line, food_colu);                                                  //清除食物
	Gotoxy(57, 11); Color(7);                                                          //清除分数表
	cout << "                                                ";
	Gotoxy(81, 11);
	cout << "                                                ";
	Gotoxy(63, 13);
	cout << "                                                ";
	Gotoxy(63, 14);
	cout << "                                                ";

	Gotoxy(15, 12); Color(11);
	cout << "Congratulation!";
	Gotoxy(15, 13);
	cout << "Your score is ";
	Color_change(score);
	cout << score;
	Gotoxy(15, 14); Color(11);
	cout << "Press any key to end this game";
	_getch();                                                                          //多用了几个getch防止暴躁老哥按急了最后看不到成绩
	_getch();
	_getch();
	_getch();
	_getch();
	_getch();
	_getch();
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值