c语言贪吃蛇蛇身越长加速越快,贪吃蛇问题

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

#include

#include

#include

#include

#include

struct Body//定义蛇身结构体

{

short x,y;//蛇身的坐标

struct Body *next;//指向下一个蛇身的指针

};

struct Body *head;//蛇头指针

int length=sizeof(struct Body);//Body结构体所占字节数

int Delay=500;//每次移动之后的停顿时间

short X=0,Y=0;//判断蛇每次移动

short food_x,food_y,food=0;//食物坐标与是否有食物

short life=1;

short score=0;

char movdir='R';//蛇头方向'U'-up,'D'-down,'L'-left,'R'-right

short lockdelay=20;

void Loc(int, int);//光标定位函数

void Beginning();//开始界面

void CreatMap();//创建地图

void GameInit();//游戏初始化

void GameStart();//游戏开始

void DeadOrNo();//蛇的生命

char DeadOrNoByPos(int, int);//蛇的生命

void JudgeFood();

void MakeFood();//制造食物

void ThroWall();//蛇可穿墙

void SnakeMove();//蛇的移动和下面两个函数一起运用

void MoveNo(struct Body *p_body,struct Body *nofood);//没有食物时蛇的移动

void MoveYes(struct Body *yesfood);//有食物时蛇的移动

void DrawSnake(char);//画蛇

void Ending();//结束界面

void HiSleep(int);

int main(void)//主函数

{

srand((unsigned int)time(NULL));//随即种子

again:;

Beginning();//开始欢迎界面

GameInit();//界面初始化

GameStart();//游戏开始

Ending();//结束界面

while(1)

{

if(kbhit())

getch();

else

break;

}

if(getch()!=27)//按ESC键退出游戏(蛇死亡之后)

goto again;

Loc(25,24);

return 0;

}

void Beginning()//开始界面

{

int initx=14,inity=11,init=2;//下面printf字开始右移的初始位置,init代表左右方向

char ch1='\0';

time_t start,end;

}

void CreatMap()//创造地图

{

int i;

for(i=0;i<=56;i+=2)//上下边框

{

Loc(i,0);

printf("□");

Loc(i,24);

printf("□");

}

for(i=0;i<=24;i++)//左右边框

{

Loc(0,i);

printf("□");

Loc(56,i);

printf("□");

}

}

void GameInit()//游戏初始化,创建链表与初始化蛇身,初始化地图

{

struct Body *p_cur,*p_new;//定义四个蛇身指针

int xh;

CreatMap();

head=(struct Body *)malloc(length);

head->x=12;head->y=2;

p_cur=head;

p_cur->next=NULL;

for(xh=0;xh<3;xh++)

{

p_new=(struct Body *)malloc(length);

p_cur->next=p_new;

p_new->x=p_cur->x-2;

p_new->y=p_cur->y;

p_cur=p_new;

p_cur->next=NULL;

}

Delay=500;

food=0;

life=1;

score=0;

movdir='R';

lockdelay=20;

DrawSnake(0);

Loc(65,3);

puts("每吃一个");

Loc(64,4);

puts("蛇会加速哦");

Loc(61,13);

puts("控制键: ↑←↓→");//不会变的游戏提示

}

void GameStart()//游戏开始

{

while(1)

{

DeadOrNo();

if(life==0)//当生命为0时蛇死亡,退出游戏

break;

MakeFood();//制造食物

if(GetAsyncKeyState(VK_UP)&&movdir!='D'&&movdir!='U')//四个if判断是否有方向键输入

movdir='U';

else if(GetAsyncKeyState(VK_DOWN)&&movdir!='U'&&movdir!='D')

movdir='D';

else if(GetAsyncKeyState(VK_LEFT)&&movdir!='R'&&movdir!='L')

movdir='L';

else if(GetAsyncKeyState(VK_RIGHT)&&movdir!='L'&&movdir!='R')

movdir='R';

SnakeMove();//蛇的移动,每次移动一格

Loc(62,7);

printf("得分: %3d",score);//定位,打出所得分数

Loc(62,10);

printf("速度: %5.1f",1000.0/(float)Delay);//定位,打出即时速度,越小越快

HiSleep(Delay);//刷新一次的速度

}

}

