贪吃蛇项目(C语言)

贪吃蛇

1.开发环境

(1)PC
(2)Microsoft Visual Studio2012
(3)Microsoft Word2016

2.设计思路

定义接口函数,分别代表蛇的各项功能

void Init_Snake();//初始化蛇
void Draw_Snake();//画蛇
void Move_Snake();//蛇的移动
void Key_Down();//按键设置
void Init_Food();//初始化食物
void DrawFood();//画食物
void EatFood();//吃食物
int DieSnake();//蛇挂掉的条件
void ShowGrade();//输出分数
void Key_Wait();//暂停
分别设计出每一个接口函数的内函数,再通过main函数结合起来,利用Easyx给设计好的贪吃蛇游戏加上图形化界面,丰富游戏者的游戏体验。

3.流程图与各端口函数间关系图
图3.1端口函数间关系图

图3.2

4.主要算法设计

(1)图片加载函数
//1,声明图片变量
IMAGE background1;//蛇身贴图
IMAGE background2;//蛇头贴图
IMAGE background3;//食物贴图
IMAGE background4;//右部分背景贴图
IMAGE background5;//墙贴图

//2,加载资源到变量:loadimage加载

void fun1()
{
loadimage(&background1 ,_T(“身体.bmp”));
}

void fun2()
{
loadimage(&background2 ,_T(“蛇头.bmp”));
}
void fun3()
{
loadimage(&background3 ,_T(“食物2.bmp”));
}
void fun4()
{
loadimage(&background4 ,_T(“background.bmp”));
}

void fun5()
{
loadimage(&background5 ,_T(“墙.bmp”));
}

(2)结构体定义与设计

typedef struct xy //xy别名->mypoint
{
int x;//横坐标
int y;//纵坐标
}mypoint;
//蛇的定义
struct Snake
{
int n;//蛇的节数
mypoint xy[300];//蛇的最大长度为两百节
char position;//定义蛇的方向
char speed;//速度
}snake;
//食物
struct Food
{
int existence;//判断食物是否存在
mypoint food_xy;// food的xy坐标
int food_grade;//吃掉食物的得分
}food;
//墙
struct Wall
{
mypoint Wall_xy;// Wall的xy坐标
}wall;

(3)枚举类型定义与设计

enum move_position{up = 80,down = 72,left = 75,right = 77,F1 = 112,F2 = 113};

5.运行界面示例

图3.3

结束游戏
1.撞墙

玩家操作游戏时,贪吃蛇与图形化界面边界接触(蛇头与图形化界面边界墙重合),则游戏结束。系统会弹框提示游戏结束,计分系统停止运行。玩家可选择退出游戏或者再来一局。重新开始新游戏计分系统清零,并重新开始计分。

图4.1

2.撞自己

玩家操作游戏时,贪吃蛇与图形化界面自身接触,则游戏结束。系统会弹框提示游戏结束并鼓励玩家继续努力,计分系统停止运行。玩家可选择退出游戏或者再来一局。重新开始新游戏计分系统清零,并重新开始计分。

图4.2

3.通关

当玩家比较厉害时,当分数达到一定高度时,系统会自动“杀死”蛇。因为此时已经到达了游戏设定的最高分,言简意赅就是恭喜玩家已经成功通关,鉴于本人能力有限,在这就不做展示,还请玩家自行探究。
本游戏结构非常简单,容易上手,玩家只需要注意一下图形化界面右边的小提示就会轻而易举实现操作,祝各位玩家取得好成绩!

图4.3

源码

/***********************************************************

Create date:2019.9.13
Designer by:MaL
Compiling environment:Microsoft Visual Studio2012

************************************************************/
#define  _CRT_SECURE_NO_WARNINGS  
#define _CRT_NON_CONFORMING_SWPRINTFS

#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<conio.h>
#include<time.h>//随机函数种子#undef  UNICODE

#undef  _UNICODE


//1,声明图片变量
IMAGE background1;//蛇身贴图
IMAGE background2;//蛇头贴图
IMAGE background3;//食物贴图
IMAGE background4;//右部分背景贴图
IMAGE background5;//墙贴图
//2,加载资源到变量:loadimage加载
void fun1()
{
	loadimage(&background1 ,_T("身体.bmp"));
}

void fun2()
{
	loadimage(&background2 ,_T("蛇头.bmp"));
}
void fun3()
{
	loadimage(&background3 ,_T("食物2.bmp"));
}

void fun4()
{
	loadimage(&background4 ,_T("background.bmp"));
}

void fun5()
{
	loadimage(&background5 ,_T("墙.bmp"));
}


