我院新闻
C语言项目实战——贪吃蛇游戏,附源码
发布时间:2024-02-11

目录

         一、在Visual Studio2010上创建C项目

二、对于新建项目的测试

三、贪吃蛇游戏

       1.游戏准备

        2.游戏界面大小及背景颜色确定

        3. 画出食物

         4.画蛇且使蛇移动

         5.通过按键控制蛇的移动

         6.蛇吃食物的问题

         7.分数显示的问题

        8.蛇死亡的问题

        9.添加音乐问题


一、在Visual Studio2010上创建C项目

        1. 打开VS2010,选择新建项目。

        2.选择“win32控制台应用程序”,在窗口下面的名称填写好名称。

        3.点击“下一步”继续,在附加选项中选择“空项目”,然后点击“完成”。

        4.在软件界面左边的"解决方案资源管理器"中的“源文件”上面右击鼠标一次选择“添加”、“新建项”。

        5.在新窗口中选择“C++文件(.cpp)”,在窗口下方的名称中填写好名称。注意不要忘记在填写好的名称后面写上 .c,最后选择“添加”

二、对于新建项目的测试

        在创建好一个新项目之后,要测试新建项目是否可以,我们便可以编写一个比较简单的C语言程序进行测试,例如: 

在进行程序执行后,便可以得到结果C=24了,说明新建项目成功。 注意,操作选择是执行文件,而不是启动调试,否则得不到输出结果。

三、贪吃蛇游戏

       1.游戏准备

        在写这个游戏之前,需要进行一些基本的准备,比如我们这个游戏的整体框架是怎样的,需要多大的游戏界面,蛇的身体长度,食物表示,死亡情况,游戏音乐等等是怎么规划的,接下来我们一步步来设计。

        2.游戏界面大小及背景颜色确定

        我们这里就定义一个X,Y坐标分别为(800,600)的一个游戏界面,并且还要设置好游戏界面的背景颜色。

        initgraph(800,600);  这个函数的功能是初始化图形环境创建一个尺寸为 800x600 的绘图环境。

        setbkcolor(RGB(110,120,119));    //设置背景颜色,这里用的是RGB三元色的参数来选择颜色, 调整相关数字,便可以得到深浅不一的各种颜色

在执行以上两个函数之后,需要进行清屏操作。

        cleardevice();                   //清屏,该函数的作用是用背景色清空屏幕,否则得不到我们设置的颜色。

        

在执行程序之后,就可以得到我们设置的图形界面了。

 

        3. 画出食物

        画一个矩形的食物,食物的颜色随机出现,并且食物的位置也是随机出现

        至于要让食物随机出现,就要用到随机函数rand(),我们以时间进行播种,则可以得到食物的随机出现。

        要完成这样的想法,首先要建立一个存储X,Y坐标的结构体,如下:

然后再建立一个结构体,存储食物坐标,食物是否存在,以及食物的分数: 

为了让食物出现,首先要给食物一个存在的坐标,并且是食物存在时的状态标位1,

接下来就可以画出食物了,画一个填充矩形就可。填充矩形颜色随机出现,运用随机函数。

         4.画蛇且使蛇移动

        在画好食物之后,便可以进行画蛇了,同样,和画食物类似,我们需要建立一个结构体来存储蛇的坐标,蛇的长度。这里我们需要注意的是,蛇不同于食物,不能仅用一个坐标来表示,蛇初始时最好是由3个矩形构成,并且随着蛇把食物吃掉,蛇的长度会增加,所以表示蛇的坐标会更多,因此,就需要一个数组来表示蛇的坐标。

        所以,首先就初始化蛇,定义好蛇最初存在的位置,这里我们考虑蛇在吃到食物之后,数组坐标值便增加一个,所以以数组0作为蛇头,初始化程序如下:

 在对蛇初始化完成之后,便可以进行画蛇的操作了,程序如下:

 在画完蛇之后运行程序的效果如下:

         现在已经有蛇存在了,我们便需要蛇能够动起来,就需要设计到蛇的方向问题,所以在存储蛇的信息的结构体里面,要加入方向的信息:

 要让我们画好的三节蛇动起来,就可以运用坐标转换的原理使蛇动起来,由于坐标转换运用的是for循环来实现,所以并没有处理蛇头,所以蛇头需要单独处理。

        对于蛇头的处理,是依据蛇头的方向,来实现蛇头的移动,具体实现代码如下:

         5.通过按键控制蛇的移动

