贪吃蛇代码解析

自己学习敲代码练习的代码

#include <easyx.h>
#include<conio.h>
#include<stdlib.h>
#include<time.h>
#include <graphics.h>
//打开静态音乐库
#pragma comment(lib,"winmm.lib")
void start();//声明函数
#define SQUARES 15//表示小方块的边长   为什么要把窗口变成小方块  因为要用不同颜色的小方块表示墙和蛇
#define WIDTH 30//表示窗口宽度的格子数量
#define HIGHT 40//表示窗口高度的格子数量
#define MAXNUMLIN 1200//表示贪吃蛇方块最大数量
//1.打开窗口
//2.定义变量:保存图片
IMAGE img;
//构造贪吃蛇方块信息类型
typedef struct Position
{
	int x;//方块x坐标
	int y;//方块y坐标
}SANKE,FOOD;
enum diretion { up = 'w', down = 's', left = 'a', right = 'd' };//贪吃蛇可能de方向
enum diretion dir;//定义贪吃蛇的方向变量

//定义结构体数组:贪吃蛇方块整体 
SANKE snake[MAXNUMLIN];//能够保存方块信息的最大数量
int SnakeNum;//贪吃蛇当前的方块数量
FOOD food;//定义食物变量
int FoddNum;//当前的食物数量
int score;//定义得分
int isGameOver;//游戏是否结束 0 继续 1 结束

//贪吃蛇的移动
void SnakeMove()
{
	//从尾部开始得到上一个方块信息(不包括头部方块)
	for (int i = 0; SnakeNum > 0; i--)
	{
		snake[i] = snake[i - 1];
		//移动贪吃蛇头部方块
		switch (dir)
		{
		case up:
			snake[0].y = snake[0].y - 1;//当向上移动时,头部下标自身减一也就是(x,y)的x不变y减一
			break;
		case down:
			snake[0].y = snake[0].y + 1;//以下一样
			break;
		case left:
			snake[0].x = snake[0].x - 1;//可简写为 snake[0].x-=1
			break;
		case right:
			snake[0].x = snake[0].x + 1;
			break;		
		}
		
	}
}

//吃食物
void SnakeEeatFood()
{
	if (snake[0].x == food.x && snake[0].y != food.y)//满足贪吃头部
	{
		FoddNum = 0;//食物没有
		snake[SnakeNum] = food;
		SnakeNum++;//贪吃蛇方块+1
		score++;//分数+1
	}

}

//生成食物
void CreatFood()
{
	//没有食物再生成
	if (FoddNum == 0)
	{
		food.x = rand() % (WIDTH - 2) + 1;//不是很懂  1~HIGHT_2
		food.y = rand() % (HIGHT - 2) + 1;//不要两竖,食物生成范围 1~HIGHT_2 
		//检测食物是否 生成在贪吃蛇身上,需要重新生成
		for (int i = 0; i < SnakeNum; i++)
		{
			if (snake[i].x == food.x && snake[i].y == food.y)
			{
				//重新生成食物
				CreatFood();
			}
		}
		//食物生成成功
		FoddNum = 1;
	}

}


//方向改变
void Chagedir()
{
	//_kbhit函数,判断是否敲击键盘,是返回真值,否返回假值 函数在 <conio.h>头文件中
	if(_kbhit())
		switch (_getch())//_getch()等待从键盘输入一个字符
		{
		case up:
			if(dir!=down)//蛇头不能立马变成蛇尾不符合常识
			{
				dir = up;//当方向不为下时,方向才能为上   
			}
			break;
		case down: 
		    if(dir!=up)
		    {		
			    dir = down;//当方向不为上时,方向才能为下
		    }
			break;
		case left:
			if (dir != right)
			{
				dir = left;//当方向不为右时,方向才能为左
			}
			break;
		case right:
			if (dir != left)
			{
				dir = right;当方向不为左时,方向才能为右
			}
			break;
		}
	    
}