//坐标
typedef struct xy     //xy别名->mypoint
{
	int x;//横坐标
	int y;//纵坐标
}mypoint;
//蛇的定义
struct Snake
{
	int n;//蛇的节数
	mypoint  xy[300];//蛇的最大长度为两百节
	char position;//定义蛇的方向
	char speed;//速度
}snake;
//食物
struct Food
{
	int existence;//判断食物是否存在
	mypoint  food_xy;// food的xy坐标
	int food_grade;//吃掉食物的得分
}food;
//墙
struct Wall
{
	mypoint  Wall_xy;// fWall的xy坐标
}wall;
//枚举出方向
enum move_position{up = 80,down = 72,left = 75,right = 77,F1 = 112,F2 = 113};

/******************************************************************************************/
//接口函数定义
void Init_Snake();//初始化蛇
void Draw_Snake();//画蛇
void Move_Snake();//蛇的移动
void Key_Down();//按键设置
void Init_Food();//初始化食物
void DrawFood();//画食物
void EatFood();//吃食物
int DieSnake();//蛇挂掉的条件
void ShowGrade();//输出分数
void Key_Wait();//暂停
int Speed_Snake();//蛇加减速的实现
/******************************************************************************************/

//初始化蛇
void Init_Snake()
{
	snake.xy [2].x  = 0;
	snake.xy [2].y  = 50;//蛇的第一节  默认蛇开始有三节

	snake.xy [1].x  =50;
	snake.xy [1].y  = 50;//第二节

	snake.xy [0].x  = 100;
	snake.xy [0].y  = 50;//第三节

	snake.n = 3;//蛇初始长度为3
	snake.position  = right;//初始方向为右
	food.existence  =0;
	food.food_grade = 0;
}

//画蛇
void Draw_Snake()
{
	for(int i = 0;i <snake.n ;++i)
	{
		putimage(snake.xy [0].x ,snake.xy [0].y, &background2);
		putimage(snake.xy [i].x ,snake.xy [i].y, &background1);
	}
}

void Move_Snake ()
{
	//除第一节外,后边每一节都是前一节的坐标
	for(int i= snake .n - 1;i>0;i--)
	{
		snake.xy [i].x = snake.xy [i-1].x ;
		snake.xy [i].y = snake.xy [i-1].y ;
	}
	//第一节处理
	switch(snake.position)
	{
	case right:
		snake .xy [0].x += 50;
		break;
	case left:
		snake .xy [0].x -= 50;
		break;
	case up:
		snake .xy [0].y += 50;
		break;
	case down:
		snake .xy [0].y -= 50;
		break;
	default:
		break;
	}
}

void Init_Food()
{
	food.food_xy .x =rand() % 13*50;
	food.food_xy .y = rand() % 13*50;
	food.existence = 1;//判断食物存在

	//如果食物坐标和蛇身坐标重合
	for(int i = 0;i>snake.n ;++i)
	{
		if(food.food_xy .x == snake.xy [i].x  && food.food_xy .y == snake.xy [i].y )
		{
			food.food_xy .x =rand() % 13*50;//重新生成食物坐标
			food.food_xy .y = rand() % 13*50;
		}
	}
	//如果食物坐标和墙身坐标重合
		if(food.food_xy .x <50  || food.food_xy .y <50)
		{
			Init_Food();
		}
	

	

	food.existence  =1;
}
void Draw_wall()
{

	for(int i =0;i<=750;i+=50)//左墙
	{
		putimage(0,i,&background5);
	}
		
		for(int i =0;i<=750;i+=50)//上墙
	{
		putimage(i,0,&background5);
	}
		
			for(int i =0;i<=750;i+=50)//右墙
	{
		putimage(750,i,&background5);
	}
		
		for(int i =0;i<=750;i+=50)//下墙
	{
		putimage(i,750,&background5);
	}
		
}

void DrawFood()
{
	putimage(food.food_xy .x ,food.food_xy .y, &background3);
}

void Key_Down ()
{
	char userKey =100;
	userKey = _getch();
	switch(userKey )
	{
	case right:
		if(snake .position != left)
			snake .position = right;
		break;
	case left:
		if(snake .position != right)
			snake .position = left;
		break;
	case up:
		if(snake .position != down)
			snake .position = up;
		break;
	case down:
		if(snake .position != up)
			snake .position = down;
		break;
	case F1:
		if(snake.speed == F1)
		{
			userKey --;
		}
		break;
	case F2:
		if(snake.speed == F2)
		{
			userKey ++;
		}
		break;
	default:
		break;
	}
}

void EatFood ()
{
	/*
	   1.蛇变长
	   2.重新生成食物
	   3.分数增加
	*/
	if(food.food_xy .x == snake.xy [0].x  && food.food_xy .y == snake.xy [0].y )
	{
		snake .n ++;
		food.food_grade += 20;
		food.existence  = 0;
	}
}