通过按键控制蛇的移动,可以用最常用的W,A,S,D来控制蛇的移动,所以就要用到一个_getch()函数,_getch() 函数读入一个字符时 不用 enter 建代码会继续跑,所以控制蛇的移动时,代码如下:

 

         6.蛇吃食物的问题

        蛇吃食物就是简化为一个坐标相等的问题,当食物的坐标等于蛇头的坐标时,就相当于蛇吃掉了食物,所以我们需要更新的就是蛇的长度,食物的存在状态以及分数。当我们更新蛇的长度之后,主函数循环里就会相应画出蛇的长度。并且我们需要更新一下食物状态,所以需要不断检测食物状态来确定是否更新食物。

         7.分数显示的问题

        这里分数显示我们使用outtextxy()函数来在制定的位置显示我们的文本,并且可以设置字体样式和颜色,输出我们想要输出的东西。

        需要注意的是,在使用settextstyle()函数和outtextxy()函数时,需要将VS版本里的项目属性里面的字符集修改为使用多字符集,否则VS会报错。 

        8.蛇死亡的问题

        蛇死亡问题,是相当于蛇头的坐标超过墙的坐标就相当于死亡,并且还有一种蛇咬到自己的一个情况,也属于蛇死亡,蛇咬到自己的一个情况是蛇头的坐标等于蛇身任何一处的坐标则相当于死亡。注意在这里的一个逻辑关系是且的关系而不是或的关系,只有蛇头的X和Y坐标都等于蛇身的X,Y坐标时,才能判定蛇已经死亡。如果蛇死亡,则主函数里可以退出循环。

        9.添加音乐问题

        在将游戏的基本框架设置好之后,之后的一步便是添加音乐了,我们先下载好音乐文件,随后将音乐文件放在我们的项目文件中,注意,一定要把音乐文件放进去,否则播放不了音乐。并且,使用mciSendString函数时,需要包含

#include        //多媒体头文件

 #pragma comment(lib,"winmm.lib")    //加载静态库

这两个文件。否则会报错,

在以上准备工作做好之后,便可以加进去了。

这样,最基本的贪吃蛇游戏便大功告成了,如果有需要改进的地方,大家可以多多交流,接下来,我把我的源码附上。亲测可用。

#include 
#include 
#include 
#include 
#include 
#include 
#pragma comment(lib,"winmm.lib")	//加载静态库

/*定义一个结构体来存储我们的坐标*/
typedef struct point          
{
	int x,y;       
}MYPOINT;

/*定义一个结构体来存储我们蛇的坐标,蛇身的长度*/
struct 
{
	MYPOINT snakexy[100];   //定义一个数组来存储蛇的坐标
	int snakenum;
	int position;
}snake;

/*定义一个结构体来存储我们的食物坐标*/
struct 
{
  MYPOINT fdxy;  //食物坐标
  int grade;   //食物分数
  int flag;    //标记食物是否出现
}food;

//定义一个枚举类型,来表示蛇的方向
enum position{up,down,right,left};

/*初始化蛇*/
void initSnake()
{
	//初始化时先列出蛇的前三节坐标位置
	snake.snakexy[2].x=0;
	snake.snakexy[2].y=0;    //蛇尾的坐标

	snake.snakexy[1].x=10;
	snake.snakexy[1].y=0;

	snake.snakexy[0].x=20;
	snake.snakexy[0].y=0;      //蛇头的坐标

	snake.snakenum=3;         //此时蛇的长度为3

	snake.position=right;
}

/*画蛇*/
void drawSnake()
{
	for(int i=0;i0;i--)
	{
		snake.snakexy[i].x=snake.snakexy[i-1].x;
		snake.snakexy[i].y=snake.snakexy[i-1].y;
	}
	//上述坐标转换没有顾忌到蛇头
	//蛇头的移动
	switch(snake.position)
	{
	case up:
		snake.snakexy[0].y=snake.snakexy[0].y-10;
		break;
	case down:
		snake.snakexy[0].y=snake.snakexy[0].y+10;
		break;
	case right:
		snake.snakexy[0].x=snake.snakexy[0].x+10;
		break;
	case left:
		snake.snakexy[0].x=snake.snakexy[0].x-10;
		break;
	}
}

/*通过按键控制蛇的移动*/
void KeyControl()
{
	char userkey=_getch();
    switch(userkey)
	{
	case 'W':
	case 'w':
		if(snake.position!=down)
		{
			snake.position=up;
		}
		break;
	case 'A':
	case 'a':
		if(snake.position!=right)
		{
			snake.position=left;
		}
		break;
	case 'S':
	case 's':
		if(snake.position!=up)
		{
			snake.position=down;
		}
		break;
	case 'D':
	case 'd':
		if(snake.position!=left)
		{
			snake.position=right;
		}
		break;
	}
}

/*在画食物之前要初始化食物,先让食物出现*/
//食物具体出现在哪里,就是食物坐标的问题,我们选择让它随机出现
void initfood()
{
	food.fdxy.x = rand()%80*10; //让食物随机出现
	food.fdxy.y = rand()%60*10;
	food.flag =1;         //1表示食物存在

	//需要注意的是,食物不能出现在蛇身上
	for(int i=0;i800 ||snake.snakexy[0].x<0 ||snake.snakexy[0].y>600 || snake.snakexy[0].y<0)
	{
		mciSendString("close 1.mp3",0,0,0);
		MessageBox(hwnd,"撞墙了,游戏结束","gameover",MB_OK);
		return 1;
	}
	//蛇吃自己游戏结束
	for(int i=1;i

[返回上级]