Linux環境下C語言實現貪吃蛇游戲

jopen 9年前發布 | 3K 次閱讀 C/C++

Linux環境下C語言實現貪吃蛇游戲

[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(); [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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!