int DieSnake()
{
	//撞墙
	if(snake.xy [0].x < 50 || snake.xy [0] .x > 700  || snake.xy [0].y <50 || snake.xy [0] .y  > 700)
	{
		TCHAR s[] = _T("你撞墙了,继续努力哦!");
		setbkmode(TRANSPARENT);
		
		outtextxy(920, 280, s);
		return 1;//游戏结束
	}
	//撞自己
	for(int i = 1;i<snake.n ;++i)
	{
		if(snake.xy [0] .x == snake .xy [i].x  && snake .xy [0].y == snake .xy [i].y )
		{
			TCHAR s[] = _T("你撞自己了,下次加油哦!");
			setbkmode(TRANSPARENT);
			outtextxy(920, 280, s);
			return 1;
		}
	}
	return 0;
	
}

void Tips()
{
	TCHAR s[] = _T("Little Tips:");
	setbkmode(TRANSPARENT);
	outtextxy(950, 400, s);
	TCHAR f[] = _T("1.按↑,↓,←, → 控制蛇头移动方向;");
	setbkmode(TRANSPARENT);
	outtextxy(880, 440, f);
	TCHAR x[] = _T("2.不能撞墙,不能撞自己,否则游戏结束;");
	setbkmode(TRANSPARENT);
	outtextxy(880, 480, x);
	TCHAR g[] = _T("3.单击空格键暂停暂停游戏;");
	setbkmode(TRANSPARENT);
	outtextxy(880, 520, g);
	TCHAR h[] = _T("4.双击空格键继续游戏;");
	setbkmode(TRANSPARENT);
	outtextxy(880, 560, h);
	TCHAR t[] = _T("祝您游戏愉快!");
	setbkmode(TRANSPARENT);
	outtextxy(1000, 650, t);
	TCHAR m[] = _T("Designed by ML");
	setbkmode(TRANSPARENT);
	outtextxy(1050, 750, m);
}

void ShowGrade ()
{ 

	TCHAR s[] = _T("分数:");
	setbkmode(TRANSPARENT);
	outtextxy(950, 200, s);
//	setbkmode(TRANSPARENT);
	settextcolor(BLACK);
	TCHAR d[5];
	_stprintf(d, _T("%d"), food.food_grade);       
	outtextxy(1000, 200, d);
	setbkmode(TRANSPARENT);
	settextcolor(BLACK);
}
//暂停的实现
void Key_Wait()
{
	if(_getch() == 32)//利用死循环控制
	{
		while(_getch () != 32);
	}
}

蛇加减速的实现
//int Speed_Snake()
//{
//	char userKey =100;
//	userKey = _getch();
//	if(_getch() ==112)
//	{
//		while(_getch() ==112)
//		{
//			userKey--;
//		};
//	}
//	if(_getch() ==113)
//	{
//		while(_getch() ==113)
//		{
//			userKey++;
//		};
//	}
//	return userKey;
//}
int main()
{
	initgraph (800, 800);
	putimage(800 ,500, &background4);//右半部分贴图
	 fun1();
	 fun3();
	 fun2();
	 fun4();
	 fun5();
	closegraph ();
	srand((unsigned int)time(NULL));//随机函数种子
	HWND r =initgraph (1200 , 800 );
	setbkcolor (WHITE);//窗口颜色
	cleardevice ();
	Init_Snake();
	while(1)
	{
		cleardevice ();//刷新函数
		solidrectangle(800,0,1200,800);
        putimage(800 ,0, &background4);
		Draw_wall();
		if(food.existence  == 0)
		{
			Init_Food ();
		}
		BeginBatchDraw();//防闪屏批量绘图
		DrawFood ();
		Draw_Snake();
		Tips();
		ShowGrade();
		EatFood();
		Move_Snake();
		if(DieSnake ())
		{
			break; 
		}
		FlushBatchDraw();//防闪屏批量绘图
		Sleep(300);
		while(_kbhit())
		{
			Key_Wait();
			Key_Down ();
	
		}
	}
	EndBatchDraw();//防闪屏批量绘图
	getchar();//防止闪屏
	closegraph ();
	return 0;
}
1.图形化界面百度百科:
https://www.baidu.com/s?wd=C语言图形化界面&ie=utf-8&tn=request_7_pg&ssl_s=1&ssl_c=ssl6_1669f5e0792
2.贪吃蛇图片素材库
https://www.baidu.com/s?wd=%E8%B4%AA%E5%90%83%E8%9B%87%E7%B4%A0%E6%9D%90&ie=utf-8&tn=request_7_pg&ssl_s=1&ssl_c=ssl6_1669f5e0792
3.Easyx库
https://www.baidu.com/s?wd=Easyx&ie=utf-8&tn=request_7_pg&ssl_s=1&ssl_c=ssl6_1669f5e0792


posted @ 2019-09-13 16:16  simonlma  阅读(70)  评论(0)    收藏  举报