免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: forest077
打印 上一主题 下一主题

[算法] [原创]贡献一个unix的贪吃蛇小游戏 [复制链接]

论坛徽章:
0
71 [报告]
发表于 2012-11-14 16:15 |只看该作者
/***snake.c***/
#include <stdio.h>
#include <malloc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <termio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define SNAKE_INITX 5
#define SNAKE_INITY 5
#define SNAKE_SHAPE '*'
#define SNAKE_INITLEN 8

#define WIN_X1 1
#define WIN_X2 80
#define WIN_Y1 1
#define WIN_Y2 24

#define MAX_LEVEL 20
#define MAX_INTER 200000
#define MIN_INTER 0
#define MAX_RICH 10
#define DEVRATE 5
#define OVER "Game Over!!!"

struct stNode {
        int x;
        int y;
        char shape;
        struct stNode *next;
};

struct stFood {
        int x;
        int y;
};

struct stNode *gpstHead, *gpstTail;
struct stFood gastFood[MAX_RICH];
int giLevel = 1;
int giRich = 1;
int giScore = 0;
int giLen = 0;

void settty(int iFlag)
{
        int fd;
        struct termio stTerm;

        if((fd = open(ttyname(1), O_RDWR)) == -1)        //ttyname()返回tty1的name  
                return;                                        //fd是打开tty1
        if(iFlag == 1)
        {
                ioctl(fd, TCGETA, &stTerm);        //获取tty1的状态
                stTerm.c_lflag &= ~ICANON;        //设置tty1的状态
                stTerm.c_lflag &= ~ECHO;
                stTerm.c_cc[4] = 1;
                stTerm.c_cc[5] = 0;
                stTerm.c_iflag &= ~ISTRIP;
                stTerm.c_cflag |= CS8;
                stTerm.c_cflag &= ~PARENB;
                ioctl(fd, TCSETA, &stTerm);
        } else
        {
                ioctl(fd, TCGETA, &stTerm);
                stTerm.c_lflag |= ICANON;
                stTerm.c_lflag |= ECHO;
                stTerm.c_cc[4] = 4;
                stTerm.c_cc[5] = 5;
                stTerm.c_iflag &= ~ISTRIP;
                stTerm.c_cflag |= CS8;
                stTerm.c_cflag &= ~PARENB;
                ioctl(fd, TCSETA, &stTerm);
        }
        close(fd);
}

//绘制蛇的节点
void vDrawOneNode(struct stNode *pstNode, int iFlag)
{
    if(iFlag == 1)
    {
            printf("\033[%dm\033[%d;%dm\033[%d;%dH%c",
                   iFlag,40, 33, pstNode->y, pstNode->x, pstNode->shape);
    }
    if(iFlag == 0)
    {
            printf("\033[%dm\033[%d;%dH%c",
                   iFlag, pstNode->y, pstNode->x, ' ');
    }
    //修改了蛇的运行轨迹BUG
        //printf("\033[%dm\033[%d;%dm\033[%d;%dH%c",
        //           iFlag,45 - iFlag * 5, 35 - iFlag * 2, pstNode->y, pstNode->x, pstNode->shape);
        fflush(stdout);
}

void vDrawOneFood(int x, int y)
{
        printf("\033[1m\033[40;36m\033[%d;%dH%c", y, x, '@');
        fflush(stdout);
}

