1.最近在了解ncurses这个字符终端处理库,使用这个库写了一个简单的贪吃蛇游戏w,s,a,d控制上下左右,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ncurses.h>
typedef struct _tagDirect
{
int x;
int y;
}Direct;
typedef struct _tagSnakeNode
{
int x;
int y;
struct _tagSnakeNode* pre;
struct _tagSnakeNode* next;
}SnakeNode,Snake;
static Direct dir;
static int fx;
static int fy;
static int length = 0;
static Snake* SnakeInit()
{
SnakeNode* sn = (SnakeNode*)malloc(sizeof(SnakeNode));
if (sn == NULL)
{
return NULL;
}
memset(sn,0,sizeof(SnakeNode));
sn->next = sn->pre = sn;
return sn;
}
//add head pos
static int SnakeInsert(Snake* sn,int x,int y)
{
if (sn == NULL)
{
return -1;
}
SnakeNode* node = (SnakeNode*)malloc(sizeof(SnakeNode));
if (node == NULL)
{
return -2;
}
node->x = x;
node->y = y;
node->next = sn->next;
sn->next->pre = node;
sn->next = node;
node->pre = sn;
return 0;
}
//del tail pos
static int SnakeDelete(Snake* sn)
{
if (sn == NULL)
{
return -1;
}
SnakeNode* tail = sn->pre;
tail->pre->next = sn;
sn->pre = tail->pre;
free(tail);
tail = NULL;
return 0;
}
static void SnakeDeinit(Snake* sn)
{
if (sn == NULL)
{
return;
}
SnakeNode* p = sn->next;
SnakeNode* tmp = NULL;
while(p && p->next != sn)
{
tmp = p;
p = p->next;
free(tmp);
tmp = NULL;
}
free(sn);
sn = NULL;
}
static void MakeFood()
{
int x = rand()%COLS;
if(x == 0)
x = 1;
int y = rand()%(LINES-2);
if (y == 0)
y = 1;
move(y,x);
printw("O");
fx = x;
fy = y;
}
//蛇的每一次前进,在链表的头部增加一个节点,在尾部删除一个节点
//如果蛇吃了一个食物,就不用删除节点了
static int SnakeShow(Snake* sn)
{
int isEat = 0;
if (sn == NULL)
{
return -1;
}
move(fy,fx);
printw("O");
if(sn->next->x+dir.x == COLS || sn->next->x+dir.x == 0 ||
sn->next->y+dir.y == LINES || sn->next->y+dir.y == -1)
{
move(LINES/2,COLS/2);
addstr("crash the wall,game over!");
refresh();
return -2;
}
//如果蛇头砬到自己的身体,则游戏结束
if('@' == mvinch(sn->next->y+dir.y, sn->next->x+dir.x) )
{
move(LINES/2,COLS/2);
addstr("crash itself,game over!");
refresh();
return -3;
}
SnakeInsert(sn,sn->next->x+dir.x,sn->next->y+dir.y);
if(sn->next->x == fx && sn->next->y == fy)
{
isEat = 1;
MakeFood();
length++;
if(length == 20)
{
move(LINES/2,COLS/2);
addstr("you are win!");
refresh();
return 1;
}
}
if(isEat == 0)
{
move(sn->pre->y,sn->pre->x);
printw(" ");
SnakeDelete(sn);
}
move(sn->next->y,sn->next->x);
printw("@");
refresh();
return 0;
}
static int UpdateDirect(char ch)
{
if('a' == ch)
{
if(dir.x == 1)
return 0;
dir.x = -1;
dir.y = 0;
}
else if('w' == ch)
{
if(dir.y == 1)
return 0;
dir.x = 0;
dir.y = -1;
}
else if('d' == ch)
{
if(dir.x == -1)
return 0;
dir.x = 1;
dir.y = 0;
}
else if('s' == ch)
{
if(dir.y == -1)
return 0;
dir.x = 0;
dir.y = 1;
}
else if('q' == ch)
{
return 1;
}
return 0;
}
int main(int argc, char const *argv[])
{
/* code */
char c = 0;
int ret = 0;
struct timeval timeout;
initscr();
cbreak(); //把终端的CBREAK模式打开
noecho(); //关闭回显
curs_set(0); //把光标置为不可见
srand(time(NULL)); //seed
Snake* sn = SnakeInit();
if (sn == NULL)
{
return -1;
}
SnakeInsert(sn,10,20);
MakeFood();
dir.x = 1;
dir.y = 0;
for(;;)
{
fd_set rdfds;
FD_ZERO(&rdfds);
FD_SET(0,&rdfds); //input
timeout.tv_sec = 0;
timeout.tv_usec = 500000; //500ms
ret = select(1,&rdfds,NULL,NULL,&timeout);
if (ret < 0)
{
continue;
}
if(FD_ISSET(0,&rdfds))
{
fread(&c,1,1,stdin);
// fprintf(stderr,"have %02x\n",c);
if(UpdateDirect(c) == 1)
{
move(LINES/2,COLS/2);
addstr("quit!");
refresh();
break;
}
}
// main loop
if((ret = SnakeShow(sn)) < 0)
break;
if(ret == 1)
break;
move(0,(COLS-strlen("SCORE:XX"))/2);
printw("SCORE:%02d",length);
refresh();
}
SnakeDeinit(sn);
getch();
endwin();
return 0;
}