教你如何用C语言做一个简单的贪吃蛇

小时候大家可能都玩过贪吃蛇,但有没有想过自己做一个出来玩玩看。今天我们就教大家用C语言做一个简单的贪吃蛇游戏。这里没有采用图形界面去做,而是采用win32控制台。
首先,先把做好的游戏初始界面和游戏截图先展示一下。
游戏初始界面如图:
在这里插入图片描述
在这里插入图片描述
游戏截图如图所示:
在这里插入图片描述
第一步
我们要搭建一个游戏的初始界面。这里我们直接采用printf()函数将界面直接打出来,然后用getch()函数来获取键盘输入的字符并将其赋值给ch1再判断ch1是否等于j,如果是则调用system(“cls”)函数清屏,然后就进入设置炸弹数量的界面,然后再用getch()函数获取输入的字符并赋值给ch2,然后再根据ch2的值来使相应标志位置1(这里的标志位是决定后面的炸弹数)。

//初始界面 
int show(){
    
    
	char ch1,ch2;
	printf("                   |----------------------------------------------------------------------------------|\n");    //欢迎界面 
    printf("                   |                                                                                  |\n");
    printf("                   |                                                                                  |\n");
	printf("                   |                            欢迎来到贪吃蛇小游戏                                  |\n");
	printf("                   |游戏规则:1.通过awsd来进行上下左右控制贪吃蛇,按k来增加速度,按L使速度初始化        |\n");
	printf("                   |          2.贪吃蛇吃到炸弹则生命值减1,吃到一个食物则分数加1,吃到自己生命值减1     |\n"); 
	printf("                   |          4.如果往蛇自己的现态反方向运动,则吃到一个身位减一个生命值              |\n");
	printf("                   |          4.字母Q代表炸弹,字母$代表食物                                          |\n"); 
	printf("                   |          5.生命值为0则游戏结束                                                   |\n");
	printf("                   |          6.按'j'来开始游戏                                                       |\n");
    printf("                   |                                                                                  |\n");
    printf("                   |----------------------------------------------------------------------------------|\n");
    ch1=getch();
    if(ch1=='j')
	{
    
    
		system("cls");      //清空函数 
		ks=1;
	}
	printf("               !! 请选择几个炸弹,输入2则出现两个炸弹,输入3则出现三个炸弹,默认为一个炸弹!!           \n"); 
	ch2=getch();
	if(ch2=='2')
	{
    
     
	    system("cls");
		zd1=1;
	}
	if(ch2=='3')
	{
    
     
	    system("cls");  
		zd2=1;
	}
	else  system("cls");            //如果按下其他的键则默认一个炸弹 
	return ks;
} 

第二步,我们创建好了初始界面后,我们就需要做一个简易的游戏地图,因为你玩贪吃蛇嘛,总要给它设置一个范围吧,当然你也可以设置整个窗口都是地图,这个等我们讲完地图如何设置,你自己可以来决定地图的范围。
这里我们先定义它的范围,后期相关物体的位置都是根据它的范围来的。

#define High 20         //设置范围 
#define Width 40

下面这代码是给墙设置一个标志位,因为我们这里使采用标志位来区分开墙,蛇头,蛇身,炸弹,食物。然后我们再用动态扫描的方法把地图都扫描一遍,根据不同的标志位来打印不同的字符,这样就可以实现一个完整的游戏。这里我们先讲解怎么打印墙,也就是贪吃蛇的活动范围。
下面这段代码的含义是将第一行和最后一行以及第一列和最后一列的标志位为-1。

	for(i=0;i<High;i++){
    
    
		map[i][0]=-1;               //每一行的第一个赋值为-1 
		map[i][Width-1]=-1;         //每一行的最后一个赋值为-1 
	}
	for(j=0;j<Width;j++){
    
     
		map[0][j]=-1;              //第一行全为-1 
		map[High-1][j]=-1;         //最后一行全为-1 
	}

然后这里我们通过扫描整个范围的地图,依次根据不同的标志位值来打印不同的物体,当标志位为-1时候就打印出#,我们可以从游戏截图的图片里面看出我们打印的城墙效果。

	for(i=0;i<High;i++){
    
    
		for(j=0;j<Width;j++){
    
    
			if(map[i][j]==-1) printf("#");                        //输出城墙 
			else if(map[i][j]==-2)  printf("$");                 //输出食物 
			else if(map[i][j]==0)   printf(" ");                 //输出空格 
			else if(map[i][j]>1)    printf("*");                 //输出蛇身 
			else if(map[i][j]==1)   printf("@");                //输出蛇头
			else if(map[i][j]<=-3)  printf("Q");               //输出炸弹 
		}
		printf("\n");
	}

第三步,我们来显示贪吃蛇,首先蛇的话我们分蛇头和蛇身。
这里我们将蛇头的标志位置1。然后用@来表示蛇头,下面map[High/2][Width/2-k]=k+1则是定义蛇尾的表示为5。

	//设计蛇头的元素组为1
	map[High/2][Width/2]=1;       //设置蛇头位置的标志位  
	for(k=1;k<5;k++){
    
    
		map[High/2][Width/2-k]=k+1;       //设置蛇尾的标志位 
	}

