To my CSDN

贪吃蛇游戏 1.0

编译环境:Visual Studio 2019

注:使用了Easyx 图形库。Easyx下载 Easyx官网

Easyx 图形库安装教程:https://blog.csdn.net/weixin_43919932/article/details/102996507

说明:此贪吃蛇游戏为第一版,使用了库中提供的简单的描线绘图功能所设计,不含资源包。可直接测试运行,贪吃蛇游戏 2.0在此基础上增加了贴图功能,界面相对部分优化。另外,为方便测试,在代码初始位置预留属性框中各属性参数均可自由调整

 

直接上代码:

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS
#undef UNICODE
#undef _UNICODE	
#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <windows.h>

/*--------------------------------属 性---------------------------*/
#define WIDE 1200		/* 窗口大小  WIDE * HIGH像素   	 */
#define HIGH 700
#define FORM 200		/*	设置文字边框宽度  */
#define SIZE 40				//每节蛇的尺寸
#define LEN 100				//蛇的最长长度
#define COLOUR RGB(rand()%255,rand()%255,rand()%255)	//彩色

static int speed = 100;		//速度(控制刷新的时间间隔)

enum Direction { right = 77, left = 75, down = 80, up = 72, Esc = 27 };//枚举方向值


/*---------------------------资源-------------------------------------*/
//蛇
typedef struct _snake
{
	int x[LEN];				//坐标—X
	int y[LEN];				//坐标—Y
	int len;				//长度
	int count;				//分数
	int direction;			//方向
}Snake;

//食物
typedef struct _food
{
	int x;
	int y;
	int flg;
}Food;


/************************************************************/
//变量
Snake snake;		//蛇
Food  food;			//食物
//函数
void Form();			//文字提示框
void Init_Snake();		//初始化蛇
void Init_Food();		//初始化食物
void ShowSnake();		//贴图画蛇
void ShowFood();		//贴图画食物
void MoveSnake();		//蛇的移动
void KeyDown();			//控制
void EatFood();			//吃食物
int GameOver();			//游戏结束




void Form()
{
	setlinecolor(BLACK);					//画线颜色
	setfillcolor(WHITE);
	fillrectangle(0, 0, WIDE, HIGH - 1);	//边框

	setfillcolor(RGB(254, 236, 232));		//右侧文字框背景色
	fillrectangle(WIDE - FORM, 0, WIDE, HIGH / 3);	//上提示框,实时显示分数
	fillrectangle(WIDE - FORM, HIGH / 3, WIDE, HIGH);	//下提示框,操作手册
	setbkmode(TRANSPARENT);		//文字透明方式
	settextcolor(LIGHTBLUE);	//文字颜色
	TCHAR  str[3][50];
	_stprintf(str[0], _T("   得分:%4d 分"), snake.count);
	_stprintf(str[1], _T("   速度:%4d 级"), (100 - speed) / 20);
	_stprintf(str[2], _T("   长度:%4d 节"), snake.len);
	for (int i = 0; i < 3; ++i)
	{
		outtextxy(WIDE - FORM + 10, i * 20 + 20, str[i]);	//指定位置输出字符串
	}

	TCHAR  str2[10][50];
	_stprintf(str2[0], _T("提示:一枚果实10分 "));
	_stprintf(str2[1], _T("      撞到墙,或撞到自己"));
	_stprintf(str2[2], _T("      游戏游戏"));
	_stprintf(str2[3], _T("      "));
	_stprintf(str2[4], _T("按键:Esc : 强制退出游戏"));
	_stprintf(str2[5], _T("          1 : 加速 "));
	_stprintf(str2[6], _T("          0 : 减速"));
	_stprintf(str2[7], _T("      空格: 暂停"));
	for (int i = 0; i < 8; i++)
	{
		outtextxy(WIDE - FORM + 10, HIGH / 3 + i * 20 + 20, str2[i]);	//指定位置输出字符串
	}


}

int main()
{

	initgraph(WIDE, HIGH);		//初始化窗口大小
	setbkcolor(WHITE);			//背景颜色

	Init_Snake();				//初始化蛇
	Init_Food();				//初始化食物

	while (true)//强退
	{
		if (food.flg == 0)
		{
			Init_Food();		//初始化食物
		}
		cleardevice();			//刷新窗口

		BeginBatchDraw();		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,防止闪屏
		Form();					//打印表框

		if (_kbhit())
		{
			KeyDown();			//玩家控制蛇移动
		}
		ShowSnake();			//画蛇
		ShowFood();				//画食物
		EndBatchDraw();			// 结束批量绘制,并执行未完成的绘制任务

		EatFood();
		MoveSnake();			//蛇移动

		if (GameOver() == 1)		//游戏结束条件
		{
			break;
		}
		Sleep(speed);			//控制速度
	}

	getchar();
	closegraph();
	return 0;
}
/*--------------------------蛇的功能函数--------------------------*/
//初始化蛇
void Init_Snake()
{
	//初始化前三节蛇
	snake.x[0] = SIZE * 2;
	snake.y[0] = 0;

	snake.x[1] = SIZE;
	snake.y[1] = 0;

	snake.x[2] = 0;
	snake.y[2] = 0;

	snake.len = 3;
	snake.count = 0;
	snake.direction = right;	//默认向右
}
//初始化食物
void Init_Food()
{
	srand((unsigned int)time(NULL));//随机种子
label:
	int x = (WIDE - FORM) / SIZE;	//预留 FORM 像素显示信息
	int y = HIGH / SIZE;
	food.x = rand() % x * SIZE;	// *10 保证食物地址为整数,与蛇头比较
	food.y = rand() % y * SIZE;
	//检查食物是否在蛇身上
	int i = 0;
	while (i < snake.len)
	{
		if (food.x == snake.x[i] && food.y == snake.y[i])
		{
			goto label;
		}
		++i;
	}
	food.flg = 1;
}
//贴图画蛇
void ShowSnake()
{
	for (int i = 0; i < snake.len; ++i)
	{
		setlinecolor(BLACK);	//设置画线颜色
		setfillcolor(GREEN);	//设置填充颜色
		fillrectangle(snake.x[i], snake.y[i], snake.x[i] + SIZE, snake.y[i] + SIZE);
		/*  左上、右下坐标*/
	}

}
//贴图画食物
void ShowFood()
{
	setfillcolor(COLOUR);	//设置填充颜色--彩色食物
	fillrectangle(food.x, food.y, food.x + SIZE, food.y + SIZE);
}
//蛇的移动
void MoveSnake()
{
	//把蛇的后一节坐标移动到前一节的坐标位置
	for (int i = snake.len - 1; i > 0; --i)
	{
		snake.x[i] = snake.x[i - 1];
		snake.y[i] = snake.y[i - 1];
	}
	//单独移动蛇头,根据蛇的方向移动
	switch (snake.direction)
	{
	case right:
		snake.x[0] += SIZE;
		break;
	case left:
		snake.x[0] -= SIZE;
		break;
	case up:
		snake.y[0] -= SIZE;
		break;
	case down:
		snake.y[0] += SIZE;
		break;
	default:
		break;
	}
}



