C语言实现贪吃蛇游戏设计
C语言实现贪吃蛇,供大家参考,具体内容如下
实验平台:DEVC++
/******************************************************************************** *Filename:SnakeGame3.0.c *Description:贪吃蛇游戏源代码(C语言),采用 *宽度优先算法,计算蛇到食物的最短路径(时间复杂度n^3空间复杂度n^2),这个算法遇* *到自身围困情况将失效,无法计算出最短路径* *********************************************************************************/ #include#include #include #include #include #include #defineSIZE25//定义地图大小 #defineMAX_LENGTH19*19//定义蛇的最大长度 typedefstructpoint//地图上的点的节点 { intr; intc; }point; typedefstructqueue//迭代搜索最短路径用到的队列 { point*body[5*SIZE];//保存蛇的身体的数组(栈的深度最大为5*SIZE) intnum;//记录队列中节点数 intfirst_in_pos;//第一个进入队列的元素的索引值 }queue; HANDLEstdOutput;//声明windows标准输出句柄 voidinit(int*length,point*foodAt,int*dir,pointbody[],charmap[][SIZE]);//初始化 intgetDir(intdir);//获取蛇的行进方向 intgetAIDir(intdir,intlength,pointbody[],pointfoodAt);//获取AI判断得出的行进方向 intmoveable(pointmoveTo,intlength,pointbody[]); intmove(pointfoodAt,intdir,intlength,pointbody[]);//蛇的运动 voiddraw(intlength,pointfoodAt,pointbody[],charmap[][SIZE]);//画图 voidfood(point*foodAt,pointbody[],intlength,charmap[][SIZE]);//生成食物 //栈相关的操作 point*pop(queue*queue);//从列队取出最先进入的点,返回取出点的指针,取出失败返回NULL voidpush(point*point,queue*queue);//推入列队中 intmain() { charmap[SIZE][SIZE];//定义地图 pointbody[MAX_LENGTH],foodAt;//整个蛇身体和食物的所在点(body数组的第一个值为蛇头) intlength;//蛇的实际长度 intdir;//行进方向 intrate=1;//行进速率 intresult;//保存蛇运动的结果:【死亡】、【得分】、【无】 init(&length,&foodAt,&dir,body,map);//初始化 while(1) { Sleep(100/rate); //dir=getDir(dir);//获取蛇的行进方向 dir=getAIDir(dir,length,body,foodAt);//获取AI判断得出的行进方向 result=move(foodAt,dir,length,body);//蛇的运动 if(result==1)//如果吃到食物 { length++; rate=length/3; if(length==MAX_LENGTH) { printf("您已通关!"); break; } food(&foodAt,body,length,map);//生成食物 } draw(length,foodAt,body,map);//画图 if(result==-1)//如果死亡 { break; } } Sleep(500); printf("失败,此次得分为%d",(length-3)*100); system("pause"); } voidinit(int*length,point*foodAt,int*dir,pointbody[],charmap[][SIZE])//初始化 { memset(map,'*',SIZE*SIZE);//初始化地图 body[0].r=3,body[0].c=2;//初始化蛇的身体 body[1].r=2,body[1].c=2; body[2].r=1,body[2].c=2; *length=3;//初始长度为3 *dir=2;//初始方向向下 food(foodAt,body,*length,map);//生成食物 draw(*length,*foodAt,body,map);//画图 printf("按下任意键开始,用ASDW控制方向,ESC暂停\n"); _getch(); srand((unsigned)time(NULL));//生成随机数种子,备用 stdOutput=GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出句柄 CONSOLE_CURSOR_INFOcci; cci.bVisible=0; cci.dwSize=1; SetConsoleCursorInfo(stdOutput,&cci); COORDcoord={0,SIZE*2+3}; } intgetDir(intdir)//获取蛇的行进方向,规定返回值0代表向上,1代表向右,2代表向下,3代表向左 { charkey; intnewDir=dir; if(_kbhit()) { key=_getch(); switch(key) { case'A':case'a':newDir=3;break; case'S':case's':newDir=2;break; case'D':case'd':newDir=1;break; case'W':case'w':newDir=0;break; case27:_getch();break; } } if(newDir-dir==2||newDir-dir==-2)//蛇不能反向 { newDir=dir; } returnnewDir; } intgetAIDir(intdir,intlength,pointbody[],pointfoodAt)//获取AI判断得出的行进方向 { staticint*shortestPathDir,count=0;//保存最短路径的方向(方向的先后顺序为倒序,即排在后面的方向先走) if(count==0)//如果最短路径还没生成,那么重新生成 { intmap_of_steps[SIZE][SIZE];//保存到达地图上某一点的最小步数 queuequeue={0,0}; point*last_body=(point*)malloc(length*sizeof(point));//保存计算过程中上次蛇的身体位置 point*next_body;//保存下一次蛇的身体 pointnext_point; inti,step=0; pointmoveTo; memcpy(last_body,body,length*sizeof(point)); memset(map_of_steps,0,SIZE*SIZE*sizeof(int)); //向队列中放入初始body push(last_body,&queue); push(NULL,&queue);//插入NULL来标识宽度优先搜索的某一层的结束 step++;//用step来表示步数,也代表层数 while(queue.num!=0) { last_body=pop(&queue); if(last_body==NULL)//如果某一层结束 { if(queue.num!=0)//如果还有下一层的元素 { step++; push(NULL,&queue);//插入下一层的结束标志 continue; } else { break; } } for(i=0;i<4;i++)//分别检测四个方向能否移动 { switch(i) { case0:moveTo.r=last_body[0].r-1,moveTo.c=last_body[0].c;break; case1:moveTo.r=last_body[0].r,moveTo.c=last_body[0].c+1;break; case2:moveTo.r=last_body[0].r+1,moveTo.c=last_body[0].c;break; case3:moveTo.r=last_body[0].r,moveTo.c=last_body[0].c-1;break; } if(moveable(moveTo,length,last_body)&&map_of_steps[moveTo.r][moveTo.c]==0)//如果移向的点之前没有移到过 //(即当前路径是到该点的最短路径),而且该点是moveable的 { map_of_steps[moveTo.r][moveTo.c]=step; if(moveTo.r==foodAt.r&&moveTo.c==foodAt.c)//如果下一步就可以到达食物所在点 { //先free一些没用的动态内存 free(last_body); while(queue.num!=0) { free(pop(&queue)); } gotoouter;//跳出循环 } //生成next_body并将其推入队列 next_body=(point*)malloc(length*sizeof(point)); for(i=length-1;i>0;i--)//移动蛇的位置 { next_body[i]=body[i-1]; } next_body[0]=moveTo;//换一个头 push(next_body,&queue);//推入队列 } } //free一些没用的动态内存 free(last_body); } outer:; if(map_of_steps[foodAt.r][foodAt.c]==0)//如果无法到达食物所在点,那么按原路走,直到死亡 { returndir; } //生成shortestPath shortestPathDir=(int*)malloc(step*sizeof(int)); count=step; next_point=foodAt; for(i=0;i =0&&map_of_steps[next_point.r][next_point.c]== map_of_steps[next_point.r][next_point.c-1]+1) { shortestPathDir[i]=1; next_point.c-=1; } elseif(next_point.r-1>=0&&map_of_steps[next_point.r][next_point.c]== map_of_steps[next_point.r-1][next_point.c]+1) { shortestPathDir[i]=2; next_point.r-=1; } else { shortestPathDir[i]=3; next_point.c+=1; } } //第一步要单独判断(因为map_of_steps的值为0的点可能是蛇头,也可能是蛇身,这样会对蛇第一步方向判断产生干扰) if(body[0].r>next_point.r) { shortestPathDir[step-1]=0; } elseif(body[0].r next_point.c) { shortestPathDir[step-1]=3; } else { shortestPathDir[step-1]=1; } /*printf("\n\n\n"); intj; for(i=0;i =SIZE||moveTo.c<0||moveTo.c>=SIZE)//如果超出边界 { return0; } return1; } intmove(pointfoodAt,intdir,intlength,pointbody[])//蛇的运动,规定返回值-1代表死亡,0代表没有吃到食物,1代表吃到食物 { inti,flag=0; pointhead=body[0]; switch(dir) { case0:head.r-=1;break; case1:head.c+=1;break; case2:head.r+=1;break; case3:head.c-=1;break; } if(head.r<0||head.r>=SIZE||head.c<0||head.c>=SIZE)//出界了死亡 { return-1; } for(i=0;i 0;i--)//移动蛇的位置 { body[i]=body[i-1]; } body[0]=head;//换一个头 if(flag==1) { return1; } return0; } voiddraw(intlength,pointfoodAt,pointbody[],charmap[][SIZE])//画图 { staticcharbitmap[SIZE+2][SIZE+2];//定义一个数组,用于把地图背景、边界、蛇、食物都画上去 inti,j; for(i=0;i r=rand()%SIZE,foodAt->c=rand()%SIZE;//随机生成食物位置 for(i=0;i r==body[i].r&&foodAt->c==body[i].c)//如果该位置在蛇的身体上 { gotoretry; } } break; retry:; } } //队列相关的函数 point*pop(queue*queue)//从队列中取出,返回取出点的指针 { queue->num--; if(queue->first_in_pos==5*SIZE-1)//返回第一进入队列的点,并将变量fist_in_pos改变 { queue->first_in_pos=0; returnqueue->body[5*SIZE-1]; } else { returnqueue->body[queue->first_in_pos++]; } } voidpush(point*body,queue*queue) { if(queue->num==0)//如果队列已空 { queue->num++; queue->first_in_pos=0;//将第一进入队列的位置设为0 queue->body[queue->first_in_pos]=body; } else//否则插入队列 { if(queue->first_in_pos+queue->num>5*SIZE-1) { queue->body[queue->first_in_pos+queue->num++-5*SIZE]=body; } else { queue->body[queue->first_in_pos+queue->num++]=body; } } }
更多有趣的经典小游戏实现专题,分享给大家:
C++经典小游戏汇总
python经典小游戏汇总
python俄罗斯方块游戏集合
JavaScript经典游戏玩不停
java经典小游戏汇总
javascript经典小游戏汇总
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。