c语言curses小游戏,Ubuntu C语言 curses 贪吃蛇 小游戏

本文详细介绍了使用Curses库开发贪吃蛇游戏的过程,包括使用双向链表结构存储蛇的身体,通过头尾节点的增删来模拟移动,并利用信号定时中断实现均匀移动和速度调整。游戏还包括了墙壁的绘制、食物生成、碰撞检测以及游戏暂停和退出功能。玩家可以通过按键控制蛇的方向,吃到食物会增加分数和长度。
摘要由CSDN通过智能技术生成

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

#include

#include

#include

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

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

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

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

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

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.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

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

//身体

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.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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值