Ubuntu C语言 curses 贪吃蛇 小游戏

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

参考资源链接:[Linux下五子棋游戏开发:基于GTK2.0的课程设计](https://wenku.csdn.net/doc/649cf9a650e8173efdb0b92e?utm_source=wenku_answer2doc_content) 要创建一个基于GTK2.0的五子棋游戏,首先需要理解Linux操作系统的基本知识,熟悉命令行操作和软件安装过程。接着,学习GTK+库的基本语法和控件使用,这对于图形界面的设计至关重要。在理解五子棋游戏规则的前提下,你需要编写程序逻辑,包括游戏状态的表示、胜利条件的判断等。集成开发环境Eclipse的使用是编程实现的核心部分,它提供了代码编写、调试和管理的平台。利用VirtualBox虚拟机,你可以在Windows环境中安装Ubuntu系统,并在其中配置Eclipse与GTK2.0开发环境。此外,项目测试和调试也是必不可少的环节,你需要使用各种测试方法确保游戏的正确性和稳定性。建议参考《Linux下五子棋游戏开发:基于GTK2.0的课程设计》来获取具体的实现细节和示例代码。这本书详细介绍了整个开发过程,包括如何处理游戏逻辑、如何在Ubuntu环境下安装和配置所需软件,以及如何使用Eclipse进行项目的开发和管理。通过学习这门课程,你不仅能够掌握五子棋游戏的开发技巧,还能加深对Linux平台开发的理解。 参考资源链接:[Linux下五子棋游戏开发:基于GTK2.0的课程设计](https://wenku.csdn.net/doc/649cf9a650e8173efdb0b92e?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值