void DeadOrNo()//判断蛇死没死

{

struct Body *p_body=head;

while(p_body->next!=NULL)//定位到最后一个蛇身

{

p_body=p_body->next;

if(p_body->x==head->x&&p_body->y==head->y)//如果有任何一个蛇身坐标与蛇头重合,蛇即死亡

life=0;

}

}

char DeadOrNoByPos(int x, int y)

{

struct Body *p_body=head;

while(p_body->next!=NULL)//定位到最后一个蛇身

{

if(p_body->x==x&&p_body->y==y)//如果有任何一个蛇身坐标与蛇头重合,蛇即死亡

return 1;

p_body=p_body->next; //假设情况,忽略蛇尾

}

return 0;

}

void JudgeFood()//判断食物是否与蛇身重叠

{

struct Body *p_body=head;//指向蛇头

while(p_body!=NULL)//当p_body指向最后一节跳出

{

if(food_x==p_body->x&&food_y==p_body->y)//如蛇身与食物重叠则在制造一个食物

{food=0;Loc(62,8);MakeFood();}

p_body=p_body->next;

}

}

void MakeFood()//制造食物

{

if(food==0)

{

food_x=rand()%53+2;

food_y=rand()%23+1;

if(food_x%2==1)

food_x++;//如果坐标为奇数,变为偶数坐标

food=1;

JudgeFood();

}

}

void ThroWall(struct Body *p)//穿墙

{

if(p->x==56)//右进左出

p->x=2;

if(p->x==0)//左进右出

p->x=54;

if(p->y==0)//上进下出

p->y=23;

if(p->y==24)//下进上出

p->y=1;

}

void SnakeMove()//蛇的移动与吃食物,其实就这段最难写

{

struct Body *p_body;//临时结构指针

struct Body *nofood;//没食物

struct Body *yesfood;//有食物

struct Body tmppos;

switch(movdir)

{

case 'U':X=0;Y=-1;break;

case 'D':X=0;Y=1;break;

case 'L':X=-2;Y=0;break;

case 'R':X=2;Y=0;break;

}

tmppos=*head;

tmppos.x+=X;

tmppos.y+=Y;

ThroWall(&tmppos);

if(DeadOrNoByPos(tmppos.x,tmppos.y))

{

if(lockdelay<=0)

life=0;

else

lockdelay--;

}

else

{

lockdelay=(1000/Delay)+1;

if(tmppos.x==food_x&&tmppos.y==food_y)//下一格有食物

MoveYes(yesfood);

else

{

nofood=(struct Body *)malloc(length);//为没食物分配空间

MoveNo(p_body,nofood);

}

}

DrawSnake(1);//画蛇

Loc(food_x,food_y);

printf("●");

}

void MoveYes(struct Body *yesfood)//有食物的移动

{

yesfood=(struct Body *)malloc(length);//每次调用都要为其分配空间,因为每次吃到了食物蛇身会长一节,必须为蛇身在分配一个空间

yesfood->x=food_x;

yesfood->y=food_y;

yesfood->next=head;//新结构拥有了蛇吃完食物的空间

head=yesfood;//在赋给头指针

food=0; score+=1; //加分

MakeFood();//制造食物

}

void MoveNo(struct Body *p_body,struct Body *nofood)//没食物的移动

{

nofood->x=head->x+X;

nofood->y=head->y+Y;

ThroWall(nofood);

nofood->next=head;

head=nofood;//同上

p_body=head;

while((p_body->next)->next!=NULL)//使p_body指向倒数第二个蛇身

p_body=p_body->next;

Loc((p_body->next)->x,(p_body->next)->y);//定位到最后一节蛇身

printf(" ");//消除蛇身

free(p_body->next);//释放空间

p_body->next=NULL;//使倒数第二节成为新的蛇尾

}

