HeartBeatDHP

这还要描述???

传统的贪吃蛇小游戏 铜牌收录

说明

这是一个传统的贪吃蛇小游戏,使用 a、s、d、w 四个按键控制蛇的移动,不要让蛇头碰到边界,也不要让蛇头碰到自己的身体。每吃一个食物就会长一节身体。第一次写的小程序,做的不好,请见谅。

效果图

游戏说明

键盘在小写模式下按 a、w、s、d 改变移动方向。

代码

/////////////////////////////////////////////////////////////
// 程序名称:贪吃蛇
// 编译环境:Visual Studio 2019, EasyX_20211109
// 作  者:心跳C<halt_233@qq.com>
// 最后修改:2020-7-15
//

// 头文件
#include <graphics.h>
#include <conio.h>
#include <ctime>

// 窗口大小
int windowX = 640, windowY = 480;

int FoodPosX()
{
	// 定义随机数
	srand((int)time(0));

	int foodPosX;
	foodPosX = (rand() % (windowX / 20 - 2) + 1) * 20 + 10;
	return foodPosX;
}
int FoodPosY()
{
	// 定义随机数
	srand((int)time(0));

	int foodPosY;
	foodPosY = (rand() % (windowY / 20 - 2) + 1) * 20 + 10;
	return foodPosY;
}