我们从这里可以看出蛇头的标志位为1,然后大于1的都为蛇身

       else if(map[i][j]>1)    printf("*");                 //输出蛇身 
       else if(map[i][j]==1)   printf("@");                //输出蛇头

然后我们要让蛇动起来的话我们要设置蛇的运动方向和蛇的移动。
这里我们通过扫描使标志位大于0的位自动加一,这样原来设置的蛇头变为蛇身,而新蛇头则为初始方向的下一个坐标。而因为我们墙和其他物体的标志位都为负数,所以不受影响。

for(i=1;i<High-1;i++)                                                     //扫描所有二维码数组,把所有>0的元素+1 *
		for(j=1;j<Width-1;j++)
			if (map[i][j]>0)    map[i][j]++;                              //扫描到坐标上的数,意思是使贪吃蛇运动起来 ,其他物体不变 

然后蛇头动起来,蛇身也要动起来,并且因为如果长度不变,蛇头移动了一个,那蛇尾自然也要移动。而因为 map[i][j]++,所以蛇尾的表示为变为6,所以我们这里通过if(map[i][j]==6+ledth) map[i][j]=0,是老的蛇尾变为0。

if(map[i][j]==6+ledth)  map[i][j]=0;                     //重新开始继续扫描

然后旧蛇头的位置因为+1,标志位变为2,所以变为蛇身。而新蛇头的位置则根据旧蛇头和移动方向来决定。所以我们要将旧蛇头的位置记录下来,在进行相应加减赋值给新蛇头。
具体代码如下:

if(map[i][j]==2)   {
    
    oldhead_x=i;oldhead_y=j;}          //把旧的坐标赋值给oldhead ,记录蛇头位置
	//新蛇头位置与老蛇头的位置关系 
	if(movedirection==4){
    
                                              //这里的x就是y,y就是x 
		newhead_y=oldhead_y+1;                       
		newhead_x=oldhead_x;               //向右 ,将旧蛇头的位置赋值给新蛇头 
	}
    movedirection=4;                     //设置蛇头的初始方向 
    int ledth=0;            //定义增加的长度 
	int oldhead_x,oldhead_y,newhead_x,newhead_y; 
	for(i=1;i<High-1;i++)                                                     //扫描所有二维码数组,把所有>0的元素+1 *
		for(j=1;j<Width-1;j++)
			if (map[i][j]>0)    map[i][j]++;                              //扫描到坐标上的数,意思是使贪吃蛇运动起来 ,其他物体不变 
	//数组内元素值为6时,置0,元素值为2的坐标定义为旧蛇头的位置 
	for(i=1;i<High-1;i++){
    
                                                //i代表的y,j代表的是x 
		for(j=1;j<Width-1;j++){
    
    
			if(map[i][j]==6+ledth)  map[i][j]=0;                     //重新开始继续扫描  
			if(map[i][j]==2)   {
    
    oldhead_x=i;oldhead_y=j;}          //把旧的坐标赋值给oldhead ,记录蛇头位置 
		}
	}
	//新蛇头位置与老蛇头的位置关系 
	if(movedirection==4){
    
                                              //这里的x就是y,y就是x 
		newhead_y=oldhead_y+1;                       
		newhead_x=oldhead_x;               //向右 ,将旧蛇头的位置赋值给新蛇头 
	}
	if(movedirection==1){
    
                     //向上 
		newhead_y=oldhead_y;
		newhead_x=oldhead_x-1;
	}
	if(movedirection==2){
    
                    //向下 
		newhead_y=oldhead_y;
		newhead_x=oldhead_x+1;
	}
	if(movedirection==3){
    
                  //向左 
		newhead_y=oldhead_y-1;
		newhead_x=oldhead_x;
	}

第四步,解决了贪吃蛇问题,我们就来设计食物和炸弹
因为我们是通过动态扫描的方式来显示不同的物体嘛,所以像食物和炸弹都需要各自的坐标,但是我们总不能自己来设置食物产生的点吧,当然是希望它是随机产生在地图的任意位置(但是不能出现在墙上和蛇身上),所以这里我们采用随机函数来产生随机坐标这里的(High-4)+2和(Width-4)+2是为了防止食物出现在墙上。

	//设计食物的元素值为-2
	srand(time(NULL));  //设计随机数种子 
    Food_x=rand()%(High-4)+2;     //生成食物随机的坐标位置  
    Food_y=rand()%(Width-4)+2;
	map[Food_x][Food_y]=-2;      //设置食物的标志位为-2

当然我们也要防止食物出现在蛇身上,所以这里当食物出现的坐标上面的标志位大于等于2,就再重新生成一个食物的随机坐标。

if(map[Food_x][Food_y]>=2)                  //防止食物出现在蛇身上 
	    {
    
    
	       Food_x=rand()%(High-4)+2;           
	       Food_y=rand()%(Width-4)+2;
	       map[Food_x][Food_y]=-2;
		}