void DrawSnake(char simple)//画出蛇头到蛇尾

{

int drawcount=0;

struct Body *p_body=head;//指向蛇头

while(p_body!=NULL)//当p_body指向最后一节跳出

{

Loc(p_body->x,p_body->y);

printf(p_body==head?"■":"□");

drawcount++;

p_body=p_body->next;

if(simple&&drawcount==2)

break;

}

}

void Ending()//结束界面

{

int num=0;

char str[]={"Thank you for playing the snaKe game! "};

system("cls");

Loc(32,9);printf("Game Over!!");

while(str[num]!='\0')

{

Loc(20+num,11);

putchar(str[num]);

num++;

HiSleep(100);

}

Loc(28,13);

puts("按ESC键退出");

Loc(30,15);

puts("按任意键重来...");

}

void Loc(int x, int y)//x为列坐标,y为行坐标,这个不用说了吧~

{

COORD pos = {x,y};

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorPosition(hOut, pos);

}

void HiSleep(int ms)

{

int x;

x=clock();

while(clock()-x

//Sleep(0);

}

#include <stdio.h> #include <windows.h> #include <conio.h> #include <time.h> //游戏窗口 #define FrameX 4 //游戏窗口左上角的X轴坐标 #define FrameY 4 //游戏窗口左上角的Y轴坐标 #define Frame_height 20 //游戏窗口的高度 #define Frame_width 20 //游戏窗口的宽度 //定义全局变量 int i,j; int a[2]; //用于记住蛇尾坐标,其中a[0]、a[1]分别表示横、竖坐标 //声明蛇的结构体 struct Snake { int x[100]; //蛇的横坐标,其中x[0]表示蛇尾的横坐标,x[N-1]表示蛇头的横坐标 int y[100]; //蛇的竖坐标,其中y[0]表示蛇尾的竖坐标,y[N-1]表示蛇头的竖坐标 int count; //蛇吃食物的个数 int length; //蛇的长度 int speed; //蛇的速度 }; //声明食物的结构体 struct Food { int x; //食物的横坐标 int y; //食物的竖坐标 }; /******光标移到指定位置**************************************************************/ void gotoxy(HANDLE hOut, int x, int y) //UNKNOW { COORD pos; pos.X = x; //横坐标 pos.Y = y; //纵坐标 SetConsoleCursorPosition(hOut, pos); } /******设置文本为绿色*****************************************************************/ void Set_TextColor_Green (void) { HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); //UNKNOW SetConsoleTextAttribute(Handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN); //UNKNOW } /******制作游戏窗口******************************************************************/ void make_frame() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定义显示器句柄变量 gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+13); //打印选择菜单 printf("Esc 退出游戏"); gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+15); printf("长按方向键:加速"); gotoxy(hOut,FrameX,FrameY); //打印框角 printf("╔"); gotoxy(hOut,FrameX+2*Frame_width-2,FrameY); printf("╗"); gotoxy(hOut,FrameX,FrameY+Frame_height); printf("╚"); gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+Frame_height); printf("╝"); for(i=2;i<2*Frame_width-2;i+=2) { gotoxy(hOut,FrameX+i,FrameY); printf("═"); //打印上横框 } for(i=2;i<2*Frame_width-2;i+=2) { gotoxy(hOut,FrameX+i,FrameY+Frame_height); printf("═"); //打印下横框 } for(i=1;i<Frame_height;i++) { gotoxy(hOut,FrameX,FrameY+i); printf("║"); //打印左竖框 } for(i=1;i<Frame_height;i++) { gotoxy(hOut,FrameX+2*Frame_width-2,FrameY+i); printf("║"); //打印右竖框 } gotoxy(hOut,FrameX+Frame_width-5,FrameY-2); //打印游戏名称 Set_TextColor_Green (); //设置蛇为绿色 printf("贪吃蛇游戏"); } /******结束菜单*******************************************************************/ void over_game() { system("cls"); printf("\n\n\n\n\n\n\n\n\t\t\t\t游戏结束\n\n\n"); Sleep(2000); getch(); } /******菜单信息***************************************************************/ void print_information(HANDLE hOut,struct Snake *snake,struct Food *food) { gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+1); printf("level : %d",snake->count/5+1); //打印游戏等级 gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+3); printf("score : %d",10*snake->count); //打印游戏得分 gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+5); printf("eat food : %d",snake->count); //打印产生食物个数 gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+7); printf("speed : %dms",snake->speed); //打印游戏速度 gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+9); printf("foodX : %d",food->x); //打印食物的横坐标 gotoxy(hOut,FrameX+2*Frame_width+3,FrameY+11); printf("foodY : %d",food->y); //打印食物的竖坐标 } /******初始化蛇**********************************************************************/ void init_snake(struct Snake *snake) { snake->x[0]=FrameX+2; //初始化蛇的横坐标 snake->y[0]=FrameY+Frame_height/2; //初始化蛇的竖坐标 snake->speed=300; //初始化蛇的速度为300ms snake->length=3; //初始化蛇的长度为3节 snake->count=0; //初始化蛇吃的个数为0 for(i=1;i<snake->length;i++) {/* 依次得到蛇身、蛇头的坐标 */ snake->x[i]=snake->x[i-1]+2; snake->y[i]=snake->y[i-1]; } } /******移动蛇*************************************************************************/ void move_snake(HANDLE hOut,struct Snake *snake) { gotoxy(hOut,snake->x[0],snake->y[0]); printf(" "); /* 清除蛇尾*/ for(i=1;i<snake->length;i++) {/* 后一节的坐标依次取代前一节的坐标 */ snake->x[i-1]=snake->x[i]; snake->y[i-1]=snake->y[i]; } } /******打印蛇*************************************************************************/ void print_snake(HANDLE hOut,struct Snake *snake) { for(i=0;i<snake->length;i++) { gotoxy(hOut,snake->x[i],snake->y[i]); if(i==0) { printf("○"); //打印蛇尾 } else if(i==snake->length-1) { printf("¤"); //打印蛇头 } else { printf("⊙"); //打印蛇身 } } } /******随机产生食物*******************************************************************/ void get_food(HANDLE hOut,struct Snake *snake,struct Food *food) { srand((unsigned)time(NULL)); //初始化随机数 while(1) {/* 产生食物的条件:1.在游戏窗口内 2.不在蛇的身上 */ food->x = rand() % (Frame_width-1); food->y = rand() % Frame_height; if( food->x==0 || food->y==0 ) { continue; } food->x = 2*food->x + FrameX; //得到食物的横坐标 food->y+=FrameY; //得到食物的竖坐标 for(i=0;i<snake->length;i++) {/* 判断食物是否在蛇的身上,如果在蛇身上,则重新产生;否则,打印蛇身 */ if( food->x==snake->x[i] && food->y==snake->y[i] ) { break; } } if(i==snake->length) { gotoxy(hOut,food->x,food->y); printf("⊙"); break; } } } /******吃食物***************************************************************************/ void eat_food(HANDLE hOut,struct Snake *snake,struct Food *food) { if( snake->x[snake->length-1]==food->x && snake->y[snake->length-1]==food->y ) {/* 如果蛇头位置与食物位置相同,吃食物 */ snake->length++; //吃一个食物,蛇身增长一节 for(i=snake->length-1;i>=1;i--) {/* 蛇后节坐标依次赋值给蛇前一节的坐标,依次得到蛇身及蛇头的坐标 */ snake->x[i]=snake->x[i-1]; snake->y[i]=snake->y[i-1]; } snake->x[0]=a[0]; //得到蛇尾移动前的横坐标 snake->y[0]=a[1]; //得到蛇尾移动前的竖坐标 get_food(hOut,snake,food); //重新产生食物 snake->count++; //食物的个数增1 if( snake->count%5==0 ) {/* 当蛇吃Up_level个食物时,速度加快Up_speed毫秒并且升一级 */ snake->speed-=50; } } } /******穿墙**********************************************************************************/ void through_wall(HANDLE hOut,struct Snake *snake,char ch) { if( ch==72 && snake->y[snake->length-1]==FrameY) { snake->y[snake->length-1] = FrameY+Frame_height-1; //如果蛇在上框且向上移动,穿墙 } if( ch==80 && snake->y[snake->length-1]==FrameY+Frame_height ) { snake->y[snake->length-1] = FrameY+1; //如果蛇在下框且向下移动,穿墙 } if( ch==75 && snake->x[snake->length-1]==FrameX ) { snake->x[snake->length-1] = FrameX+2*Frame_width-4; //如果蛇在左框且向左移动,穿墙 } if( ch==77 && snake->x[snake->length-1]==FrameX+2*Frame_width-2 ) { snake->x[snake->length-1] = FrameX+2; //如果蛇在右框且向右移动,穿墙 } } /******判断蛇是否死**************************************************************************/ int if_die(struct Snake *snake) {/* 当蛇头碰到自身时,蛇死 ,返回值为0 */ for(i=0;i<snake->length-1;i++) { if( snake->x[snake->length-1]==snake->x[i] && snake->y[snake->length-1]==snake->y[i] ) { return 0; } } return 1; } /******开始游戏*******************************************************************************/ void start_game() { unsigned char ch=77; //定义用于接收键盘输入的字符变量 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //定义显示器句柄变量 struct Snake s,*snake=&s; //定义蛇的结构体指针并指向蛇的结构体 struct Food f,*food=&f; //定义食物的结构体指针并指向食物的结构体 make_frame(); //制作游戏窗口 init_snake(snake); //初始化蛇 get_food(hOut,snake,food); //随机产生食物 while(1) { print_information(hOut,snake,food); //打印菜单信息 a[0]=snake->x[0]; //记住蛇尾的横坐标 a[1]=snake->y[0]; //记住蛇尾的竖坐标 j=0; if(kbhit()) //unknow {/* 判断是否按下键盘,如果按下,ch接收键盘输入 */ ch=getch(); if(kbhit()) {/* 如果长按键盘,则加速 */ Sleep(20); //unknow j=1; } } switch(ch) { case 72: {/* 向上移动 */ move_snake(hOut,snake); //移动蛇 snake->y[snake->length-1]-=1; //蛇头的竖坐标向上移,即减1 break; } case 80: {/* 向下移动 */ move_snake(hOut,snake); //移动蛇 snake->y[snake->length-1]+=1; //蛇头的竖坐标向下移,即加1 break; } case 75: {/* 向左移动 */ move_snake(hOut,snake); //移动蛇 snake->x[snake->length-1]-=2; //蛇头的横坐标向左移,即减2 break; } case 77: {/* 向右移动 */ move_snake(hOut,snake); //移动蛇 snake->x[snake->length-1]+=2; //蛇头的横坐标向右移,即加2 break; } } through_wall(hOut,snake,ch); //穿墙 eat_food(hOut,snake,food); //吃食物 print_snake(hOut,snake); //打印蛇 if( if_die(snake)==0 || ch==27 || snake->speed==50 ) {/* 游戏结束条件:1.蛇碰到自身 2.按Esc键 3.速度为50ms */ gotoxy(hOut,FrameX+Frame_width-2,FrameY+Frame_height/2-1); printf("Game Over"); Sleep(2000); break; } if(j==0) { Sleep(snake->speed); //延迟时间 } else { Sleep(10); } } } int main() { system("color 0D"); //设置文本为粉红色 start_game(); //开始游戏 over_game(); //结束游戏 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值