貪吃蛇示例

最近在瞭解ncurses這個字符終端處理庫,使用這個庫寫了一個簡單的貪吃蛇遊戲w,s,a,d控制上下左右,代碼如下:


<code>#include #include #include #include #include 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; }/<code>