学完C语言但不会写贪吃蛇? 嗯嗯没毛病,书上的C语言其给人的感觉也就是用来输出设计好的文字和图像,或者拿来解决数学问题,一顿操作之后输出函数静静地在屏幕上输出结果。而这些都是静态的输出,但游戏应该是动态的输出。 所以要编写贪吃蛇,首先要解决的就是如何输出动态图像的问题。 二维数组和链表?并没有用到,连开始用的结构体都在后期优化当中用两个一维数组代替了。嗯,看别人都说用链表,我也用用看,结果最后结构体都砍了。 二维数组存放地图打印刷新烦人,地图越大越晃眼。这里采用坐标函数配合printf()函数来打印地图,并且打印蛇身和食物也是用这个方法。 使用坐标函数需要调用头文件windows.h,然后自定义这个函数,名字叫什么都可以,这里沿用gotoxy()。其作用很简单,就是将光标移动到指定的坐标。 两个for循环加gotoxy()就可轻松打印出方形地图,并且只需打印一次不像二维数组一样要重复刷新。 注意我编写代码用的是汉字作为输出图形,一个汉字占两个字符位置,从设计的坐标位置到打印坐标位置横坐标要乘2。 只需用坐标打印新蛇头并删除蛇尾就能完成一次移动,随后让蛇身的后一节坐标依次等于前一节坐标,完成下次移动的准备。 整个蛇身的移动由循环函数实现,以Sleep()函数暂停以实现速度控制,而不是瞬间完成循环。 由kbhit()、getch()和switch()函数完成实现:敲击方向键,退出当前方向运动循环,重新进入键入方向运动循环。 撞墙判定:由蛇头部和墙坐标重合触发,进而选择重新开始或退出游戏。 自食判定:由蛇头部和蛇身坐标重合触发,进而选择重新开始或退出游戏。 增长判定:由蛇头部和食物坐标重合触发,然后蛇身增长,食物重新刷新。 通关判定:由蛇长度达到设定长度触发,进而选择下一难度或退出游戏。 gotoxy()、srand()、rand()、Sleep()、kbhit()、getch(),system(),整个实现游戏的代码需要用到以上7个函数,其他的就只是for()、while()、if()、switch()等基本函数了。 其中srand()函数和rand()函数仅用于食物的随机刷新,srand()函数仅出现1次,rand()函数出现于2处。 kbhit()函数和getch()函数用于键盘方向键操作和游戏结束时的选择,kbhit()函数出现3次,getch()函数出现2次。 Sleep()函数仅出现1次。 system(“cls”)用于重启游戏时刷屏,仅出现1次。 这7个函数的讲解可查看我的其他博文,或自行搜索。 编码选择:建议选择GB18030,否则游戏中的汉字可能出现乱码。或者也可以选择把代码中的汉字重打一遍。 游戏源代码编译通用性检测:用了一新一老编译器测试,通用性良好,毕竟vc++6.0都能编译通过。 游戏截图: 第6行: 第7~11行:定义坐标函数gotoxy(),因为全程要用到,所以定义在了主函数之前,还能省一行声明,默默地给机智的自己点一个赞。 第14行: 第15行:初始化前三节蛇身坐标。 第16~27行:打印地图。 第28~31行:打印第一次的食物。 第32行和第40行的while(1)构成嵌套循环游戏主体。 第33~39行:敲击键盘就进行方向选择,不敲击就跳过。75、77、72、80是左右上下的双ASCII码之一。 第41~46行:对应运动方向,把新蛇头坐标赋值给x[0]和y[0],如当choose=1时, 第47行: 第48~57行:检测新蛇头是否吃到食物: 第58~59行:打印新蛇头。 第60行: 第61~63行:自食判定: 第64~66行:打印食物,移开光标。 第67行: 第68行: 第69~74行:单独移动蛇头坐标,之前x[0]和y[0]是提前用了新蛇头坐标,在这里才将x[1]或y[1]移动,放在最后是因为第68行的蛇身赋值要求蛇头坐标最后改变。 第75行: 第81~91行:判断游戏通关还是游戏失败: 第92~97行:while(1)等待,有键盘输入则跳出并继续。49和50是1和2的ASCII码。选1进入下一难度,速度加快,通关长度要求增加,清屏回到初始代码位置,选2退出;其他键不处理,重新等待。 要是超过100个赞我就考虑再写推箱子好还是俄罗斯方块好。文章目录
前言
一、实现原理
1、地图打印
void gotoxy(int x,int y) { COORD p; p.X=x,p.Y=y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),p); }
2、蛇身运动
3、方向键操控
4、四种判定
5、函数工具
二、游戏试玩
1、编译环境
2、源代码
#include<stdio.h> #include<stdlib.h> #include<windows.h> #include<conio.h> #include<time.h> int I=13,J=16,L=6,level=1,_speed=700; void gotoxy(int x,int y){ COORD p; p.X=x,p.Y=y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),p); } int main() { res:int x[100],y[100],xo,yo,choose=2,length=3,fact=0,ability=0; x[1]=3,y[1]=6,x[2]=2,y[2]=6,x[3]=1,y[3]=6; for(int i=0;i<I;i++){ gotoxy(0,i); printf("田"); gotoxy(2*(J-1),i); printf("田"); } for(int j=0;j<J;j++){ gotoxy(2*j,0); printf("田"); gotoxy(2*j,I-1); printf("田"); } srand((unsigned) time(0)); xo=rand()%(J-2)+1,yo=rand()%(I-2)+1; gotoxy(2*xo,yo); printf("虫"); while(1){ if(kbhit()) switch(getch()){ case 75:choose=1;break; case 77:choose=2;break; case 72:choose=3;break; case 80:choose=4; } while(1){ switch(choose){ case 1:x[0]=x[1]-1,y[0]=y[1];break; case 2:x[0]=x[1]+1,y[0]=y[1];break; case 3:y[0]=y[1]-1,x[0]=x[1];break; case 4:y[0]=y[1]+1,x[0]=x[1]; } if(kbhit())break; if(x[0]==xo && y[0]==yo){ xo=rand()%(J-2)+1,yo=rand()%(I-2)+1; length++; gotoxy(34,0); printf("难度等级:%2d 进度得分:%3d",level,100*(length-3)/(L-3)); } else{ gotoxy(2*x[length],y[length]); printf(" "); } gotoxy(2*x[0],y[0]); printf("口"); if(length==L)break; for(int k=2;k<=length;k++) if(x[0]==x[k] && y[0]==y[k])fact=1; if(fact)break; gotoxy(2*xo,yo); printf("虫"); gotoxy(30,20); Sleep(_speed); for(int i=length;i>1;i--)x[i]=x[i-1],y[i]=y[i-1]; switch(choose){ case 1:x[1]--;break; case 2:x[1]++;break; case 3:y[1]--;break; case 4:y[1]++; } if(x[1]<1||x[1]>J-2||y[1]<1||y[1]>I-2) break; } if(x[1]<1||x[1]>J-2||y[1]<1||y[1]>I-2) break; if(fact)break; if(length==L)break; } if(length==L){ gotoxy(11,14); printf("恭喜通关!"); ability=1,level++; printf("n输入1进入下一难度,输入2退出游戏:"); } else{ gotoxy(11,14); printf("GAME OVER!"); printf("n输入1重启游戏,输入2退出游戏:"); } sty:while(1)if(kbhit())break; switch(getch()){ case 49:if(ability==1)_speed=0.6*_speed,L=L/0.6;system("cls");goto res; case 50:break; default:goto sty; } return 0; }
三、代码详解
1、游戏配置部分(第1~31行)
int I=13,J=16,L=6,level=1,_speed=700;
声明全局变量:
I和J是设定地图的宽和长;
L是通关长度;
level是难度等级;
_speed是Sleep()函数的参数,初始设定700毫秒。res:int x[100],y[100],xo,yo,choose=2,length=3,fact=0,ability=0;
声明变量:x[100]和y[100]是存放蛇身坐标的数组;
xo和yo是食物的坐标;
choose是选择运动方向的辅助变量,设定值为2表示开始时自动向右行进;
length是初始蛇长;
fact是辅助自食判定的变量;
ability是辅助判定是否提升难度的变量;
res:配合goto语句重启游戏。2、游戏主体部分(第32~80行)
x[0]=x[1]-1,y[0]=y[1];
x[1]-1和y[1]就是新蛇头坐标,也就是向左移动了一格。if(kbhit())break;
检测到有键盘输入则中断循环回到上一循环,没有就跳过。
吃到就重新随机食物坐标,蛇身长度变量加1,得分增加,蛇尾不删除;
没吃到就去蛇尾坐标位置把蛇尾删掉。if(length==L)break;
通关判定:
长度达标则跳出循环,配合第79行的相同判定跳出双嵌套循环进入游戏结束阶段;
没达标就过。
新蛇头坐标和蛇身坐标重合则跳出循环,配合第78行if(fact)break;
再次判定跳出双嵌套循环进入游戏结束阶段;
没自食就过。Sleep(_speed);
速度控制。for(int i=length;i>1;i--)x[i]=x[i-1],y[i]=y[i-1];
蛇身各坐标顺序向前一格。(仅赋值,下一循环才打印)if(x[1]<1||x[1]>J-2||y[1]<1||y[1]>I-2) break;
撞墙判定:
撞了就跳出循环,配合第77行的相同判定跳出双嵌套循环进入游戏结束阶段;
没撞就过;3、游戏结束部分(第81~99行)
长度达标则输出“恭喜通关”和选择重来或退出的提示,ability赋值为1,等级提升;
长度未达标跳出主体循环就是游戏失败了,输出“GAME OVER”和选择重来或退出的提示。结语
整个代码还有2行是不必要的,大家能找到在那里吗?欢迎给我留言。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算