鱼C论坛

 找回密码
 立即注册
查看: 6390|回复: 3

[原创] Linux终端贪吃蛇--

[复制链接]
发表于 2015-7-10 12:23:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这几天看了下linux程序设计,昨天没事干,突发奇想写个贪吃蛇怎么样,因为想想这个游戏也简单!代码全是自己写!

要是有win下的童鞋,注意,这个是linux 版的,用到curses库和pthread库(多线程库)

前提都要安装相关的库
curses库   sudo apt-get install libncurses5-dev
pthread 库sudo apt-get install glibc-doc    sudo apt-get install manpages-posix-dev

编译的时候带上两库 gcc greedsnake.c -o greedsnake -lcurses -lpthread

注:代码全是自己想和写的,没有参照网上代码,故代码质量较差,高人勿喷!而且这个是刚刚完工的版本,存在bug,但是对于刚入门linuxC的来说
已经满意啦!

游戏实现:
        0,因为终端贪吃蛇,所以用字符表示它的身体了,哈
        1,首先是用键盘几个方向键控制贪吃蛇的方向,我这里用全局变量way表示,0 向左,1 向上,2 向右,3 向下
        2,当头部触及到食物的时候,向前走一步,把食物纳为自己身体,同时最后一节身体不丢失,实现身长+1
        3,触及到墙壁或者自己身体的时候,那么蛇死

游戏重点分析:
        一    运行分析
                因为我没有接触到多线程那些,昨天刚开始写的时候只用了curses库,发现贪吃蛇既要向已定的方向移动,又要监视键盘的输入,刚开始我都没有想到要用多线程,后面写完主体实现后发现,运行点击键盘就崩溃程序,百思不得妻姐,后来脑子一闪,想到了java中的多线程,因为接触C都从来没有用过多线程,所以就仓促百度了下实现过程:
        这里,监视键盘输入做为主线程,而游戏运动作为游戏开始后再创立的线程,这样就能实现键盘输入和游戏运行互不影响

        二   如何让终端描绘贪吃蛇
                错误观点:因为使用curses库终端就是一个24×80的屏幕(默认大小),我这里首先想到用一个二维数组,刚开始全部赋值0,表示终端对应x,y坐标不显示任何东西,而要是array[x][y] = 1 那么对应就是贪吃蛇的身体一个点,我首先用这种思想试了,贪吃蛇成功走起,但是bug非常多,每前进一步,头部向前移,尾部点消失,就是这个关键,尾部点的坐标,一开始我是用rear_x 和rear_y保存尾部点,但是,当蛇向前移的时候,下一个尾部点的对应坐标是什么呢?是它的四个方向的哪一个?刚开始想的是哪个方向点不为空就是谁,但是为题来了,当蛇身体有一部分在身边如何判断?(就是它尾部点周围方向又有其他身体点,如蛇的缠绕在一起,尾部周围可能都是点,——) 所以二维行不通,
                正确:那就使用三维数组把,假设那个点存在,那么就保留当前点的时候蛇的前进方向,这样,有了rear_x rear_y就能通过当前点的方向找到下一个尾部节点,比如array[x][y][0] = 1 array[x][y][1] = 2表示当前点为蛇的身体一节点,该节点的前进方向是2(向右)那么这个节点的后一个节点就是
array[x][y+1][0],以此类推,那么找到尾节点就不是问题、

至此,游戏大概思路就这样,主线程处理按键输入,另一线程让贪吃蛇按照既定方向前进

不说,直接上代码
#include <curses.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define Q_line 22
#define width 78
#define height 22

int array[22][78][2]={0};
int head_x = 10;
int head_y = 10;
int rear_x = 10;
int rear_y = 10;
int fool_x;
int fool_y;
int way = 3;
pthread_t id;
//0 left 1 up 2 right 3down

 
int getchoice();//获取键盘输入
void strat_game();//开始游戏
void creat_fool();//产生一个食物节点
void go();//贪吃蛇的运行前进
void refresh_win();//刷新界面
void creat_fool();//
int check_fool();//检测当前方向的前一个节点是不是食物
void go_catch();//吃掉食物
void find_rear();//找到后一个尾节点
void all_check();//检测是不是墙壁或者吃到自身
void snake_die();//死亡方法

int main()
{
    int choice;
    int first =0,key;
    initscr();
    noecho();
    cbreak();
    keypad(stdscr,1);
    mvprintw(5,5,"My Greedy Snake Game V1.0");
    mvprintw(6,10,"Power by HeLe");
    mvprintw(Q_line,5,"Press space to start");
    refresh();

    while((key = getchoice()) != 'q'){
        switch(key){
            case ' ':if(!first){strat_game();first=1;}
            break;
            case KEY_UP:if(way != 3){way = 1;array[head_x][head_y][1] = 1;}
            break;
            case KEY_DOWN:if(way != 1){way = 3;array[head_x][head_y][1] = 3;}
            break;
            case KEY_LEFT:if(way !=2){ way = 0;array[head_x][head_y][1] = 0;}
            break;
            case KEY_RIGHT:if(way != 0) {way = 2;array[head_x][head_y][1] = 2;}
            break;
        }
    }
    endwin();
    exit(EXIT_SUCCESS);
}

