c语言贪吃蛇 MSDN,贪吃蛇循环队列实现

19/7/24

更新

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

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

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

fa875ec0453db565965ccc2d8badb48c.png

更详细注释见代码

/*

食物不能产生在身上未加

//

使用顺序循环队列实现

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;

}

9e4d1a065848fc5c06d2d8e10434a4b0.png

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

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

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

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

88299035aa2c901b460b766273ba4acc.png

O是蛇身,*是食物

//贪吃蛇数组实现,无限生命版(撞墙不会挂)

#include#include#include//窗口大小设为20,25;

#includechar 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的,但是目前来看还行,就是有点闪,还可以优化,当然你也可以考虑使用链表

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值