int main()
{

	//
	bool startGame = false;

	// 颜色设定
	COLORREF backgroundColor = RGB(10, 10, 10);
	COLORREF limitColor = RGB(255, 150, 50);
	COLORREF snakeColor = RGB(50, 250, 100);
	COLORREF foodColor = RGB(255, 255, 255);

	// 最大长度为沾满屏幕的所以格子
	int snakeMaxLength = ((windowX / 20) - 1) * ((windowY / 20) - 1);

	// 定义当前长度
	int snakeLength;

	// 食物坐标
	int foodX, foodY;

	// 蛇的坐标信息
	int* snakeX = new int[snakeMaxLength];
	int* snakeY = new int[snakeMaxLength];

	// 蛇的朝向
	int tower;

	// 绘制边界的变量
	int bjx, bjy;

	// 获取当前操作的变量
	char ch = 'd';

	// 绘制窗口
	initgraph(windowX, windowY);
	setbkcolor(backgroundColor);
	cleardevice();

	// food 生成相关
	bool foodCanPut = false;

reStrat:
	// 定义初始长度,小于 (windowX / 2) - 2
	snakeLength = 3;

	// 定义初始坐标
	for (int i = snakeLength - 1; i >= 0; i--)
	{
		snakeX[i] = 30 + 20 * (snakeLength - i - 1);
		snakeY[i] = 70;
	}

	// 定义初始朝向
	tower = 4;

	// 设定初始食物坐标
	foodX = FoodPosX();
	foodY = FoodPosY();
	while (foodCanPut == false)
	{
		for (int i = 0; i < snakeLength; i++)
		{
			if (foodX != snakeX[i] || foodY != snakeX[i])
			{
				foodCanPut = true;
			}
			else if (foodX == snakeX[i] && foodY == snakeX[i])
			{
				foodX = FoodPosX();
				foodY = FoodPosY();
				foodCanPut = false;
			}
		}
	}

	// 开始菜单
	settextstyle(20, 0, _T("Consolas"));
	cleardevice();
	outtextxy(windowX / 2 - 50, windowY / 2, _T("按任意键继续开始"));
	system("pause");
	cleardevice();

	// 绘制边界
	setlinecolor(limitColor);
	for (int i = 10; i <= windowX - 10; i += 20)
	{
		bjx = i;
		if (i == 10 || i == windowX - 10)
		{
			for (int j = 10; j <= windowY - 10; j += 20)
			{
				bjy = j;
				rectangle(bjx - 9, bjy - 9, bjx + 9, bjy + 9);
			}
		}
		rectangle(bjx - 9, bjy - 9, bjx + 9, bjy + 9);
		rectangle(bjx - 9, 10 - 9, bjx + 9, 10 + 9);
		Sleep(windowX / 20);
	}

	// 倒计时动画
	settextstyle(72, 0, _T("Consolas"));
	outtextxy(windowX / 2 - 10, windowY / 2 - 40, _T("3"));
	Sleep(1000);
	clearrectangle(20, 20, windowX - 20, windowY - 20);
	outtextxy(windowX / 2 - 10, windowY / 2 - 40, _T("2"));
	Sleep(1000);
	clearrectangle(20, 20, windowX - 20, windowY - 20);
	outtextxy(windowX / 2 - 10, windowY / 2 - 40, _T("1"));
	Sleep(1000);
	clearrectangle(20, 20, windowX - 20, windowY - 20);
	settextstyle(20, 0, _T("Consolas"));

	int ctrl = 0;

	// 游戏主体
	while (1)
	{
		if (_kbhit())
		{
			ch = _getch();
		}
		ctrl++;
		while (ctrl > 100)
		{
			ctrl = 0;
			// 清理除边界外的所有
			clearrectangle(20, 20, windowX - 20, windowY - 20);

			// 目前方向
			switch (ch)
			{
			case 'a':
				if (tower != 4)
				{
					tower = 1;
				}
				break;
			case 'w':
				if (tower != 3)
				{
					tower = 2;
				}
				break;
			case 's':
				if (tower != 2)
				{
					tower = 3;
				}
				break;
			case 'd':
				if (tower != 1)
				{
					tower = 4;
				}
				break;
			default:
				break;
			}

			// 判定吃食物
			if (snakeX[0] == foodX && snakeY[0] == foodY)
			{
				snakeLength++;
				foodX = FoodPosX();
				foodY = FoodPosY();
				while (foodCanPut == false)
				{
					for (int i = 0; i < snakeLength; i++)
					{
						if (foodX != snakeX[i] || foodY != snakeX[i])
						{
							foodCanPut = true;
						}
						else if (foodX == snakeX[i] && foodY == snakeX[i])
						{
							foodX = FoodPosX();
							foodY = FoodPosY();
							foodCanPut = false;
						}
					}
				}
			}

			// 计算尾巴坐标
			for (int i = snakeLength - 1; i >= 0; i--)
			{
				if (i != 0)
				{
					snakeX[i] = snakeX[i - 1];
					snakeY[i] = snakeY[i - 1];
				}
			}

			// 蛇头坐标
			switch (tower)
			{
			case 1:
				snakeX[0] -= 20;
				break;
			case 2:
				snakeY[0] -= 20;
				break;
			case 3:
				snakeY[0] += 20;
				break;
			case 4:
				snakeX[0] += 20;
				break;
			}

			// 判断撞身体
			for (int i = 0; i < snakeLength; i++)
			{
				if (i != 0 && snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0])
				{
					snakeX[0] = 10;
				}
			}

			// 结束菜单
			if (snakeLength == snakeMaxLength)
			{
				outtextxy(windowX / 2 - 50, windowY / 2 + 20, _T("胜利!"));
				outtextxy(windowX / 2 - 50, windowY / 2, _T("按任意键继续"));
				system("pause");
				cleardevice();
				outtextxy(windowX / 2 - 50, (windowY / 2) - 10, _T("按“Y”重玩"));
				outtextxy(windowX / 2 - 50, (windowY / 2) + 10, _T("按“N”结束"));
				while (1)
				{
					ch = _getch();
					if (ch == 'y' || ch == 'Y')
					{
						goto reStrat;
					}
					else if (ch == 'n' || ch == 'N')
					{
						goto endGame;
					}
				}
			}

			// 判断撞墙
			if (snakeX[0] >= windowX - 10 || snakeX[0] <= 10 || snakeY[0] >= windowY - 10 || snakeY[0] <= 10)
			{
				cleardevice();
				outtextxy(windowX / 2 - 35, windowY / 2 - 20, _T("你失败了"));
				outtextxy(windowX / 2 - 50, windowY / 2, _T("按任意键继续"));
				system("pause");
				cleardevice();
				outtextxy(windowX / 2 - 50, (windowY / 2) - 10, _T("按“Y”重玩"));
				outtextxy(windowX / 2 - 50, (windowY / 2) + 10, _T("按“N”结束"));
				while (1)
				{
					ch = _getch();
					if (ch == 'y' || ch == 'Y')
					{
						goto reStrat;
					}
					else if (ch == 'n' || ch == 'N')
					{
						goto endGame;
					}
				}
			}

			BeginBatchDraw();
			// 绘制食物
			setlinecolor(foodColor);
			rectangle(foodX - 8, foodY - 8, foodX + 8, foodY + 8);

			// 绘制蛇
			setlinecolor(snakeColor);
			for (int i = 0; i < snakeLength; i++)
			{
				rectangle(snakeX[i] - 8, snakeY[i] - 8, snakeX[i] + 8, snakeY[i] + 8);
			}
			EndBatchDraw();

			// 速度
			Sleep(100);
		}

	}
endGame:
	delete[] snakeX;
	delete[] snakeY;

	return 0;
}

添加评论