//初始化游戏数据
void InitGameData()
{

	SnakeNum = 2;//初始化当前贪吃蛇方块数量
	for (int i = 0; i < SnakeNum; i++)//初始化方块信息
	{
		snake[i].x = 2;
		snake[i].y = 4 - i;
	}
	//初始化游戏方向
	dir = down;
	//初始化食物
	FoddNum=0;
	//生成随机种子
	srand((unsigned)time(NULL));//因为系统时间函数是负数值,不符合坐标的值所以用无符号标识符
	//初始化得分
	score = 0;
	//初始化游戏状态
	isGameOver = 0;
	//打开音乐
	mciSendString("open JustBlue.mp3",0,0,0);
	//播放音乐
	mciSendString("play JustBlue.mp3", 0, 0, 0);
}

//贴图函数
static void RrawMap()
{
	//批量绘制函数
	BeginBatchDraw();
	putimage(0, 0, &img);//背景
	//贴贪吃蛇
	setcolor(GREEN);//设置当前图形填充颜色为
	for (int i = 0; i < SnakeNum; i++)
	{   //画矩形或小方块
		fillrectangle(snake[i].x * SQUARES, snake[i].y * SQUARES, (snake[i].x + 1) * SQUARES, (snake[i].y + 1) * SQUARES);
	}	
	//贴食物
	//画矩形
	setcolor(MAGENTA);
	fillrectangle(food.x * SQUARES, food.y * SQUARES, (food.x + 1) * SQUARES, (food.y + 1) * SQUARES);
	//画围墙
	setcolor(BROWN);//棕色
	for (int i = 0; i < WIDTH; i++)
	{   //画横		
		fillrectangle(i * SQUARES, 0 * SQUARES, 1 * SQUARES, (i + 1) * SQUARES);//画第一横
		fillrectangle(i * SQUARES, (HIGHT-1) * SQUARES, i+1 * SQUARES, HIGHT * SQUARES);//画第二横
	}
	for (int i = 0; i < HIGHT; i++)
	{
		//画竖
		fillrectangle(0 * SQUARES, i * SQUARES, 1 * SQUARES, (i + 1) * SQUARES);//画第一竖
		fillrectangle((WIDTH - 1) * SQUARES, i * SQUARES, WIDTH * SQUARES, i+1 * SQUARES);//画第二竖
	}
	EndBatchDraw(); //结束批量绘制函数
}

//判断游戏是否碰撞     0 没有结束  1 结束游戏  游戏是否结束
void GarmerOver()
{
	//检测是否碰墙
	if (snake[0].x <= 0 || snake[0].x >= WIDTH - 1 || snake[0].y <=0 || snake[0].y >= HIGHT - 1 )
	{
		isGameOver = 1;//游戏结束		
	}
	//检测是否碰到自身 (不包括头部)
	for (int i = 0; i < SnakeNum; i++)
	{
		if (snake[0].x == snake[i].x && snake[0].y == snake[i].y)
		{
			isGameOver = 1;//游戏结束
			break;
		}
	}
}
void start() //开始函数   函数所有功能从这里开始
{
	initgraph(SQUARES*WIDTH, SQUARES*HIGHT);//小方块的边长*宽度的格子数量=整体的窗口宽度 第二个类似
	while(1);//利用无限循环卡住窗口	
	loadimage(&img, "蛇背景.jpg", SQUARES * WIDTH, SQUARES * HIGHT);//背景图片加载函数
	InitGameData(); //初始化游戏数据	
	while (1)       //可以不断地贴图和移动
	{
		SnakeEeatFood();//判断贪吃蛇是否吃到食物
		SnakeMove();    //移动函数
		RrawMap();      //贴图函数
		CreatFood();    //生成食物	
		GarmerOver();    //马上进行碰撞检测   不能吃到食物马上进行碰撞检测会让 数据重复
		Sleep(100);     //睡眠函数,由于计算机运算速度过快,100毫秒,1秒=1000毫秒;
		if (isGameOver == 1)
		{ 
			//关闭音乐
			mciSendString("close JustBlue.mp3", 0, 0, 0);
			char str[128];
			wsprintf(str,"成绩为%d/n 游戏失败",score);//显示的内容
			int temp = MessageBox(GetHWnd(),str,"提示", MB_YESNO);
			if (temp == IDYES)//选择“是”
			{
				InitGameData();//重新初始化游戏数据
			}
			else
			{
				exit(1);//退出程序
			}
		}
		closegraph();
	}
}

int main()
{
	start();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Фоня

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值