Curses
需要使用这个库,通过这个库来进行屏幕的刷新
详情请参考: http://blog.csdn.net/hengqiaqia/article/details/77882270
通过学习了解了 curses ,在来进行贪吃蛇的游戏分析
蛇的移动问题,这个是核心部分以及最困难的设计部分了,我采用的是蛇用双向链表的结构来构造出来,分别有一个head 和tail指针,用来添加和删除元素。这里若要实现移动的话(未碰到食物前),就是在链表的头部(head的下一个)插入一个新元素,记录下此时的坐标,用mvaddch(y,x,c)函数添加蛇的图形'@',与此同时,在链表尾部(tail的前一个)删除一个节点,同时这里的坐标用mvaddch(y,x, ' ')添加了' '空白字符,实现删除效果,最后加上refresh(). 这样就可以看到蛇在“移动”了。当然,要是碰到食物的话,尾部节点处就不用删除,达到增长长度的效
如何触发蛇的移动呢?如何实现均匀移动以及通过按键 ‘f’ 或 's' 改变运动速度呢?这里我采用的是信号计时中断调用的函数 signal(SIGALRM, Snake_Move) 和 间隔计数器来实现,通过产生相同间隔的时间片段来不断地调用Snake_Move()函数来执行相应的功能。加减速的功能是通过设定其他变量ttm, ttg来实现再此基本计数器上面再次分频的效果来加减速,ttm, ttg 越大,减速越明显,反之则相反效果。
思路: 双链表,每个结点记录的是当前蛇身的坐标跟前驱后继指针。这样在蛇移动时在头结点前添加一个结点,用move()移动到蛇头坐标,打印蛇头;接着如果没有吃到食物的话,把尾结点删掉,用move()移动到蛇尾,打印空值。
//mysnake1.0.c
//编译命令:gcc mysnake1.0.c -lcurses -o mysnake1.0 -Wall
//用方向键控制蛇的方向
#include<curses.h>
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
struct Snack
{int x[100],y[100];
int node;
int life;
int direction;
}snack; //
struct Food
{ int X,Y;
int set;
}food; //食物
struct timespec delay;
struct timespec dummy;
time_t timer;
int TIME=0;
long Time,Time1=0,Time2=0;
int ptime[100];
int score=0;
int i,tem[2],k=0;
void color(); // 画布
void init(); //初始化
void draw(); //
void start_attr(); //
void output();
void play(); //开始
void judge(); //判断蛇的位置
int pause_time(int ,int *); // 时间暂停
void d_e();
int main(int argc,char **argv)
{
init();
draw();
play();
return 0;
}
void d_e() //开始选择困难的程度
{
int location=18;
int ch2=KEY_LEFT,which=0;
char str[2][5]={"Easy","Hard"};
while(ch2!='\n')
{
switch(ch2)
{
case (KEY_LEFT):
if(location!=18)
{location-=10;which=0;}
break;
case (KEY_RIGHT):
if(location==18)
{location+=10;which=1;}
break;
}
mvprintw(8,10,"Please choose the difficulty!");
mvprintw(10,23,"^_^");
mvprintw(12,18,"Easy");
mvprintw(12,28,"Hard");
attron(A_REVERSE);
mvprintw(12,location,"%s",str[which]);
attroff(A_REVERSE);
refresh();
ch2=getch();}
/*Time2=time(NULL);
ptime[k]=Time2-Time1;
k++; */
if(location==28)
delay.tv_nsec=100000000;
else
delay.tv_nsec=200000000;
}
int pause_time(int k,int *PTIME) //时间的暂停
{
int j;int sum=0;
for(j=0;j<k;j++)
sum=sum+ptime[j];
return sum;
}
void judge() // 蛇的位置
{
if(snack.direction==1)
snack.y[0]--;
else if(snack.direction==2)
snack.y[0]++;
else if(snack.direction==3)
snack.x[0]--;
else
snack.x[0]++;
}
void color() //周围的墙
{
start_color();
init_pair(1,COLOR_GREEN,COLOR_RED);
attron(COLOR_PAIR(1));
for(i=0;i<50;i++)
mvaddch(0,i,'■');
for(i=0;i<20;i++)
mvaddch(i,0,'■');
for(i=49;i>=0;i--)
mvaddch(19,i,'■');
for(i=19;i>=0;i--)
mvaddch(i,49,'■');//box(stdscr,'*','*');
attroff(COLOR_PAIR(1));
}
void init()
{
initscr();
raw();
noecho();
keypad(stdscr,TRUE);
curs_set(0);
nodelay(stdscr,TRUE);
}
void draw() //蛇开始 以及食物
{
snack.x[0]=6;
snack.y[0]=3;
snack.x[1]=5;
snack.y[1]=3;
snack.x[2]=4;
snack.y[2]=3;
snack.life=0;
snack.node=1;
snack.direction=4;
food.set=0;
color();
d_e();
for(i=0;i<snack.node;i++)
mvprintw(snack.y[i],snack.x[i],"$");
refresh();
timer=time(NULL);
}
void output() //打印输出显示
{ color();
mvprintw(20,0,"Score=%d",score);
mvprintw(20,43,"Node=%d",snack.node);
mvprintw(21,0,"Time=%ds",TIME);
attroff(A_REVERSE);
refresh();
}
void start_attr()
{
attron(A_REVERSE);
}
void play()
{
while(1)
{
Time=time(NULL);
TIME=Time-timer-pause_time(k,ptime);
clear();
if(food.set==0)
{
food.X=rand()%50;
while(food.X==0||food.X==49)
food.X=rand()%50;
food.Y=rand()%20;
while(food.Y==0||food.Y==19)
food.Y=rand()%20;
food.set=1;
}
tem[0]=snack.y[snack.node-1];tem[1]=snack.x[snack.node-1];
for(i=snack.node-1;i>0;i--)
{
snack.x[i]=snack.x[i-1];
snack.y[i]=snack.y[i-1];
}
int ch=0;
ch=getch();
switch(ch)
{
case(KEY_UP):
if(snack.direction==3||snack.direction==4)
{
snack.y[0]--;
snack.direction=1;
}
else if(snack.direction==1)
snack.y[0]--;
else
snack.y[0]++;
break;
case(KEY_DOWN):
if(snack.direction==3||snack.direction==4)
{
snack.y[0]++;
snack.direction=2;
}
else if(snack.direction==1)
snack.y[0]--;
else
snack.y[0]++;
break;
case(KEY_LEFT):
if(snack.direction==1||snack.direction==2)
{
snack.x[0]--;
snack.direction=3;
}
else if(snack.direction==3)
snack.x[0]--;
else
snack.x[0]++;
break;
case(KEY_RIGHT):
if(snack.direction==1||snack.direction==2)
{
snack.x[0]++;
snack.direction=4;
}
else if(snack.direction==3)
snack.x[0]--;
else
snack.x[0]++;
break;
case 'p':case 'P':
Time1=time(NULL);
judge();
for(i=0;i<snack.node;i++)
mvprintw(snack.y[i],snack.x[i],">");
mvaddch(food.Y,food.X,'$');
start_attr();
mvprintw(9,10,"Pause!Press 'p' to continue!");
output();
while(getch()!='p')
;
Time2=time(NULL);
ptime[k]=Time2-Time1;
k++;
break;
case 'q':case 'Q':
Time1=time(NULL);
judge();
for(i=0;i<snack.node;i++)
mvprintw(snack.y[i],snack.x[i],">");
mvaddch(food.Y,food.X,'$');
start_attr();
mvprintw(10,22,"Quit!");
output();
int location=18;
int ch2=KEY_LEFT,which=0;
char str[2][5]={"No","Yes"};
while(ch2!='\n')
{
switch(ch2)
{
case (KEY_LEFT):
if(location!=18)
{location-=10;which=0;}
break;
case (KEY_RIGHT):
if(location==18)
{location+=10;which=1;}
break;
}
mvprintw(12,18,"No");
mvprintw(12,28,"Yes");
attron(A_REVERSE);
mvprintw(12,location,"%s",str[which]);
attroff(A_REVERSE);
refresh();
ch2=getch();}
Time2=time(NULL);
ptime[k]=Time2-Time1;
k++;
if(location==18)
break;
else
{
clear();
endwin();
exit(1);
}
default:
judge();
break;
}
for(i=1;i<snack.node;i++)
if((snack.x[0]==snack.x[i]&&snack.y[0]==snack.y[i])||snack.x[0]==0||snack.y[0]==0||snack.x[0]==49||snack.y[0]==19)
{ for(i=1;i<snack.node;i++)
{snack.x[i-1]=snack.x[i];snack.y[i-1]=snack.y[i];}
snack.y[snack.node-1]=tem[0];
snack.x[snack.node-1]=tem[1];
for(i=0;i<snack.node;i++)
mvprintw(snack.y[i],snack.x[i],">");
mvaddch(food.Y,food.X,'$');
start_attr();
mvprintw(10,10,"You lose!");
mvprintw(11,10,"Do you want again?(y/n)");
output();
snack.life=1;
//sleep(1);
break;
}
if(snack.x[0]==food.X&&snack.y[0]==food.Y)
{
food.set=0;
snack.node++;
score+=10;
for(i=snack.node-1;i>0;i--)
{
snack.x[i]=snack.x[i-1];
snack.y[i]=snack.y[i-1];
}
judge();
}
if(snack.life==0)
{ ;
for(i=0;i<snack.node;i++)
//身体
mvprintw(snack.y[i],snack.x[i],">");
//attron(A_INVIS);
//食物
mvaddch(food.Y,food.X,'$');
//sleep(1);
//attroff(A_INVIS);
start_attr();
output();
nanosleep(&delay,&dummy);//sleep(2);
}
else
{
char ch1;
while((ch1=getch()))
if(ch1=='y'||ch1=='Y')
{ clear();
for(i=0;i<snack.node;i++)
snack.x[i]=snack.y[i]=-1;
TIME=Time1=Time2=k=0;
score=0;
draw();
snack.life=0;
break;
}
else if(ch1=='n'||ch1=='N')
{
//退出
endwin();
exit(1);
}
else continue;
}
}
}
来一张效果图:
效果图有点大,发不上来,已传云盘,以下链接:
https://pan.baidu.com/s/1ck3cgI