【C语言】贪吃蛇游戏的实现(三)

游戏的静态初始化已经完成,下面要做的就是动态逻辑的编写,在游戏开始后,我们需要实现的有几个功能:在不按下按键(上下左右)时,蛇朝着默认方向前进,在按下方向键时,蛇改变前进方向,如果蛇撞到墙或者咬到自己,则游戏结束。那么问题来了,如何用代码实现键盘控制方向呢,这里用到的是short GetAsyncKeyState(int nVirtKey);方法,该方法传入的参数nVirtKey为虚拟键盘值常量,这样一来,通过传入的nVirtKey参数我们就可以控制蛇的方向了,同理,加速减速以及暂停等功能也可以实现。

/*
	控制键盘按键
*/
void keyboardControl()
{
	status=R;       //初始蛇向右移动
    while(1)
    {
		scoreandtips();
        if(GetAsyncKeyState(VK_UP) && status!=D)            //GetAsyncKeyState函数用来判断函数调用时指定虚拟键的状态
        {
            status=U;           //如果蛇不是向下前进的时候,按上键,执行向上前进操作
        }
        else if(GetAsyncKeyState(VK_DOWN) && status!=U)     //如果蛇不是向上前进的时候,按下键,执行向下前进操作
        {
            status=D;
        }
        else if(GetAsyncKeyState(VK_LEFT)&& status!=R)      //如果蛇不是向右前进的时候,按左键,执行向左前进
        {
            status=L;
        }
        else if(GetAsyncKeyState(VK_RIGHT)&& status!=L)     //如果蛇不是向左前进的时候,按右键,执行向右前进
        {
            status=R;
        }
        if(GetAsyncKeyState(VK_SPACE))		//按暂停键,执行pause暂停函数
        {
            while(1)
			{
				Sleep(300); //sleep()函数,头文件#include   令进程暂停,直到达到里面设定的参数的时间
				if(GetAsyncKeyState(VK_SPACE))      //按空格键暂停
				{
					break;
				}
				
			}       
        }
        else if(GetAsyncKeyState(VK_ESCAPE))
        {
            endgamestatus=3;    //按esc键,直接到结束界面
            break;
        }
        else if(GetAsyncKeyState(VK_F1))    //按F1键,加速
        {
            speedup();
        }
        else if(GetAsyncKeyState(VK_F2))    //按F2键,减速
        {
        	speeddown();
            
        }
        Sleep(sleeptime);
        snakemove();
    }
}

蛇在前进时,是通过新建头节点,擦去尾节点实现的,并且在吃到食物时,会自动加速。

/*
	控制方向
*/
void snakemove()	//蛇前进,上U,下D,左L,右R
{
	snake * nexthead;
    cantcrosswall();
    nexthead=(snake*)malloc(sizeof(snake));		//为下一步开辟空间
    if(status==U)
    {
        nexthead->x=head->x;        //向上前进时,x坐标不动,y坐标-1
        nexthead->y=head->y-1;
        nexthead->next=head;
        head=nexthead;
        q=head;						//指针q指向蛇头
        if(nexthead->x==food->x && nexthead->y==food->y)	//如果下一个有食物 下一个位置的坐标和食物的坐标相同
        {
            
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
				color(14);
                printf("◆");       //原来食物的位置,从●换成◆
                q=q->next;          //指针q指向的蛇身的下一位也执行循环里的操作
				
            }
            score=score+add;        //吃了一个食物,在总分上加上食物的分
			speedup();
            createfood();           //创建食物
        }
        else                        
        {
            while(q->next->next!=NULL)	//如果没遇到食物
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");           //蛇正常往前走,输出当前位置的蛇身
                q=q->next;              //继续输出整个蛇身
            }
            gotoxy(q->next->x,q->next->y);  //经过上面的循环,q指向蛇尾,蛇尾的下一位,就是蛇走过去的位置
			color(3);
            printf("■");
            free(q->next);			//进行输出■之后,释放指向下一位的指针
            q->next=NULL;			//指针下一位指向空
        }
    }
    if(status==D)
    {
        nexthead->x=head->x;        //向下前进时,x坐标不动,y坐标+1
        nexthead->y=head->y+1;
        nexthead->next=head;
        head=nexthead;
        q=head;
        if(nexthead->x==food->x && nexthead->y==food->y)  //有食物
        {
            
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");
                q=q->next;
            }
            score=score+add;
			speedup();
            createfood();
        }
        else                               //没有食物
        {
            while(q->next->next!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");
                q=q->next;
            }
            gotoxy(q->next->x,q->next->y);
			color(3);
            printf("■");
            free(q->next);
            q->next=NULL;
        }
    }
    if(status==L)
    {
        nexthead->x=head->x-2;        //向左前进时,x坐标向左移动-2,y坐标不动
        nexthead->y=head->y;
        nexthead->next=head;
        head=nexthead;
        q=head;
        if(nexthead->x==food->x && nexthead->y==food->y)//有食物
        {
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");
                q=q->next;
            }
            score=score+add;
			speedup();
            createfood();
        }
        else                                //没有食物
        {
            while(q->next->next!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");
                q=q->next;        
            }
            gotoxy(q->next->x,q->next->y);
			color(3);
            printf("■");
            free(q->next);
            q->next=NULL;
        }
    }
    if(status==R)
    {
        nexthead->x=head->x+2;        //向右前进时,x坐标向右移动+2,y坐标不动
        nexthead->y=head->y;
        nexthead->next=head;
        head=nexthead;
        q=head;
        if(nexthead->x==food->x && nexthead->y==food->y)//有食物
        {
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");
                q=q->next;
            }
            score=score+add;
			speedup();
            createfood();
        }
        else                                         //没有食物
        {
            while(q->next->next!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("◆");
                q=q->next;        
            }
            gotoxy(q->next->x,q->next->y);
			color(3);
            printf("■");
            free(q->next);
            q->next=NULL;
        }
    }
    if(biteself()==1)       //判断是否会咬到自己
    {
        endgamestatus=2;
        endgame();
    }
}

加速代码即缩短时间间隔,同时得分增加。

/*
	加速,蛇吃到食物会自动提速,并且按F1会加速
*/
void speedup()
{
	if(sleeptime>=50)
	{
		sleeptime=sleeptime-10;
		add=add+2;

    }
}

减速亦然。

/*
	减速,按F2会减速
*/
void speeddown()
{
	if(sleeptime<350)               //如果时间间隔小于350
    {
        sleeptime=sleeptime+30;     //时间间隔加上30
        add=add-2;                  //每吃一次食物的得分减2

    }
}

如何判断蛇是否咬到自己,是通过遍历蛇身节点判断是否重复实现的。

/*
	判断是否咬到了自己
*/
int biteself()
{
    snake *self;            //定义self为蛇身上的一个节点
    self=head->next;        //self是蛇头之外的蛇身上的节点
    while(self!=NULL)
    {
        if(self->x==head->x && self->y==head->y)    //如果self和蛇身上的节点重合
        {
            return 1;       //返回1
        }
        self=self->next;
    }
    return 0;
}

而撞墙检查更为简单,判断头节点与上下左右“墙”的坐标值是否重合即可。

/*
	设置蛇撞墙的情况
*/
void cantcrosswall()
{  
    if(head->x==0 || head->x==56 ||head->y==0 || head->y==26) //如果蛇头碰到了墙壁
    {
        endgamestatus=1;        //返回第一种情况
        endgame();              //出现游戏结束界面
    }
}

至此,游戏动态逻辑的编写已经完成。

你可能感兴趣的:(C,贪吃蛇,VC++6.0,C语言)