#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;
}