void snake_die()
{
    mvprintw(Q_line-1,5,"Snake has die,Press Q to quti");
    refresh();
    pthread_exit("Ok");
    
}

void all_check(int tway)        //check die
{
    if(head_x > Q_line || head_x < 1 || head_y > 77 || head_y < 1)snake_die();
    switch(tway){
        case 0:if(array[head_x][head_y-1][0] == 1)snake_die();
        break;
        case 1:if(array[head_x-1][head_y][0] == 1)snake_die();
        break;
        case 2:if(array[head_x][head_y+1][0] == 1)snake_die();
        break;
        case 3:if(array[head_x+1][head_y][0] == 1) snake_die();
        break;
    }
}

void refresh_win()
{
    int x,y;
    clear();
    for(x = 1; x <= height;x++ )
    {
        for(y = 1; y <= width; y++)
        {
            if(array[x][y][0] == 1)
            {
                mvprintw(x,y,"%s","*");
            } 
            if(x == rear_x && y==rear_y){
                mvprintw(x,y,"%s","$");
            }
            if(x==head_x && y == head_y){
                mvprintw(x,y,"%s","@");
            }
        }
    }
    for(x = 0 ,y =0;y < 78;y++)
    {
        mvprintw(x,y,"-");
        mvprintw(y,x,"|");
        mvprintw(Q_line+1,y,"-");
        mvprintw(y,width,"|");
    }
    move(height,width);
    refresh();
    usleep(200000);
    go();
}

int getchoice(){
    int key;
    key = getch();
    return key;
}

void creat_fool()
{
    srand((unsigned)time(NULL));
    fool_x = rand() %21+1;
    fool_y = rand()%77+1;
    while(array[fool_x][fool_y][0] == 1)
    {
        fool_x = rand()%22+1;
        fool_y = rand()%78+1;
    }
    array[fool_x][fool_y][0] = 1;
}

void strat_game()
{
    clear();
    //box(stdscr,'|','-');
    array[10][10][0] = 1;
    array[10][10][1] = 3;
    creat_fool();
    if((pthread_create(&id,NULL,(void*)refresh_win,NULL)) !=0){
        endwin();
        exit(1);
    }  
}

int check_fool()
{
    switch(way)
    {
        case 0:if(head_x == fool_x && (head_y-1) == fool_y)return 1;
        else return 0;
        break;
        case 1:if((head_x-1) == fool_x && head_y == fool_y)return 1;
        else return 0;
        break;
        case 2:if(head_x == fool_x && (head_y+1) == fool_y)return 1;
        else return 0;
        break;
        case 3:if((head_x+1) == fool_x && head_y == fool_y)return 1;
        else return 0;
        break;
    }
}
void go_catch(int tway)
{
    array[fool_x][fool_y][0] = 1;
    array[fool_x][fool_y][1] = tway;
    head_x = fool_x;
    head_y = fool_y;
    creat_fool();
}

void find_rear()
{
    array[rear_x][rear_y][0] = 0;
    switch(array[rear_x][rear_y][1]){
        case 0:rear_y--;
        break;
        case 1:rear_x--;
        break;
        case 2:rear_y++;
        break;
        case 3:rear_x++;
        break;
    }
}

void go()
{
    switch(way)
    {
        case 0:if(check_fool()){
            go_catch(0);
        }
        else {
            all_check(0);
            array[head_x][--head_y][0] = 1;
            array[head_x][head_y][1] = 0;
            array[rear_x][rear_y][0] = 0;
            find_rear();
        }
        break;
        case 1:if(check_fool()){
            go_catch(1);
        }
        else {
            all_check(1);
            array[--head_x][head_y][0] = 1;
            array[head_x][head_y][1] = 1;
            array[rear_x][rear_y][0] = 0;
            find_rear();
        }
        break;
        case 2:if(check_fool()){
            go_catch(2);
        }
        else {
            all_check(2);
            array[head_x][++head_y][0] = 1;
            array[head_x][head_y][1] = 2;
            array[rear_x][rear_y][0] = 0;
            find_rear();
        }
        break;
        case 3:if(check_fool()){
            go_catch(3);
        }
        else {
            all_check(3);
            array[++head_x][head_y][0] = 1;
            array[head_x][head_y][1] = 3;
            array[rear_x][rear_y][0] = 0;
            find_rear();
        }
        break;
    }
    refresh_win();
}



如果有童鞋有更好的实现方法,可以说说我实现下,哈! 毕竟这个贪吃蛇完全出于我的手!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-7-10 12:27:05 | 显示全部楼层
图片效果
Screenshot from 2015-07-10 12:27:11.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-26 02:57:00 From FishC Mobile | 显示全部楼层
刚学习不久,很多看不懂,只能默默支持一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-8-21 23:00:19 | 显示全部楼层
厉害了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 18:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表