炸弹的原理跟食物是一样的,这里就展示代码
先是随机产生炸弹的位置,然后根据开始选的炸弹数执行相应代码

    boom_x=rand()%(High-4)+2;     
    boom_y=rand()%(Width-4)+2;
	map[boom_x][boom_y]=-3;
	if(zd1){
    
                                         //选1则出现两个炸弹 
	boom_x1=rand()%(High-4)+2;     
    boom_y1=rand()%(Width-4)+2;
	map[boom_x1][boom_y1]=-4;}                   //使其赋值标志位为-4 
	if(zd2){
    
                                        //选2则出现三个炸弹 
	boom_x1=rand()%(High-4)+2;                   
    boom_y1=rand()%(Width-4)+2;
	map[boom_x1][boom_y1]=-4;	
	boom_x2=rand()%(High-4)+2;     
    boom_y2=rand()%(Width-4)+2;
	map[boom_x2][boom_y2]=-5; } 

第五步,蛇和食物与炸弹都有了,我们该写吃到食物长度加长和分数加1,吃到炸弹生命值减1。
这里当我们吃到食物后,执行分数加1并且长度加1,然后再重新生成一个食物,其坐标也是随机函数生成的。

	//吃到食物
	if((oldhead_x==Food_x)&&(oldhead_y==Food_y)) 
	{
    
    
	   	score++;
	   	srand(time(NULL));
	   	ledth++;
	   	Food_x=rand()%(High-4)+2;
	    Food_y=rand()%(Width-4)+2;
	    map[Food_x][Food_y]=-2;
	    if(map[Food_x][Food_y]>=2)                      //防止食物出现在蛇身上
	    {
    
    
	       Food_x=rand()%(High-4)+2;
	       Food_y=rand()%(Width-4)+2;
	       map[Food_x][Food_y]=-2;
		} 	
	}

然后就是吃到炸弹后生命值减小并且再重新生成一个炸弹,其炸弹的坐标也是有随机函数生成的。当然两个、三个炸弹的原理都是一样的。这里就举例一个炸弹

	//吃到炸弹
	 if((oldhead_x==boom_x)&&(oldhead_y==boom_y)) 
	{
    
    
	   	--shenming;
	   	srand(time(NULL));
	   	boom_x=rand()%(High-4)+2;
	    boom_y=rand()%(Width-4)+2;
	    map[boom_x][boom_y]=-3; 	
	}

当然还有比如蛇吃到自己身体和撞到墙上的情况,吃到一个身位生命值就减1,当减到0就会游戏结束。而撞到墙上则游戏直接结束。

	//吃到自己的身体
	if(map[newhead_x][newhead_y]>2) 
	{
    
    
	   --shenming;
	}
	//判断失败,撞到墙 
   if(map[newhead_x][newhead_y]==-1){
    
                             
   	printf("game over\n");
   	exit(0);
	}
	//生命值为0则结束游戏 
	if(shenming==0)
	{
    
     
	  printf("game over\n");
	} 

第六步,就是写相关操控,我们要用上下左右来去控制蛇的运动方向以及改变蛇的运动速度和暂停以及退出。

 //键盘输入判断
void keyboard()
 {
    
    
 	    char ch;
		if(kbhit())
	    {
    
    
		ch=getch();                   
		if(ch=='a') movedirection=3;               //向左 
		if(ch=='d') movedirection=4;               //向右 
		if(ch=='w') movedirection=1;               //向上 
		if(ch=='s') movedirection=2;               //向下 
		if(ch=='k') {
    
    sudo=sudo+20;}                //速度加快 
		if(ch=='l') sudo=0;                       //速递变为初始值 
		if(ch=='\033') exit(0);                   //按下esc可以退出 
		if(ch==32)  system("pause");             //按下空格键可以暂停 
		}
		if(sudo==240) 
		{
    
    
			sudo=0;
		}
}

最后我们写一下游戏规则,这里打印在游戏地图的下面

	printf("|游戏规则:1.通过awsd来进行上下左右控制贪吃蛇,按k来增加速度,按L使速度初始化       |\n");          //游戏规则 
    printf("|          2.按空格键可以暂停游戏,按esc键可以退出游戏                             |\n");	
	printf("|          3.贪吃蛇吃到炸弹则生命值减1,吃到一个食物则分数加1,吃到自己生命值减1     |\n"); 
	printf("|          4.如果往蛇自己的现态反方向运动,则吃到一个身位减一个生命值              |\n"); 
	printf("|          5.字母Q代表炸弹,字母$代表食物                                          |\n"); 
	printf("|          6.生命值为0则游戏结束                                                   |\n");
	printf("score:%d\n",score);
	printf("生命值:%d\n",shenming); 

好了写到这里,简单版贪吃蛇已经讲解完,感兴趣的朋友们可以自己做一下。
这里分享源代码给大家
代码链接:https://download.csdn.net/download/OMGMac/19354774

本人水平有限,上述信息仅供参考,如有错误和不妥之处,请多多指教。
另外创作不易,请勿抄袭,如果有帮助到大家的话希望大家可以点个赞,谢谢~

猜你喜欢

转载自blog.csdn.net/OMGMac/article/details/117454558