/*getch函数从控制台读取单个字符而不回显,函数不能去读取CTRL+C,当读取一个
	功能键或方向键,函数必须调用两次(这就说明可以用这个函数去监控功能键
	和方向键),第一次调用返回0或0xe0,第二次返回实际的键代码*/
	//控制
void KeyDown()
{
	char tmp = _getch();		//接受_getch()的第一个返回值
	switch (tmp)
	{
	case '1':		// 1 加速
		if (speed > 20)
		{
			speed -= 20;
		}
		return;
		break;
	case '0':		// 0 减速
		if (speed < 200)
		{
			speed += 20;
		}
		return;
		break;
	default:
		break;
	}
	char key = _getch();		//接受键盘键入的值
	switch (key)
	{
	case right:
		if (snake.direction != left)	//不能相反方向移动
			snake.direction = right;
		break;
	case left:
		if (snake.direction != right)
			snake.direction = left;
		break;
	case up:
		if (snake.direction != down)
			snake.direction = up;
		break;
	case down:
		if (snake.direction != up)
			snake.direction = down;
		break;
	case Esc:	//强退
	{
		TCHAR s[] = _T("即将退出游戏,是(Y)/否(N)");
		setfillcolor(LIGHTCYAN);
		fillrectangle(0, 0, WIDE - FORM, HIGH);
		setbkmode(TRANSPARENT);			//文字透明方式
		settextcolor(LIGHTBLUE);		//文字颜色
		outtextxy(WIDE * 3 / 10, HIGH / 2, s);	//指定位置输出字符串
		char ch = getchar();
		if (ch == 'Y' || ch == 'y')	exit(0);

	}
	break;
	case ' ':		//暂停
		while (true)
		{
			if (_kbhit())
			{
				char ch = _getch();
				if (_getch() == ' ')	break;
			}

		}

		break;

	default:
		break;

	}
	fflush(stdin);
}



//吃食物
void EatFood()
{
	if (food.x == snake.x[0] && food.y == snake.y[0])
	{
		++snake.len;
		snake.count += 10;	//一个食物十分
		food.flg = 0;
	}

}



//死亡
int GameOver()
{
	for (int i = 1; i < snake.len; i++)
	{
		//撞自己
		if (snake.x[i] == snake.x[0] && snake.y[i] == snake.y[0])
		{
			TCHAR s[100];
			_stprintf(s, _T("咬到自己了 GameOver!\n您的分数为%d分"), snake.count);

			setfillcolor(WHITE);		//背景填充颜色
			fillrectangle(0, 0, WIDE - FORM, HIGH);
			setbkmode(TRANSPARENT);		//文字透明方式
			settextcolor(LIGHTBLUE);	//文字颜色
			outtextxy(WIDE * 2 / 10, HIGH / 2, s);	//指定位置输出字符串

			return 1;
		}
		//撞墙
		else if (snake.x[i]<0 || snake.x[0]>WIDE - FORM - SIZE ||		//横坐标出界
			snake.y[i]<0 || snake.y[0]>HIGH - SIZE)		//纵坐标出界
		{
			TCHAR s[100];
			_stprintf(s, _T("你撞墙了 GameOver!\n您的分数为%d分"), snake.count);

			setfillcolor(WHITE);		//背景填充颜色
			fillrectangle(0, 0, WIDE - FORM, HIGH);
			setbkmode(TRANSPARENT);		//文字透明方式
			settextcolor(LIGHTBLUE);	//文字颜色
			outtextxy(WIDE * 2 / 10, HIGH / 2, s);	//指定位置输出字符串
			return 1;
		}
		//通关
		else if (snake.len == LEN)		//最长长度
		{
			TCHAR s[100];
			_stprintf(s, _T("恭喜 通关 GameOver!\n您的分数为%d分"), snake.count);

			setfillcolor(WHITE);		//背景填充颜色
			fillrectangle(0, 0, WIDE - FORM, HIGH);
			setbkmode(TRANSPARENT);		//文字透明方式
			settextcolor(LIGHTBLUE);	//文字颜色
			outtextxy(WIDE * 2 / 10, HIGH / 2, s);	//指定位置输出字符串
			return 1;
		}
	}
	return 0;
}

效果如下:

 

posted @ 2019-10-06 17:51  我叫RT  阅读(149)  评论(0编辑  收藏  举报