Linux環境下C語言實現貪吃蛇游戲
Linux環境下C語言實現貪吃蛇游戲
[liul@test snake]$ more snake.cinclude <stdio.h>
include <stdlib.h>
include <curses.h>
include <signal.h>
include <sys/time.h>
define NUM 60
struct direct //用來表示方向的 { int cx; int cy; }; typedef struct node //鏈表的結點 { int cx; int cy; struct node back; struct node next; }node;
void initGame(); //初始化游戲 int setTicker(int); //設置計時器 void show(); //顯示整個畫面 void showInformation(); //顯示游戲信息(前兩行) void showSnake(); //顯示蛇的身體 void getOrder(); //從鍵盤中獲取命令 void over(int i); //完成游戲結束后的提示信息
void creatLink(); //(帶頭尾結點)雙向鏈表以及它的操作 void insertNode(int x, int y);
void deleteNode(); void deleteLink();int ch; //輸入的命令 int hour, minute, second; //時分秒 int length, tTime, level; //(蛇的)長度,計時器,(游戲)等級 struct direct dir, food; //蛇的前進方向,食物的位置 node head, tail; //鏈表的頭尾結點
int main() { initscr(); [liul@test snake]$ more snake.c
include <stdio.h>
include <stdlib.h>
include <curses.h>
include <signal.h>
include <sys/time.h>
define NUM 60
struct direct //用來表示方向的 { int cx; int cy; }; typedef struct node //鏈表的結點 { int cx; int cy; struct node back; struct node next; }node;
void initGame(); //初始化游戲 int setTicker(int); //設置計時器 void show(); //顯示整個畫面 void showInformation(); //顯示游戲信息(前兩行) void showSnake(); //顯示蛇的身體 void getOrder(); //從鍵盤中獲取命令 void over(int i); //完成游戲結束后的提示信息
void creatLink(); //(帶頭尾結點)雙向鏈表以及它的操作 void insertNode(int x, int y);
void deleteNode(); void deleteLink();int ch; //輸入的命令 int hour, minute, second; //時分秒 int length, tTime, level; //(蛇的)長度,計時器,(游戲)等級 struct direct dir, food; //蛇的前進方向,食物的位置 node head, tail; //鏈表的頭尾結點
int main() { initscr(); initGame(); signal(SIGALRM, show); getOrder(); endwin(); return 0; }
void initGame() { cbreak(); //把終端的CBREAK模式打開 noecho(); //關閉回顯 curs_set(0); //把光標置為不可見 keypad(stdscr, true); //使用用戶終端的鍵盤上的小鍵盤 srand(time(0)); //設置隨機數種子 //初始化各項數據 hour = minute = second = tTime = 0; length = 1; dir.cx = 1; dir.cy = 0; ch = 'A'; food.cx = rand() % COLS; food.cy = rand() % (LINES-2) + 2; creatLink(); setTicker(20); }
//設置計時器(這個函數是書本上的例子,有改動) int setTicker(int n_msecs) { struct itimerval new_timeset; long n_sec, n_usecs;
n_sec = n_msecs / 1000 ; n_usecs = ( n_msecs % 1000 ) * 1000L ; new_timeset.it_interval.tv_sec = n_sec; new_timeset.it_interval.tv_usec = n_usecs; n_msecs = 1; n_sec = n_msecs / 1000 ; n_usecs = ( n_msecs % 1000 ) * 1000L ; new_timeset.it_value.tv_sec = n_sec ; new_timeset.it_value.tv_usec = n_usecs ; return setitimer(ITIMER_REAL, &new_timeset, NULL);
}
void showInformation() { tTime++; if(tTime >= 1000000) // tTime = 0; if(1 != tTime % 50) return; move(0, 3);
//顯示時間 printw("time: %d:%d:%d %c", hour, minute, second); second++; if(second > NUM) { second = 0; minute++; } if(minute > NUM) { minute = 0; hour++; } //顯示長度,等級 move(1, 0); int i; for(i=0;i<COLS;i++) addstr("-"); move(0, COLS/2-5); printw("length: %d", length); move(0, COLS-10); level = length / 3 + 1; printw("level: %d", level); }//蛇的表示是用一個帶頭尾結點的雙向鏈表來表示的, //蛇的每一次前進,都是在鏈表的頭部增加一個節點,在尾部刪除一個節點 //如果蛇吃了一個食物,那就不用刪除節點了 void showSnake() { if(1 != tTime % (30-level)) return; //判斷蛇的長度有沒有改變 bool lenChange = false; //顯示食物 move(food.cy, food.cx); printw("@"); //如果蛇碰到墻,則游戲結束 if((COLS-1==head->next->cx && 1==dir.cx) || (0==head->next->cx && -1==dir.cx) || (LINES-1==head->next->cy && 1==dir.cy) || (2==head->next->cy && -1==dir.cy)) { over(1); return; } //如果蛇頭砬到自己的身體,則游戲結束 if('' == mvinch(head->next->cy+dir.cy, head->next->cx+dir.cx) ) { over(2); return; } insertNode(head->next->cx+dir.cx, head->next->cy+dir.cy); //蛇吃了一個“食物” if(head->next->cx==food.cx && head->next->cy==food.cy) { lenChange = true; length++; //恭喜你,通關了 if(length >= 50) { over(3); return; } //重新設置食物的位置 food.cx = rand() % COLS; food.cy = rand() % (LINES-2) + 2; } if(!lenChange) { move(tail->back->cy, tail->back->cx); printw(" "); deleteNode(); } move(head->next->cy, head->next->cx); printw(""); }
void show() { signal(SIGALRM, show); //設置中斷信號 showInformation(); showSnake(); refresh(); //刷新真實屏幕 }
void getOrder() { //建立一個死循環,來讀取來自鍵盤的命令 while(1) { ch = getch(); if(KEY_LEFT == ch) { dir.cx = -1; dir.cy = 0; } else if(KEY_UP == ch) { dir.cx = 0; dir.cy = -1; } else if(KEY_RIGHT == ch) { dir.cx = 1; dir.cy = 0; } else if(KEY_DOWN == ch) { dir.cx = 0; dir.cy = 1; } setTicker(20); } }
void over(int i) { //顯示結束原因 move(0, 0); int j; for(j=0;j<COLS;j++) addstr(" "); move(0, 2); if(1 == i) addstr("Crash the wall. Game over"); else if(2 == i) addstr("Crash itself. Game over"); else if(3 == i) addstr("Mission Complete"); setTicker(0); //關閉計時器 deleteLink(); //釋放鏈表的空間 }
//創建一個雙向鏈表 void creatLink() { node temp = (node )malloc( sizeof(node) ); head = (node )malloc( sizeof(node) ); tail = (node )malloc( sizeof(node) ); temp->cx = 5; temp->cy = 10; head->back = tail->next = NULL; head->next = temp; temp->next = tail; tail->back = temp; temp->back = head; }
//在鏈表的頭部(非頭結點)插入一個結點 void insertNode(int x, int y) { node temp = (node )malloc( sizeof(node) ); temp->cx = x; temp->cy = y; temp->next = head->next; head->next = temp; temp->back = head; temp->next->back = temp; }
//刪除鏈表的(非尾結點的)最后一個結點 void deleteNode() { node temp = tail->back; node bTemp = temp->back; bTemp->next = tail; tail->back = bTemp; temp->next = temp->back = NULL; free(temp); temp = NULL; }
//刪除整個鏈表 void deleteLink() { while(head->next != tail) deleteNode(); head->next = tail->back = NULL; free(head); free(tail); } </pre>
運行[liul@test snake]$ [liul@test snake]$ gcc snake.c -lcurses -o snake [liul@test snake]$ ./snake