尝试了贪吃蛇的编写
第一次编写这么长的程序,说实话C语言并没有学到家,完全只是用数组实现的基本功能。不过在思考如何编写程序的过程中我也收获了许多有用的经验。总之结果还是挺满意的。
由于编程在ubuntu中进行,有些关键函数所需的头文件缺失,下载了扩展包后依旧不能解决,让我纠结了好久,不过还是找出了一些方法,在此我对提供帮助的人表示感谢。
源代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/time.h>
#include<sys/types.h>
#include<termios.h>
#include<time.h>
#include<limits.h>
#include<fcntl.h>
#include<signal.h>
#define up 'w'
#define down 's'
#define left 'a' //定义四个方向的对应字符
#define right 'd'
int f1,f2,x,y,m,z1,z2,p,q,r,t,li; //x,y,m is tool,p,q is head,f1 f2 is food,z1,z2 is memory.
char dir; //决定蛇头接下来的方向
char formal_dir; //记忆蛇头原来的方向
int body1[324]; //body1和body2两个数组记忆蛇身坐标
int body2[324];
int main()
{
srand((unsigned)time(NULL)); //设置随机数种子/stdlib.h&time.h
dir='s',li=1, //dir:初始方向向下;li为生命
r=0,t=0,
p=4,q=4; //p,q是蛇头位置,初始位置设为(4,4)
void food(); //随机生成食物的函数
int kbhit();
//响应键盘敲击(在win中有头文件conio.h,但在Linux中没有,故此处为自行定义)
int agetch(); //得到键盘输入字符/linux中没有,自行定义。。。
void direction(); //根据输入字符改变蛇头方向
food();
int bgd[20][20]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};//地图(这样可以轻易修改,加墙啥的)
while(1) //重复循环打印
{
system("clear"); //清屏/stdlib.h
if(bgd[p][q]==1) //判断是否撞到墙或咬到自己
li=0;
else if(bgd[p][q]==3)
{li=0;}
if (li==0) //死亡
break;
r=0;
if(p==f1&&q==f2) //刷新食物
{food();}
r=0;
bgd[f1][f2]=4;
bgd[p][q]=2;
z1=p,z2=q;
x=0,y=0; //打印,0:空位;1:墙;2:蛇头;3:蛇身;4:食物
for(m=1;y<20;y++)
{x=0;
for(m=1;x<20;x++)
{if(bgd[y][x]==1)
printf("#");
else if(bgd[y][x]==0)
printf(" ");
else if(bgd[y][x]==2)
printf("@");
else if(bgd[y][x]==3)
printf("0");
else if(bgd[y][x]==4)
printf("$");
}
printf("\n");
}
formal_dir=dir;
usleep(300000); //休眠函数,sleep单位为秒,usleep为微秒/因gcc:unistd.h
if(kbhit()) //检测有无按键输入,并传给direction()
{dir=agetch();
}
direction();
bgd[z1][z2]=3;
//将蛇身坐标依次记录到数组,并传递变化
if(f1==p&&f2==q) //咬到食物,增加元素
{body1[t]=z1;
body2[t]=z2;
t=t+1;
}
else //未咬到食物,元素位置传递
{
if(t==0)
{body1[0]=z1;
body2[0]=z2;
bgd[body1[0]][body2[0]]=0;}
else
{ body1[t]=z1;
body2[t]=z2;
r=0;
bgd[body1[0]][body2[0]]=0;
while(r<t)
{
body1[r]=body1[r+1];
body2[r]=body2[r+1];
r=r+1;
}
}
}
}
printf("GAME OVER\nscore:%d\n",t);
}
void food()
{
f1=rand()%18+1;
f2=rand()%18+1;
if(f1==p&&f2==q) //食物是否和蛇头重合
{food();}
while(t>r) //食物是否和蛇身重合
{
if(f1==body1[r]&&f2==body2[r])
{food();}
r=r+1;
}
}
void direction()
{ if(dir==up&&formal_dir==down) //防止控制蛇往回走
dir=formal_dir;
else if(dir==down&&formal_dir==up)
dir=formal_dir;
else if(dir==left&&formal_dir==right)
dir=formal_dir;
else if(dir==right&&formal_dir==left)
{dir=formal_dir;}
switch(dir) //蛇四面运动的实现
{ case up:p=p-1;break;
case down:p=p+1;break;
case left:q=q-1;break;
case right:q=q+1;break;
default: //若为其他键输入,则无效化
{dir=formal_dir;
direction();}
}
}
int agetch()
{
struct termios tm, tm_old;
int fd = 0, ch;
if (tcgetattr(fd, &tm) < 0) {//保存现在的终端设置
return -1;
}
tm_old = tm;
cfmakeraw(&tm);//更改终端设置为原始模式,该模式下所有的输入数据以字节为单位被处理
if (tcsetattr(fd, TCSANOW, &tm) < 0) {//设置上更改之后的设置
return -1;
}
ch = getchar();
if (tcsetattr(fd, TCSANOW, &tm_old) < 0) {//更改设置为最初的样子
return -1;
}
return ch;
}
int kbhit(void) //抄来的。。。
{
struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;
}