int iGetDir(int iOriDir)
{
        fd_set rset;
        struct timeval hTmo;
        int iRet, iFlag = 0;
        char cCh;

        FD_ZERO(&rset);
        FD_SET(0, &rset);
        hTmo.tv_sec = 0;
        hTmo.tv_usec = MAX_INTER - (MAX_INTER - MIN_INTER) / MAX_LEVEL * giLevel;

        iRet = select(1, &rset, NULL, NULL, &hTmo);
        if(iRet <= 0)
        {
                return (iOriDir);
        }
        for (;
        {
                cCh = getchar();
                if(cCh != -1)
                {
                        switch (cCh)
                        {
                        case 27:
                        case 91:
                                iFlag++;
                                break;
                        case 65:                        //UP
                        case 66:                        //DOWN
                        case 67:                        //RIGHT
                        case 68:                        //LEFT
                                if(iFlag == 2)
                                        return ((!((cCh - 0x41) ^ iOriDir ^ 1)) ^ (cCh - 0x41));
                        default:
                                return (iOriDir);
                        }
                }
        }
}

void vInitScreen()
{
        settty(1);
        printf("\033[?25l\033[2J";        //隐藏光标和清屏
}

void vRestoreScreen()
{
    //修正了游戏结束时,屏幕显示的BUG
        //printf("\033[25;1H\033[0m\033[46;37m\033[?25h";
        printf("\033[25;1H\033[0m\033[?25h";
        settty(0);
}

void vDrawScope()
{
        int i, j;

        for (j = WIN_Y1; j <= WIN_Y2; j += WIN_Y2 - WIN_Y1)
        {
                printf("\033[%d;%dH+", j, WIN_X1);        //光标定位和答应每行开头的“+”号
                for (i = WIN_X1 + 1; i < WIN_X2; i++)
                        printf("-";                //打印每行中间的“-”
                printf("+";                        //打印每行末尾的“+”
        }
        for (i = WIN_Y1 + 1; i < WIN_Y2; i++)
                //将第二行到倒数第二行中间设置为空,同时开头和末尾设置为“|”
                //不明白为什么只有三个占位符,却又四个参数?
                printf("\033[%d;%dH|%*c|\n", i, WIN_X1, WIN_X2 - WIN_X1 - 1, ' ');
}

void vCreateSnake()
{
        struct stNode *pstNew;
        int i;

        gpstHead = (struct stNode *) malloc(sizeof(struct stNode));        //为蛇头开辟空间,同时初始化蛇头位置
        gpstHead->x = SNAKE_INITX;
        gpstHead->y = SNAKE_INITY;
        gpstHead->shape = SNAKE_SHAPE;
        gpstHead->next = NULL;
        vDrawOneNode(gpstHead, 1);        //绘制蛇头节点
        gpstTail = gpstHead;
        for (i = 1; i < SNAKE_INITLEN; i++)        //绘制其他蛇身节点
        {
                pstNew = (struct stNode *) malloc(sizeof(struct stNode));
                pstNew->x = gpstHead->x + 1;
                pstNew->y = gpstHead->y;
                pstNew->shape = SNAKE_SHAPE;
                pstNew->next = NULL;
                vDrawOneNode(pstNew, 1);
                gpstHead->next = pstNew;
                gpstHead = pstNew;
        }
        return;
}

void vKillSnake()
{
        struct stNode *pstNode;

        for (pstNode = gpstTail; gpstTail != NULL
        {
                gpstTail = pstNode->next;
                free(pstNode);
                pstNode = gpstTail;
        }
}

void vGenFood(int iIdx)
{
        struct stNode *pstNode;
        int i, iFound = 0;

        for (; !iFound
        {
                iFound = 1;
                gastFood[iIdx].x = rand() % (WIN_X2 - WIN_X1 - 1) + WIN_X1 + 1;
                gastFood[iIdx].y = rand() % (WIN_Y2 - WIN_Y1 - 1) + WIN_Y1 + 1;
                for (i = 0; i < giRich; i++)
                {
                        if(i != iIdx && gastFood[iIdx].x == gastFood.x &&
                           gastFood[iIdx].y == gastFood.y)
                        {
                                iFound = 0;
                                break;
                        }
                }
                if(!iFound)
                        continue;
                for (pstNode = gpstTail; pstNode != NULL; pstNode = pstNode->next)
                {
                        if(gastFood[iIdx].x == pstNode->x && gastFood[iIdx].y == pstNode->y)
                        {
                                iFound = 0;
                                break;
                        }
                }
                if(!iFound)
                        continue;
        }
        vDrawOneFood(gastFood[iIdx].x, gastFood[iIdx].y);
}

void vInitFood()
{
        int i;

        srand(getpid());
        for (i = 0; i < giRich; i++)
                vGenFood(i);
}

int iIsValid(int x, int y)
{
        struct stNode *pstNode;

        if(x <= WIN_X1 || x >= WIN_X2 || y <= WIN_Y1 || y >= WIN_Y2)
                return (0);
        pstNode = gpstTail;
        for (; pstNode != NULL
        {
                if(x == pstNode->x && y == pstNode->y)
                        return (0);
                pstNode = pstNode->next;
        }
        return (1);
}

int iEat(int x, int y)
{
        int i;

        for (i = 0; i < giRich; i++)
        {
                if(x == gastFood.x && y == gastFood.y)
                {
                        vGenFood(i);
                        giScore += giLevel * 10;
                        giLen++;
                        if(giLevel < MAX_LEVEL)
                                if(giLen % DEVRATE == 0)
                                        giLevel++;
                        return (1);
                }
        }
        return (0);
}

int main(void)
{
        int iDir = 2, iNextX, iNextY;
        struct stNode *pstNew;
        char sPrompt[80];

        vInitScreen();                                //初始化tty1和清屏
        vDrawScope();                                //绘制外围边框
        vCreateSnake();                                //创建蛇的原型
        vInitFood();                                //初始化食物
        for (;
        {
                iDir = iGetDir(iDir);
                iNextX = gpstHead->x + (iDir >> 1) * (5 - (iDir << 1));
                iNextY = gpstHead->y - (!(iDir >> 1)) * (1 - (iDir << 1));
                if(!iIsValid(iNextX, iNextY))
                {
                        printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
                                   WIN_Y2 - 1, (WIN_X1 + WIN_X2) / 2 - strlen(OVER) / 2, OVER);
                        break;
                }
                pstNew = (struct stNode *) malloc(sizeof(struct stNode));
                pstNew->x = iNextX;
                pstNew->y = iNextY;
                pstNew->shape = SNAKE_SHAPE;
                pstNew->next = NULL;
                gpstHead->next = pstNew;
                gpstHead = pstNew;
                vDrawOneNode(gpstHead, 1);
                if(!iEat(iNextX, iNextY))
                {
                        //vDrawOneNode(gpstHead, 1);
                        vDrawOneNode(gpstTail, 0);
                        pstNew = gpstTail;
                        gpstTail = pstNew->next;
                        free(pstNew);
                }
                sprintf(sPrompt, "Score:%7d Level:%2d", giScore, giLevel);
                printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
                           WIN_Y2, (WIN_X1 + WIN_X2) / 2 - strlen(sPrompt) / 2, sPrompt);
        }
        vKillSnake();
        vRestoreScreen();
        return 0;
}

我把楼主的代码带了一些注释,另外修改了两个小问题,
1.蛇路过的地方,会留下轨迹。2.游戏结束后会修改背景和字体的颜色

论坛徽章:
0
72 [报告]
发表于 2012-11-14 16:17 |只看该作者
/***snake.c***/
#include <stdio.h>
#include <malloc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <termio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define SNAKE_INITX 5
#define SNAKE_INITY 5
#define SNAKE_SHAPE '*'
#define SNAKE_INITLEN 8

#define WIN_X1 1
#define WIN_X2 80
#define WIN_Y1 1
#define WIN_Y2 24

#define MAX_LEVEL 20
#define MAX_INTER 200000
#define MIN_INTER 0
#define MAX_RICH 10
#define DEVRATE 5
#define OVER "Game Over!!!"

struct stNode {
        int x;
        int y;
        char shape;
        struct stNode *next;
};

struct stFood {
        int x;
        int y;
};

struct stNode *gpstHead, *gpstTail;
struct stFood gastFood[MAX_RICH];
int giLevel = 1;
int giRich = 1;
int giScore = 0;
int giLen = 0;

void settty(int iFlag)
{
        int fd;
        struct termio stTerm;

        if((fd = open(ttyname(1), O_RDWR)) == -1)        //ttyname()返回tty1的name  
                return;                                        //fd是打开tty1
        if(iFlag == 1)
        {
                ioctl(fd, TCGETA, &stTerm);        //获取tty1的状态
                stTerm.c_lflag &= ~ICANON;        //设置tty1的状态
                stTerm.c_lflag &= ~ECHO;
                stTerm.c_cc[4] = 1;
                stTerm.c_cc[5] = 0;
                stTerm.c_iflag &= ~ISTRIP;
                stTerm.c_cflag |= CS8;
                stTerm.c_cflag &= ~PARENB;
                ioctl(fd, TCSETA, &stTerm);
        } else
        {
                ioctl(fd, TCGETA, &stTerm);
                stTerm.c_lflag |= ICANON;
                stTerm.c_lflag |= ECHO;
                stTerm.c_cc[4] = 4;
                stTerm.c_cc[5] = 5;
                stTerm.c_iflag &= ~ISTRIP;
                stTerm.c_cflag |= CS8;
                stTerm.c_cflag &= ~PARENB;
                ioctl(fd, TCSETA, &stTerm);
        }
        close(fd);
}

//绘制蛇的节点
void vDrawOneNode(struct stNode *pstNode, int iFlag)
{
    if(iFlag == 1)
    {
            printf("\033[%dm\033[%d;%dm\033[%d;%dH%c",
                   iFlag,40, 33, pstNode->y, pstNode->x, pstNode->shape);
    }
    if(iFlag == 0)
    {
            printf("\033[%dm\033[%d;%dH%c",
                   iFlag, pstNode->y, pstNode->x, ' ');
    }
    //修改了蛇的运行轨迹BUG
        //printf("\033[%dm\033[%d;%dm\033[%d;%dH%c",
        //           iFlag,45 - iFlag * 5, 35 - iFlag * 2, pstNode->y, pstNode->x, pstNode->shape);
        fflush(stdout);
}

void vDrawOneFood(int x, int y)
{
        printf("\033[1m\033[40;36m\033[%d;%dH%c", y, x, '@');
        fflush(stdout);
}

int iGetDir(int iOriDir)
{
        fd_set rset;
        struct timeval hTmo;
        int iRet, iFlag = 0;
        char cCh;

        FD_ZERO(&rset);
        FD_SET(0, &rset);
        hTmo.tv_sec = 0;
        hTmo.tv_usec = MAX_INTER - (MAX_INTER - MIN_INTER) / MAX_LEVEL * giLevel;

        iRet = select(1, &rset, NULL, NULL, &hTmo);
        if(iRet <= 0)
        {
                return (iOriDir);
        }
        for (;;)
        {
                cCh = getchar();
                if(cCh != -1)
                {
                        switch (cCh)
                        {
                        case 27:
                        case 91:
                                iFlag++;
                                break;
                        case 65:                        //UP
                        case 66:                        //DOWN
                        case 67:                        //RIGHT
                        case 68:                        //LEFT
                                if(iFlag == 2)
                                        return ((!((cCh - 0x41) ^ iOriDir ^ 1)) ^ (cCh - 0x41));
                        default:
                                return (iOriDir);
                        }
                }
        }
}

void vInitScreen()
{
        settty(1);
        printf("\033[?25l\033[2J");        //隐藏光标和清屏
}

void vRestoreScreen()
{
    //修正了游戏结束时,屏幕显示的BUG
        //printf("\033[25;1H\033[0m\033[46;37m\033[?25h");
        printf("\033[25;1H\033[0m\033[?25h");
        settty(0);
}

void vDrawScope()
{
        int i, j;

        for (j = WIN_Y1; j <= WIN_Y2; j += WIN_Y2 - WIN_Y1)
        {
                printf("\033[%d;%dH+", j, WIN_X1);        //光标定位和答应每行开头的“+”号
                for (i = WIN_X1 + 1; i < WIN_X2; i++)
                        printf("-");                //打印每行中间的“-”
                printf("+");                        //打印每行末尾的“+”
        }
        for (i = WIN_Y1 + 1; i < WIN_Y2; i++)
                //将第二行到倒数第二行中间设置为空,同时开头和末尾设置为“|”
                //不明白为什么只有三个占位符,却又四个参数?
                printf("\033[%d;%dH|%*c|\n", i, WIN_X1, WIN_X2 - WIN_X1 - 1, ' ');
}

void vCreateSnake()
{
        struct stNode *pstNew;
        int i;

        gpstHead = (struct stNode *) malloc(sizeof(struct stNode));        //为蛇头开辟空间,同时初始化蛇头位置
        gpstHead->x = SNAKE_INITX;
        gpstHead->y = SNAKE_INITY;
        gpstHead->shape = SNAKE_SHAPE;
        gpstHead->next = NULL;
        vDrawOneNode(gpstHead, 1);        //绘制蛇头节点
        gpstTail = gpstHead;
        for (i = 1; i < SNAKE_INITLEN; i++)        //绘制其他蛇身节点
        {
                pstNew = (struct stNode *) malloc(sizeof(struct stNode));
                pstNew->x = gpstHead->x + 1;
                pstNew->y = gpstHead->y;
                pstNew->shape = SNAKE_SHAPE;
                pstNew->next = NULL;
                vDrawOneNode(pstNew, 1);
                gpstHead->next = pstNew;
                gpstHead = pstNew;
        }
        return;
}

void vKillSnake()
{
        struct stNode *pstNode;

        for (pstNode = gpstTail; gpstTail != NULL;)
        {
                gpstTail = pstNode->next;
                free(pstNode);
                pstNode = gpstTail;
        }
}

void vGenFood(int iIdx)
{
        struct stNode *pstNode;
        int i, iFound = 0;

        for (; !iFound;)
        {
                iFound = 1;
                gastFood[iIdx].x = rand() % (WIN_X2 - WIN_X1 - 1) + WIN_X1 + 1;
                gastFood[iIdx].y = rand() % (WIN_Y2 - WIN_Y1 - 1) + WIN_Y1 + 1;
                for (i = 0; i < giRich; i++)
                {
                        if(i != iIdx && gastFood[iIdx].x == gastFood[i].x &&
                           gastFood[iIdx].y == gastFood[i].y)
                        {
                                iFound = 0;
                                break;
                        }
                }
                if(!iFound)
                        continue;
                for (pstNode = gpstTail; pstNode != NULL; pstNode = pstNode->next)
                {
                        if(gastFood[iIdx].x == pstNode->x && gastFood[iIdx].y == pstNode->y)
                        {
                                iFound = 0;
                                break;
                        }
                }
                if(!iFound)
                        continue;
        }
        vDrawOneFood(gastFood[iIdx].x, gastFood[iIdx].y);
}

void vInitFood()
{
        int i;

        srand(getpid());
        for (i = 0; i < giRich; i++)
                vGenFood(i);
}

int iIsValid(int x, int y)
{
        struct stNode *pstNode;

        if(x <= WIN_X1 || x >= WIN_X2 || y <= WIN_Y1 || y >= WIN_Y2)
                return (0);
        pstNode = gpstTail;
        for (; pstNode != NULL;)
        {
                if(x == pstNode->x && y == pstNode->y)
                        return (0);
                pstNode = pstNode->next;
        }
        return (1);
}

int iEat(int x, int y)
{
        int i;

        for (i = 0; i < giRich; i++)
        {
                if(x == gastFood[i].x && y == gastFood[i].y)
                {
                        vGenFood(i);
                        giScore += giLevel * 10;
                        giLen++;
                        if(giLevel < MAX_LEVEL)
                                if(giLen % DEVRATE == 0)
                                        giLevel++;
                        return (1);
                }
        }
        return (0);
}

int main(void)
{
        int iDir = 2, iNextX, iNextY;
        struct stNode *pstNew;
        char sPrompt[80];

        vInitScreen();                                //初始化tty1和清屏
        vDrawScope();                                //绘制外围边框
        vCreateSnake();                                //创建蛇的原型
        vInitFood();                                //初始化食物
        for (;;)
        {
                iDir = iGetDir(iDir);
                iNextX = gpstHead->x + (iDir >> 1) * (5 - (iDir << 1));
                iNextY = gpstHead->y - (!(iDir >> 1)) * (1 - (iDir << 1));
                if(!iIsValid(iNextX, iNextY))
                {
                        printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
                                   WIN_Y2 - 1, (WIN_X1 + WIN_X2) / 2 - strlen(OVER) / 2, OVER);
                        break;
                }
                pstNew = (struct stNode *) malloc(sizeof(struct stNode));
                pstNew->x = iNextX;
                pstNew->y = iNextY;
                pstNew->shape = SNAKE_SHAPE;
                pstNew->next = NULL;
                gpstHead->next = pstNew;
                gpstHead = pstNew;
                vDrawOneNode(gpstHead, 1);
                if(!iEat(iNextX, iNextY))
                {
                        //vDrawOneNode(gpstHead, 1);
                        vDrawOneNode(gpstTail, 0);
                        pstNew = gpstTail;
                        gpstTail = pstNew->next;
                        free(pstNew);
                }
                sprintf(sPrompt, "Score:%7d Level:%2d", giScore, giLevel);
                printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
                           WIN_Y2, (WIN_X1 + WIN_X2) / 2 - strlen(sPrompt) / 2, sPrompt);
        }
        vKillSnake();
        vRestoreScreen();
        return 0;
}

上面不知道为什么有表情

论坛徽章:
0
73 [报告]
发表于 2012-11-16 00:00 |只看该作者
学习下……

论坛徽章:
0
74 [报告]
发表于 2013-03-02 16:12 |只看该作者
还不错,不该不是linux下的

论坛徽章:
0
75 [报告]
发表于 2013-03-28 19:39 |只看该作者
我试着在redhat 下编译了一把,贴上源代码,解释权归楼主哈。

  1. /***snake.c***/
  2. #include <stdio.h>
  3. #include <malloc.h>
  4. #include <sys/time.h>
  5. #include <sys/types.h>
  6. #include <sys/select.h>
  7. #include <termio.h>
  8. #include <fcntl.h>
  9. #include <sys/stat.h>
  10. #include <unistd.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #define SNAKE_INITX 5
  14. #define SNAKE_INITY 5
  15. #define SNAKE_SHAPE '*'
  16. #define SNAKE_INITLEN 8

  17. #define WIN_X1 1
  18. #define WIN_X2 80
  19. #define WIN_Y1 1
  20. #define WIN_Y2 24

  21. #define MAX_LEVEL 20
  22. #define MAX_INTER 200000
  23. #define MIN_INTER 0
  24. #define MAX_RICH 10
  25. #define DEVRATE 5
  26. #define OVER "Game Over!!!"

  27. struct stNode
  28. {
  29.         int x;
  30.         int y;
  31.         char shape;
  32.         struct stNode *next;
  33. };

  34. struct stFood
  35. {
  36.         int x;
  37.         int y;
  38. };

  39. struct stNode *gpstHead,*gpstTail;
  40. struct stFood gastFood[MAX_RICH];
  41. int giLevel=1;
  42. int giRich=1;
  43. int giScore=0;
  44. int giLen=0;

  45. void settty(int iFlag)
  46. {
  47.         int fd;
  48.         struct termio stTerm;

  49.         if((fd = open(ttyname(1),O_RDWR))==-1)        return;
  50.         if(iFlag == 1)
  51.         {
  52.                 ioctl(fd,TCGETA,&stTerm);
  53.                 stTerm.c_lflag &= ~ICANON;
  54.                 stTerm.c_lflag &= ~ECHO;
  55.                 stTerm.c_cc[4] = 1;
  56.                 stTerm.c_cc[5] = 0;
  57.                 stTerm.c_iflag &= ~ISTRIP;
  58.                 stTerm.c_cflag |= CS8;
  59.                 stTerm.c_cflag &= ~PARENB;
  60.                 ioctl(fd,TCSETA,&stTerm);
  61.         }
  62.         else
  63.         {
  64.                 ioctl(fd,TCGETA,&stTerm);
  65.                 stTerm.c_lflag |= ICANON;
  66.                 stTerm.c_lflag |= ECHO;
  67.                 stTerm.c_cc[4] = 4;
  68.                 stTerm.c_cc[5] = 5;
  69.                 stTerm.c_iflag &= ~ISTRIP;
  70.                 stTerm.c_cflag |= CS8;
  71.                 stTerm.c_cflag &= ~PARENB;
  72.                 ioctl(fd,TCSETA,&stTerm);
  73.         }
  74.         close(fd);
  75. }

  76. void vDrawOneNode(struct stNode *pstNode,int iFlag)
  77. {
  78.         printf("\033[%dm\033[40;%dm\033[%d;%d;H%c",
  79.                 iFlag,iFlag*3+30,pstNode->y,pstNode->x,pstNode->shape);
  80.         fflush(stdout);
  81. }

  82. void vDrawOneFood(int x,int y)
  83. {
  84.         printf("\033[1m\033[40;36m\033[%d;%d;H%c",y,x,'@');
  85.         fflush(stdout);
  86. }

  87. int iGetDir(int iOriDir)
  88. {
  89.         fd_set rset;
  90.         struct        timeval        hTmo;
  91.         int iRet,iFlag=0;
  92.         char cCh;

  93.         FD_ZERO(&rset);
  94.         FD_SET(0,&rset);
  95.         hTmo.tv_sec=0;
  96.         hTmo.tv_usec=MAX_INTER-(MAX_INTER-MIN_INTER)/MAX_LEVEL*giLevel;

  97.         iRet=select(1,&rset,NULL,NULL,&hTmo);
  98.         if(iRet<=0)
  99.         {
  100.                 return(iOriDir);
  101.         }
  102.         for(;;)
  103.         {
  104.                 cCh=getchar();
  105.                 if(cCh != -1)
  106.                 {
  107.                         switch(cCh)
  108.                         {         
  109.                         case 27  :
  110.                         case 91  :
  111.                                 iFlag++;
  112.                                 break;
  113.                         case 65  ://UP
  114.                         case 66 ://DOWN
  115.                         case 67  ://RIGHT
  116.                         case 68 ://LEFT
  117.                         if(iFlag==2)
  118.                                 return((!((cCh-0x41)^iOriDir^1))^(cCh-0x41));
  119.                         default  :
  120.                                 return(iOriDir);
  121.                         }
  122.                 }
  123.         }
  124. }
  125. void vInitScreen()
  126. {
  127.         settty(1);
  128.         printf("\033[?25l\033[2J");
  129. }

  130. void vRestoreScreen()
  131. {
  132.         printf("\033[24;1H\033[1m\033[40;34m\033[?25h");
  133.         settty(0);
  134. }

  135. void vDrawScope()
  136. {
  137.         int i,j;
  138.         
  139.         for(j=WIN_Y1;j<=WIN_Y2;j+=WIN_Y2-WIN_Y1)
  140.         {
  141.                 printf("\033[%d;%dH+",j,WIN_X1);
  142.                 for(i=WIN_X1+1;i<WIN_X2;i++)
  143.                         printf("-");
  144.                 printf("+");
  145.         }
  146.         for(i=WIN_Y1+1;i<WIN_Y2;i++)
  147.                 printf("\033[%d;%dH|%*c|\n",i,WIN_X1,WIN_X2-WIN_X1-1,' ');
  148. }

  149. void vCreateSnake()
  150. {
  151.         struct stNode *pstNew;
  152.         int i;

  153.         gpstHead=(struct stNode*)malloc(sizeof(struct stNode));
  154.         gpstHead->x=SNAKE_INITX;        
  155.         gpstHead->y=SNAKE_INITY;
  156.         gpstHead->shape=SNAKE_SHAPE;
  157.         gpstHead->next=NULL;
  158.         vDrawOneNode(gpstHead,1);
  159.         gpstTail=gpstHead;
  160.         for(i=1;i<SNAKE_INITLEN;i++)
  161.         {
  162.                 pstNew=(struct stNode*)malloc(sizeof(struct stNode));
  163.                 pstNew->x=gpstHead->x+1;        
  164.                 pstNew->y=gpstHead->y;
  165.                 pstNew->shape=SNAKE_SHAPE;
  166.                 pstNew->next=NULL;
  167.                 vDrawOneNode(pstNew,1);
  168.                 gpstHead->next=pstNew;
  169.                 gpstHead=pstNew;
  170.         }
  171.         return;
  172. }

  173. void vKillSnake()
  174. {
  175.         struct stNode *pstNode;

  176.         for(pstNode=gpstTail;gpstTail!=NULL;)
  177.         {
  178.                 gpstTail=pstNode->next;
  179.                 free(pstNode);
  180.                 pstNode=gpstTail;
  181.         }
  182. }

  183. void vGenFood(int iIdx)
  184. {
  185.         struct stNode *pstNode;
  186.         int i,iFound=0;
  187.         
  188.         for(;!iFound;)
  189.         {
  190.                 iFound=1;
  191.                 gastFood[iIdx].x=rand()%(WIN_X2-WIN_X1-1)+WIN_X1+1;
  192.                 gastFood[iIdx].y=rand()%(WIN_Y2-WIN_Y1-1)+WIN_Y1+1;
  193.                 for(i=0;i<giRich;i++)
  194.                 {
  195.                         if(i!=iIdx && gastFood[iIdx].x==gastFood[i].x &&
  196.                                 gastFood[iIdx].y==gastFood[i].y)
  197.                         {
  198.                                 iFound=0;
  199.                                 break;
  200.                         }
  201.                 }
  202.                 if(!iFound) continue;
  203.                 for(pstNode=gpstTail;pstNode!=NULL;pstNode=pstNode->next)
  204.                 {
  205.                         if(gastFood[iIdx].x==pstNode->x &&
  206.                                 gastFood[iIdx].y==pstNode->y)
  207.                         {
  208.                                 iFound=0;
  209.                                 break;
  210.                         }
  211.                 }
  212.                 if(!iFound) continue;
  213.         }
  214.         vDrawOneFood(gastFood[iIdx].x,gastFood[iIdx].y);
  215. }

  216. void vInitFood()
  217. {
  218.         int i;
  219.         
  220.         srand(getpid());
  221.         for(i=0;i<giRich;i++)        vGenFood(i);
  222. }
  223.         
  224. int iIsValid(int x,int y)
  225. {
  226.         struct stNode *pstNode;

  227.         if(x<=WIN_X1 || x>=WIN_X2 || y<=WIN_Y1 || y>=WIN_Y2)
  228.                 return(0);
  229.         pstNode=gpstTail;
  230.         for(;pstNode!=NULL;)
  231.         {
  232.                 if(x==pstNode->x && y==pstNode->y)
  233.                         return(0);
  234.                 pstNode=pstNode->next;
  235.         }
  236.         return(1);
  237. }

  238. int iEat(int x,int y)
  239. {
  240.         int i,j;
  241.         
  242.         for(i=0;i<giRich;i++)
  243.         {
  244.                 if(x==gastFood[i].x && y==gastFood[i].y)
  245.                 {
  246.                         vGenFood(i);
  247.                         giScore+=giLevel*10;
  248.                         giLen++;
  249.                         if(giLevel<MAX_LEVEL)
  250.                                 if(giLen%DEVRATE==0)
  251.                                         giLevel++;
  252.                         return(1);
  253.                 }
  254.         }
  255.         return(0);
  256. }
  257. main()
  258. {
  259.         int iDir=2,iNextX,iNextY;
  260.         struct stNode *pstNew;
  261.         char sPrompt[80];
  262.         
  263.         vInitScreen();
  264.         vDrawScope();
  265.         vCreateSnake();
  266.         vInitFood();
  267.         for(;;)
  268.         {
  269.                 iDir=iGetDir(iDir);
  270.                 iNextX=gpstHead->x+(iDir>>1)*(5-(iDir<<1));
  271.                 iNextY=gpstHead->y-(!(iDir>>1))*(1-(iDir<<1));
  272.                 if(!iIsValid(iNextX,iNextY))
  273.                 {
  274.                         printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
  275.                                 WIN_Y2-1,(WIN_X1+WIN_X2)/2-strlen(OVER)/2,OVER);
  276.                         break;
  277.                 }
  278.                 pstNew=(struct stNode*)malloc(sizeof(struct stNode));
  279.                 pstNew->x=iNextX;
  280.                 pstNew->y=iNextY;
  281.                 pstNew->shape=SNAKE_SHAPE;
  282.                 pstNew->next=NULL;
  283.                 gpstHead->next=pstNew;
  284.                 gpstHead=pstNew;
  285.                 vDrawOneNode(gpstHead,1);
  286.                 if(!iEat(iNextX,iNextY))
  287.                 {
  288.                         vDrawOneNode(gpstHead,1);
  289.                         vDrawOneNode(gpstTail,0);
  290.                         pstNew=gpstTail;
  291.                         gpstTail=pstNew->next;
  292.                         free(pstNew);
  293.                 }
  294.                 sprintf(sPrompt,"Score:%7d Level:%2d",giScore,giLevel);
  295.                 printf("\033[%d;%dH\033[1m\033[40;34m%s\033[0m",
  296.                         WIN_Y2,(WIN_X1+WIN_X2)/2-strlen(sPrompt)/2,sPrompt);
  297.         }
  298.         vKillSnake();
  299.         vRestoreScreen();
  300. }
复制代码

论坛徽章:
0
76 [报告]
发表于 2013-03-30 11:33 |只看该作者
不错呀。对新手来说真的是不错

论坛徽章:
0
77 [报告]
发表于 2013-08-01 10:32 |只看该作者
Linux 下可以跑吗?

论坛徽章:
0
78 [报告]
发表于 2013-08-16 17:31 |只看该作者

论坛徽章:
0
79 [报告]
发表于 2013-08-16 17:33 |只看该作者
回复 77# myzonesky


    看截图~

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
80 [报告]
发表于 2013-10-14 16:38 |只看该作者
在AIX下。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP