简易贪食蛇C语言

时间:2021-11-04 10:29:37
#ifndef __SNAKE_H_ 

#define __SNAKE_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h> //linux线程,编译文件需链接 -lpthread
#include <time.h>


#define MAX     100//最大长度

#define W       40 //游戏界面宽
#define H       20 //游戏界面高
#define HEAD     '@' //头形状
#define FOOD     'o' //食物和身体形状
#define TAIL    '*' //尾巴形状


#define UP       1 //方向
#define DOWN     2
#define LEFT     3
#define RIGHT   4


char board[W][H] = {}; //游戏界面用二维数组表示


struct node_t { //每个节点信息
    int x;//x坐标
    int y;//y坐标
    struct node_t *next;
    struct node_t *prev;
};


struct snake_t { //创建贪食蛇链表信息
    int num; //目前蛇的长度
    int speed; //行走速度
    int step; //步长
    int dir; //方向
    int quit; //游戏结束标志位
    struct node_t *head; //定义指向蛇头指针
    struct node_t *tail; //定义指向蛇尾指针
};


struct snake_t *snake_init(int x, int y, int speed); //初始化
void *snake_run(void *arg); //运行函数
void snake_del(struct snake_t *snake); //链表销毁函数


#endif

====================================================================================================================================

#include "snake.h"


struct snake_t *snake_init(int x, int y, int speed)
{
    struct snake_t *snake = NULL;
    struct node_t *new = NULL;


    snake = (struct snake_t *)malloc(sizeof(struct snake_t));
    new = (struct node_t *)malloc(sizeof(struct node_t));


    new->x = x;
    new->y = y;
    new->next = NULL;
    new->prev = NULL;
    snake->head = new;
    snake->tail = new;


    snake->speed = speed;
    snake->num = 0;
    snake->step = 1;
    snake->dir = 0;
    snake->quit = 0;


    return snake;
}

/*添加一个节点*/
void add_node(struct snake_t **snake, int x, int y)
{
    struct node_t *new = NULL;


    new = (struct node_t *)malloc(sizeof(struct node_t));
    new->x = x;
    new->y = y;
    (*snake)->num++;


    new->next = NULL;
    new->prev = (*snake)->head;
    (*snake)->head->next = new;
    (*snake)->head = new;
}

/*画游戏界面*/
void drawboard(struct snake_t *snake)
{
    int i, j;
    struct node_t *tail = NULL;


        printf("\033[1;1H\033[2J"); //linux系统终端VT码,实现定位,清屏
        for (tail = snake->head; tail != NULL; tail = tail->prev)
        {
            if (tail == snake->head)
                board[tail->x][tail->y] = HEAD;
            else if (tail == snake->tail)
                board[tail->x][tail->y] = TAIL;
            else
                board[tail->x][tail->y] = FOOD;
        }
        for (j = 1; j <= H; j++)
        {
            for (i = 1; i <= W; i++)
            {
                if (i == 1 || i == W || j == 1 || j == H)
                    printf("#");
                else if (board[i][j] == 1)
                    printf("o");
                else if (board[i][j] == 0)
                    printf(" ");
                else
                    printf("%c", board[i][j]);
            }
            printf("\n");
        }
}

/*随机一个坐标*/
void food(void)
{
    int x, y;


    srand(time(NULL));
RAND:
    x = rand() % (W - 2) + 2;
    y = rand() % (H - 2) + 2;
    if (board[x][y] == HEAD || board[x][y] == FOOD || board[x][y] == TAIL)
        goto RAND;


    board[x][y] = 1;
}

/*检测目前界面中有无食物,没有随机放置*/
int set_food(void)
{
    int i, j;


    for (i = 1; i <= W; i++)
    {
        for (j = 1; j <= H; j++)
        {
            if (board[i][j] == 1)
                return 0;
        }
    }
    food();


    return 0;
}


/*移动*/
void move(struct snake_t *snake, int dir)
{
    struct node_t *tail = snake->tail;


    board[tail->x][tail->y] = 0;


    for (tail = snake->tail; tail != NULL; tail = tail->next)
    {
        if (tail == snake->head && dir != 0)
        {
            if (dir == LEFT || dir == RIGHT)
            {
                tail->x += snake->step;
                if (board[tail->x + snake->step][tail->y] == 1)
                {
                    add_node(&snake, tail->x + snake->step, tail->y);
                    board[tail->x + snake->step][tail->y] = 0;
                }
                else if ((board[tail->x][tail->y + snake->step] == 1 || board[tail->x][tail->y - snake->step] == 1)
                            && (dir == UP || dir == DOWN))
                {
                    add_node(&snake, tail->x + snake->step, tail->y);
                    board[tail->x + snake->step][tail->y] = 0;
                }
            }


            else if (dir == UP || dir == DOWN)
            {
                tail->y += snake->step;
                if (board[tail->x][tail->y + snake->step] == 1)
                {
                    add_node(&snake, tail->x, tail->y + snake->step);
                    board[tail->x][tail->y + snake->step] = 0;
                }
            }
        }


        else 
        {
            if (dir != 0)
            {
                tail->x = tail->next->x;
                tail->y = tail->next->y;
            }
        }
    }
}

/*获取按键信息*/
int getInput(void)
{
    char ch[8];
    int ret;


    ret = read(0, ch, 8);


    if (ret == 1)
        return ch[0];
    else if (ret == 3 && ch[0] == 27 && ch[1] == 91)
        return ch[2] + 127;


    return -1;
}


/*按键处理*/
void *key_handler(void *arg)
{
    char ch;
    struct node_t *tail = NULL;
    struct snake_t *snake = (struct snake_t *)arg;


    while (1)
    {
        ch = getchar();
        switch (ch)
        {
            case 'h':
                if (snake->dir != RIGHT)
                {
                    snake->step = -1;
                    snake->dir = LEFT;
                }
                break;
            case 'l':
                if (snake->dir != LEFT)
                {
                    snake->step = 1;
                    snake->dir = RIGHT;
                }
                break;
            case 'j':
                if (snake->dir != UP)
                {
                    snake->step = 1;
                    snake->dir = DOWN;
                }
                break;
            case 'k':
                if (snake->dir != DOWN)
                {
                    snake->step = -1;
                    snake->dir = UP;
                }
                break;
            case 'q':
                snake->quit = 1;
        }
    usleep(1000);
    }
}

/*检测游戏运行状态*/
void dead_check(void *arg)
{
    struct snake_t *snake = (struct snake_t *)arg;
    struct node_t *tail = NULL;


    if (snake->head->x <= 1 || snake->head->x >= W || snake->head->y >= H || snake->head->y <= 1)
    {
        printf("\033[11;60H GAME OVER!\n");
        snake->quit = 1;
        return;
    }
    else
    {
        for (tail = snake->tail; tail != snake->head; tail = tail->next)
        {
            if ((tail->x == snake->head->x) && (tail->y == snake->head->y))
            {
                printf("\033[11;60H GAME OVER!\n");
                snake->quit = 1;
                return;
            }
        }
    }
}


void *snake_run(void *arg)
{
    struct snake_t *snake = (struct snake_t *)arg;


    while (1)
    {
        set_food();
        move(snake, snake->dir);
        drawboard(snake);
        printf("\033[10;60H Score: %d\n", snake->num);

        usleep(snake->speed);
    }
}


void snake_del(struct snake_t *snake)
{
    struct node_t *tail = NULL;


    for (tail = snake->head; tail != NULL; tail = tail->prev)
        free(tail);
    free(snake);
}


int main(void)
{
    struct snake_t *snake = NULL; 
    pthread_t tid, tid1;
    char ch, flag = 0;

    system("stty -echo -icanon");
    snake = snake_init(W / 2, H / 2, 400000);
    pthread_create(&tid, NULL, snake_run, snake);
    pthread_create(&tid1, NULL, key_handler, snake);


    while (!snake->quit)
    {
        dead_check(snake);
        if ((snake->num > 0) && (flag == 0) && (snake->num % 10 == 0))
        {
            snake->speed = snake->speed * 4 / 5;
            flag = 1;
        }
        else
            flag = 0;

        if (snake->num == MAX)
            printf("\033[11;60H YOU WIN\n");


        usleep(10000);
    }
    printf("\033[%d;1H", H + 1);
    snake_del(snake);

    system("stty echo icanon");

    return 0;
}