贪吃蛇循环队列实现

19/7/24

更新

这几天想写一个32操作系统,操作系统上面跑东西啊要,就又拿着贪吃蛇鞭尸了。。。。

这次用循环队列实现,效果比数组好,因为避免了数据的反复后移。只需要直接入队,出队就行

屏幕的刷新上面,没有采取上一次的整体刷新,代替的是确定光标位置,在光标处刷新。

贪吃蛇循环队列实现_第1张图片

更详细注释见代码

/*
食物不能产生在身上未加
//
使用顺序循环队列实现
kbhit()检测键盘是否有输入,有返回非零值,否则0


撞墙会死
前进过程中不能突然折回

                    by shuiyihang0981   19/7/24

//
*/
#include
#include
#include
#include
#define MAX_LEN  100
#define Side_X    30
#define Side_Y    25//墙的边界
//#define  DEBUG
char  dir='s',last_dir='s';//设定默认方向
int test1,test2,test3,test4;//测试bug调用
int count=0,srand_x=0,srand_y=0;
int temp;
bool Game_over=false;
typedef struct
{
	int x,y;
}Pos;
typedef struct
{
	Pos vex;
	bool exist;
}Goal;
typedef struct
{
	Pos date[MAX_LEN];
	int head,rear;

}Snake;
void gotoxy(int x,int y)//任意点确定光标,参考MSDN
{
    COORD point={x,y};
    HANDLE HOutput=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(HOutput,point);
}
void Init(Snake *S)//墙,蛇初始化
{
	S->head=S->rear=0;
	S->date[S->rear].x=2;
	S->date[S->rear].y=3;
	S->rear=(S->rear+1)%MAX_LEN;
	gotoxy(S->date[S->rear-1].x,S->date[S->rear-1].y);
	printf("O");
	gotoxy(Side_X+5,Side_Y/2-5);
	printf("Snake Game");
	gotoxy(0,Side_Y);
	printf("---------------------------------\n");
	gotoxy(Side_X+5,Side_Y/2);
	printf("Core:%d",count);
	for(int i=0;iexist==false)
	{

		food->vex.x=srand_x;
		food->vex.y=srand_y;
		food->exist=true;
		gotoxy(food->vex.x,food->vex.y);
		printf("*");
	}
}
/*
蛇只管前行,遇到食物入队,此时不需要尾巴出队
没有吃到食物,新的队首入队,尾巴出队
*/
void GoHead(Snake *S,Goal *food)//蛇前行
{
	srand_x=rand()%Side_X;
	temp=((S->rear)-1+MAX_LEN)%MAX_LEN;//0的前一个应该是9,而不是-1
	switch(dir)
	{

		case 's':
			if(last_dir!='w')//Up
            {
                S->date[S->rear].y=(S->date[temp].y+1);
                S->date[S->rear].x=(S->date[temp].x);
            }else
            {
                Game_over=true;
                gotoxy(Side_X+5,Side_Y/2+2);
                printf("Bite Self!");
            }
			break;
		case 'w':
			if(last_dir!='s')//Down
            {
                S->date[S->rear].y=(S->date[temp].y-1);
                S->date[S->rear].x=(S->date[temp].x);
            }else
            {
                Game_over=true;
                gotoxy(Side_X+5,Side_Y/2+2);
                printf("Bite Self!");
            }
			break;
		case 'a':
			if(last_dir!='d')//Left
            {
                S->date[S->rear].x=(S->date[temp].x-1);
                S->date[S->rear].y=(S->date[temp].y);
            }else
            {
                Game_over=true;
                gotoxy(Side_X+5,Side_Y/2+2);
                printf("Bite Self!");
            }
			break;
		case 'd':
			if(last_dir!='a')//Right
            {
                S->date[S->rear].x=(S->date[temp].x+1);
                S->date[S->rear].y=(S->date[temp].y);
            }else
            {
                Game_over=true;
                gotoxy(Side_X+5,Side_Y/2+2);
                printf("Bite Self!");
            }
			break;
		default:
			break;

	}
	#ifdef   DEBUG
	test1=S->date[S->rear].x;
	test2=S->date[S->rear].y;
	#endif // DEBUG
	if((S->date[S->rear].x)<0||(S->date[S->rear].x)>Side_X||(S->date[S->rear].y)<0||(S->date[S->rear].y)>Side_Y)//撞墙
    {
        Game_over=true;
        gotoxy(Side_X+5,Side_Y/2+2);
        printf("Brick Wall!");
    }
    else
    {
        gotoxy(S->date[S->rear].x,S->date[S->rear].y);
        printf("O");
        Sleep(0.5);
        if(food->exist&&(S->date[S->rear].x==food->vex.x)&&(S->date[S->rear].y==food->vex.y))
        {
            count++;
            food->exist=false;
            gotoxy(Side_X+10,Side_Y/2);
            printf("%d",count);
        }else
        {
            gotoxy(S->date[S->head].x,S->date[S->head].y);
            printf(" ");
            Sleep(0.5);
            S->head=(S->head+1)%MAX_LEN;
        }
        S->rear=(S->rear+1)%MAX_LEN;
    }

}
void PlayInput()//检测输入
{
    srand_y=rand()%Side_Y;
	if(kbhit())//
	{
	    last_dir=dir;//上一次的方向,规定不能突然折返蛇身
		dir=getch();
		if(dir!='w'&&dir!='a'&&dir!='s'&&dir!='d')
        {
            dir=last_dir;
        }
	}
}
int main()
{
	srand(10);
	Snake Q;
	Goal  food;
	Init(&Q);
	while(false==Game_over)
	{
		PlayInput();
		GoHead(&Q,&food);
		CreFood(&food);
		Sleep(200);//windows.h//游戏速度设定
	}
	gotoxy(Side_X+5,Side_Y/2);
    printf("Game OVER! Count:%d",count);
    gotoxy(0,Side_Y+2);
	return 0;
}

 

 

 

 

 

 

 

 

上一次的数组实现,有兴趣看一下,就不推荐了

贪吃蛇比较简单,要了解它的步骤:

如果你可以单独对某个点重画,就要利用只有蛇头,蛇尾会变的特点,这样会快很多。

我是在windows下跑的,通过cls命令清空,所以会有点闪,sleep函数用于调节蛇的速度

贪吃蛇循环队列实现_第2张图片

O是蛇身,*是食物

//贪吃蛇数组实现,无限生命版(撞墙不会挂)
#include
#include
#include//窗口大小设为20,25;
#include
char str;
int num=0;
int count=0;
bool eated=false;
int rand_x,rand_y;//提前准备着方便使用
struct Snake{
	int x;
	int y;
	char dir;
}mole[50];//可以设置更长>50
struct food{
	int x;
	int y;
}bread;
/初始化
void init()
{
	mole[0].x=10;
	mole[0].y=15;
	bread.x=5;
	bread.y=5;
	//mole[1].dir='a';//默认向左

}
/方向控制
void PlayInput()
{
	rand_y=rand()%20;
	if(kbhit())
	{
		str=getch();
		switch (str){
			case 'w':
				mole[num].dir='w';//可以直接赋值,防止误输入
				break;
			case 'a':
				mole[num].dir='a';
				break;
			case 's':
				mole[num].dir='s';
				break;
			case 'd':
				mole[num].dir='d';
				break;
			default:
				break;
		}
	}
}
/屏幕重画
void show()
{
	bool flag=false;
	for(int i=0;i<20;i++)
	{
		for(int j=0;j<25;j++)
		{
			for(int k=0;k<=num;k++)
			{
				if(mole[k].x==j&&mole[k].y==i)
				{
					printf("O");
					flag=true;
					break;
				}
			}
			if(bread.x==j&&bread.y==i)//画食物
			{
				printf("*");
				//flag=true;
			}
			if(flag==false)printf(" ");
			else flag=false;
		}
		printf("\n");
	}
	printf("Your Score:%d\n", count);
}
/蛇移动
void SnakeMove()//清屏重画
{
	for(int i=0;i19)mole[num].x=0;
			break;
		case 'd':
			mole[num].x=mole[num].x+1;
			if(mole[num].x>24)mole[num].x=0;
			break;
	}
	system("cls");//如果不刷屏的话,只删除蛇尾,效果会更好
	show();
}
食物产生
void creatFood()
{
	if(eated==true)//食物被吃掉随即再次产生
	{
		//范围是25,20
		bread.x=rand_x;
		bread.y=rand_y;
		eated=false;
	}
}
蛇吃食
void FoodEat()
{
	SnakeMove();
	switch (mole[num].dir){
	case 'w':
		if((mole[num].y-1)==bread.y&&mole[num].x==bread.x)
		{
			num++;
			mole[num].x=bread.x;
			mole[num].y=bread.y;
			eated=true;
			count++;
		}
		break;
	case 'a':
		if((mole[num].x-1)==bread.x&&mole[num].y==bread.y)
		{
			num++;
			mole[num].x=bread.x;
			mole[num].y=bread.y;
			eated=true;
			count++;
		}
		break;
	case 's':
		if((mole[num].y+1)==bread.y&&mole[num].x==bread.x)
		{
			num++;
			mole[num].x=bread.x;
			mole[num].y=bread.y;
			eated=true;
			count++;
		}
		break;
	case 'd':
		if((mole[num].x+1)==bread.x&&mole[num].y==bread.y)
		{
			num++;
			mole[num].x=bread.x;
			mole[num].y=bread.y;
			eated=true;
			count++;
		}
		break;
}
	creatFood();
}
int main()
{
	srand(10);
	init();
	while(1)
	{
		PlayInput();
		FoodEat();
		Sleep(250);
	}
	return 0;
}
//-----------------------------By shuiyihang------------------------------------//
//-----------------------------CodeBlocks下测试----------------------------------//

程序肯定是有Bug的,但是目前来看还行,就是有点闪,还可以优化,当然你也可以考虑使用链表

你可能感兴趣的:(Game)