日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux环境下Ncurses实现贪吃蛇游戏

發(fā)布時間:2023/12/10 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux环境下Ncurses实现贪吃蛇游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

游戲說明: linux環(huán)境下基于Ncurses圖形庫的C語言小游戲。

Ncurses介紹:
Ncurses(new curses)是一套編程庫,它提供了一系列的函數以便使用者調用它們去生成基于文本的用戶界面。 Ncurses是一個能提供功能鍵定義(快捷鍵),屏幕繪制以及基于文本終端的圖形互動功能的動態(tài)庫。Ncurses用得最多的地方是linux內核編譯之前的內核配置,Ncurses早已淡出舞臺,甚至體驗感完爆Ncurses的C圖形庫GTK、C++圖形庫QT也區(qū)趨于落伍嵌入式設備上的Android 系統(tǒng)。這個游戲只是使用Ncurses并不以學習它為目的,主要還是通過這個游戲鍛煉我們C語言的能力。

準備工作:
在ubuntu上面安裝Ncurses庫,輸入以下指令:

sudo apt-get install libncurses5-dev

來編寫第一個程序看看是否能成功運行:

#include<curses.h> int main() {initscr();//ncurses界面初始化函數printw("This is a ncurses window.\n");//在ncurses模式下的printfgetch();//等待用戶輸入,如果沒有這句話,程序就退出了,看不到運行結果endwin();//程序退出,調用該函數來恢復shell終端的顯示,如果沒有這句話,shell終端字亂碼壞掉return 0; }

運行上面那個程序時需要用到-lcurses:

gcc ncurses.c -lcurses -o ncurses //因為需要用到curses庫所以要鏈入curses

以上代碼輸出界面是:

Ncurses的上下左右鍵值:

#define KEY_DOWN 0402 #define KEY_UP 0403 #define KEY_LEFT 0404 #define KEY_RIGHT 0405 //這些是Ncurses的一些宏定義,表示上下左右鍵,這些數都是八進制的 /* 這些內容可以通過命令查看curses.h的文件可知 命令:cd /usr/include/curses.h */

代碼如下:

#include<curses.h> int main() {initscr();//ncurses界面初始化函數printw("This is a ncurses window.\n");//在ncurses模式下的printfkeypad(stdscr,1);//這個函數是一個函數,第一個參數是從stdscr中接受功能建,第二個是參數表示是否接收,1表示接收while(1){//char c=getch();//等待用戶輸入,如果沒有這句話,程序就退出了,看不到運行結果int key=getch();//這里要把char類型改為int類型,因為char類型最大表示是128,而這些方向鍵的值(0404等)要>128,所以用intprintw("you input :%d\n",key);}endwin();//程序退出,調用該函數來恢復shell終端的顯示,如果沒有這句話,shell終端字亂碼壞掉return 0; }代碼運行結果如下: This is a ncurses window. you input :259 you input :258 you input :260 you input :261 按下上下左右鍵,分別輸出259258260261 輸出的這些數字都是十進制的,分別對應宏定義中的:0403040204040405

代碼可以進一步優(yōu)化:

#include<curses.h> int main() {initscr();//ncurses界面初始化函數printw("This is a ncurses window.\n");//在ncurses模式下的printfkeypad(stdscr,1);//這個函數是一個函數,第一個參數是從stdscr中接受功能建,第二個是參數表示是否接收,1表示接收while(1){//char c=getch();//等待用戶輸入,如果沒有這句話,程序就退出了,看不到運行結果int key=getch();//這里要把char類型改為int類型,因為char類型最大表示是128,而這些方向鍵的值(0404等)要>128,所以用intswitch(key){case 0402:printw("DOWN");break;case 0402:printw("DOWN");break;case 0402:case 0402:printw("DOWN");break;printw("DOWN");break;}}endwin();//程序退出,調用該函數來恢復shell終端的顯示,如果沒有這句話,shell終端字亂碼壞掉return 0; } 當然程序中的代表方向的數字也可以用宏表示。 輸入上下左右鍵,程序運行結果如下: This is a ncurses window. UP DOWN LEFT RIGHT

地圖規(guī)劃:

兩個- 和一個 | 組成一個方格,下圖是20×20的一個地圖。
地圖代碼:

#include<curses.h>void initNcurses() {initscr();keypad(stdscr,1); }void map() {int hang;int lie;for(hang=0;hang<20;hang++){if(hang==0){for(lie=0;lie<20;lie++){printw("--");}printw("\n");printw("");}if(hang>=0&&hang<=19){for(lie=0;lie<=20;lie++){if(lie==0||lie==20){printw("|");}else{printw(" ");}}printw("\n");}if(hang==19){for(lie=0;lie<20;lie++){printw("--");}printw("\n");printw("");}}printw("By Feng Hui Nan."); } int main() {initNcurses();map();getch();endwin();//沒有這行會破壞shell終端return 0; }

貪吃蛇身子節(jié)點構成:

struct Snake {int hang;int lie;struct Snake*next; };

實現蛇身子的全部顯示,并向右移動:

#include<curses.h> #include <stdlib.h> #include <unistd.h> void initNcurses() {initscr();keypad(stdscr,1); }struct Snake //貪吃蛇身子的一個結點 {int hang;int lie;struct Snake*next; }; struct Snake* head=NULL;//將蛇的頭節(jié)點定義為全局變量 struct Snake* tail=NULL;//將蛇的尾節(jié)點定義為全局變量,防止錯誤過多 int hasSnakeNode(int i,int j) {struct Snake *p;p=head;while(p!=NULL){if(p->hang==i && p->lie==j){return 1;}p=p->next;}return 0; } void map() {int hang;int lie;move(0,0);//在每次調用地圖的時候用move函數將光標移動到地圖的第一個方格的位置for(hang=0;hang<20;hang++){if(hang==0){for(lie=0;lie<20;lie++){printw("--");}printw("\n");printw("");}if(hang>=0&&hang<=19){for(lie=0;lie<=20;lie++){if(lie==0||lie==20){printw("|");}else if(hasSnakeNode(hang,lie)){printw("[]");}else{printw(" ");}}printw("\n");}if(hang==19){for(lie=0;lie<20;lie++){printw("--");}printw("\n");}}printw("By Feng Hui Nan."); } void addSnake() {struct Snake* new=(struct Snake*)malloc(sizeof(struct Snake));new->hang=tail->hang;new->lie=tail->lie+1;new->next=NULL;tail->next=new;tail=new; } void initSnake() {struct Snake*p;while(head!=NULL){p=head;head=head->next;//將鏈表的每一個節(jié)點都釋放掉,指針后移free(p);}//添加這個循環(huán)的目的是在一次游戲結束后釋放當局游戲創(chuàng)建的鏈表,避免內存泄露head=(struct Snake*)malloc(sizeof(struct Snake));head->hang=1;head->lie=1;head->next=NULL;tail=head;addSnake();addSnake();addSnake(); } void deleSnake() {struct Snake*p;p=head;head=head->next;free(p); } void moveSnake() {addSnake();//在蛇的尾部添加節(jié)點并且刪除節(jié)點后然后判斷尾節(jié)點的行和列是否達到邊界deleSnake();if(tail->hang==0 || tail->lie==20 || tail->lie==0 || tail->hang==20){initSnake();} } int main() {initNcurses();initSnake();map();while(1){moveSnake();map();//刪除后再次刷新地圖顯示移動后的界面refresh();//刷新界面函數//sleep(1);//每隔一秒蛇移動一下,并刷新界面,這行控制蛇的移動速率usleep(100000);//sleep以秒為單位有點慢,usleep以微秒為單位此處控制蛇的移動速度}getch();endwin();//沒有這行會破壞shell終端return 0; }

效果圖:
遇到問題:
如何在響應方向鍵的同時,控制蛇的移動?好像需要兩個while循環(huán)同時執(zhí)行。我想到一個方法,就是用switch判斷輸入的方向鍵,然后再封裝向上下左右移動的函數,在switch中進行調用,仔細思考以下發(fā)現不可行,因為在這個游戲中地圖是每隔100毫秒刷新一次要不斷的刷新,所以不可行。

問題解決:
用linux線程即可解決該問題,我們將一個程序里的執(zhí)行路線叫做線程(thread)。更準確的定義是:線程是一個進程內部的控制序列。

線程demo:

#include<stdio.h> #include<pthread.h>void*thread(void *arg) {printf("this is a thread and arg=%d.\n",*(int*)arg);*(int*)arg=0;return arg; } int main(int argc,char *argv[]) {pthread_t th;int ret;int arg=10;int *thread_ret=NULL;ret=pthread_create(&th,NULL,thread,&arg);//pthread_create這個函數是線程的創(chuàng)建函數//第一個參數th是線程的描述符,就是上邊定義的pthread_t th中的th,就相當于給第三那個參數的一個ID吧//第二個參數一般就寫NULL//第三個參數是做好的準備被調用的函數,最后一個參數是函數的參數if(ret!=0){printf("Creat thread error!\n");return -1;}printf("this is the mian process.\n");pthread_join(th,(void**)&thread_ret);//int pthread_join(pthread_t thread, void **value_ptr);//thread:等待退出線程的線程號。//value_ptr:退出線程的返回值。return 0; }

自己實現線程的創(chuàng)建:

#include<stdio.h> #include<pthread.h> #include <unistd.h> void* fun1() {while(1){printf("this is func1.\n");sleep(1);} } void* fun2() {while(1){printf("this is fun2.\n");sleep(1);} } int main() {pthread_t th1;pthread_t th2;int ret1;int ret2;int *pthread_th1=NULL;int *pthread_th2=NULL;ret1=pthread_create(&th1,NULL,fun1,NULL);ret2=pthread_create(&th2,NULL,fun2,NULL);if(ret1!=0 || ret2!=0){printf("thread creat error.\n");perror("error");return -1;} // while(1);//在主線程等待其他線程運行完后再退出pthread_join(th1,(void **)&pthread_th1);pthread_join(th2,(void **)&pthread_th2);//這種方法也可以使主線程等待指定線程退出后才退出//th2是線程的ID//int pthread_join(pthread_t thread, void **value_ptr);//thread:等待退出線程的線程號。//value_ptr:退出線程的返回值。return 0;}

程序總體代碼:

#include<curses.h> #include <stdlib.h> #include <unistd.h> #include<pthread.h>#define UP 1 #define DOWN -1 #define RIGHT 2 #define LEFT -2struct Snake //貪吃蛇身子的一個結點 {int hang;int lie;struct Snake*next; };struct Snake food; void initFood() {int x=rand()%20;int y=rand()%20;//%20是為了保證使rand出現的隨機數盡量的出現在地圖范圍內food.hang=x;food.lie=y; } void initNcurses() {initscr();keypad(stdscr,1);noecho();//不要把無關的東西打印在界面上 }struct Snake* head=NULL;//將蛇的頭節(jié)點定義為全局變量 struct Snake* tail=NULL;//將蛇的尾節(jié)點定義為全局變量,防止錯誤過多 int key; int dir;int hasFood(int i,int j) {if(food.hang==i && food.lie==j){return 1;}return 0; } int hasSnakeNode(int i,int j) {struct Snake *p;p=head;while(p!=NULL){if(p->hang==i && p->lie==j){return 1;}p=p->next;}return 0; } void map() {int hang;int lie;move(0,0);//在每次調用地圖的時候用move函數將光標移動到地圖的第一個方格的位置for(hang=0;hang<20;hang++){if(hang==0){for(lie=0;lie<20;lie++){printw("--");}printw("\n");printw("");}if(hang>=0&&hang<=19){for(lie=0;lie<=20;lie++){if(lie==0||lie==20){printw("|");}else if(hasSnakeNode(hang,lie)){printw("[]");}else if(hasFood(hang,lie)){printw("**");}else{printw(" ");}}printw("\n");}if(hang==19){for(lie=0;lie<20;lie++){printw("--");}printw("\n");}}printw("By Feng Hui Nan."); } void addSnake() {struct Snake* new=(struct Snake*)malloc(sizeof(struct Snake));new->next=NULL;switch(dir){case UP:new->hang=tail->hang-1;new->lie=tail->lie;break;case DOWN:new->hang=tail->hang+1;new->lie=tail->lie;break;case LEFT:new->hang=tail->hang;new->lie=tail->lie-1;break;case RIGHT:new->hang=tail->hang;new->lie=tail->lie+1;break;}tail->next=new;tail=new; } void initSnake()//蛇的初始化函數 {struct Snake*p;dir=RIGHT;while(head!=NULL){p=head;head=head->next;//將鏈表的每一個節(jié)點都釋放掉,指針后移free(p);}//添加這個循環(huán)的目的是在一次游戲結束后釋放當局游戲創(chuàng)建的鏈表,避免內存泄露initFood();head=(struct Snake*)malloc(sizeof(struct Snake));head->hang=1;head->lie=1;head->next=NULL;tail=head;addSnake();addSnake();addSnake(); } void deleSnake() {struct Snake*p;p=head;head=head->next;free(p); }int ifSnakeDie() {struct Snake*p;p=head;if(tail->hang<0 || tail->lie==20 || tail->lie==0 || tail->hang==20){return 1;}while(p->next!=NULL){if(p->hang==tail->hang && p->lie==tail->lie){return 1;}p=p->next;}return 0;} void* moveSnake() {addSnake();//在蛇的尾部添加節(jié)點并且刪除節(jié)點后然后判斷尾節(jié)點的行和列是否達到邊界if(hasFood(tail->hang,tail->lie)){initFood();}else{deleSnake();}if(ifSnakeDie()){initSnake();} } void* refreshUi()//封裝的界面刷新函數 {while(1){moveSnake();map();//刪除后再次刷新地圖顯示移動后的界面refresh();//刷新界面函數//sleep(1);//每隔一秒蛇移動一下,并刷新界面,這行控制蛇的移動速率usleep(150000);//sleep以秒為單位有點慢,usleep以微秒為單位此處控制蛇的移動速度} } void turn(int direction)//這個函數的作用是當蛇在豎直方向上運動時使上下鍵無效//在水平方向運動時,左右方向鍵無效 {if(abs(dir)!=abs(direction)){dir=direction;} } void* changeDir() {while(1){key=getch();switch(key){case KEY_DOWN:turn(DOWN);break;case KEY_UP:turn(UP);break;case KEY_RIGHT:turn(RIGHT);break;case KEY_LEFT:turn(LEFT);break;}}} int main() {initNcurses();initSnake();map();pthread_t t1;pthread_t t2;int *pthread1=NULL;int *pthread2=NULL;pthread_create(&t1,NULL,changeDir,NULL);pthread_create(&t2,NULL,refreshUi,NULL); // pthread_join(t1,(void**)&pthread1); // pthread_join(t2,(void**)&pthread2);while(1);getch();endwin();//沒有這行會破壞shell終端return 0; }

編譯的時時候記得要加-lpthread、-lcurses

總結

以上是生活随笔為你收集整理的linux环境下Ncurses实现贪吃蛇游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产尤物在线观看 | 中文字幕网伦射乱中文 | 成人av中文解说水果派 | 香蕉视频一区二区三区 | 天天操夜夜撸 | 黄色尤物视频 | 诱惑の诱惑筱田优在线播放 | 亚洲精品成人无码熟妇在线 | 国产69熟 | 国产99久久九九精品无码 | 国产尤物在线观看 | 欧美性天堂 | 超污视频在线观看 | 久久久久久无码精品大片 | av免费播放 | 骚虎视频最新网址 | 天天艹天天爽 | 国产精品免费观看视频 | 91在线视频播放 | 亚洲区小说 | 久久黄色网 | 麻豆91精品91久久久 | 91精品国产色综合久久不卡电影 | 国产一区资源 | 亚洲第一综合网站 | 国产精品国产精品国产专区 | 人妻天天爽夜夜爽一区二区三区 | 高跟鞋丝袜猛烈xxxx | 久久久久久av无码免费网站下载 | 国产精品系列在线观看 | 91精品国产高清一区二区三区蜜臀 | 最新中文字幕在线观看 | 国产精品视频在 | 一级黄色av | 玩偶姐姐在线观看免费 | 韩国伦理大片 | 成人精品一区二区三区视频 | 99在线精品免费视频 | 亚洲黄色免费网站 | 高清欧美性猛交xxxx黑人猛交 | 一本大道综合伊人精品热热 | 视频在线亚洲 | 黄色三级视频网站 | 欧美91精品久久久久国产性生爱 | 日韩欧美在线视频 | 免费男女乱淫真视频免费播放 | 亚洲一一在线 | 一区精品二区国产 | 国产性生活视频 | 天天玩天天操 | 久久久精品视频一区 | 亚洲精品国产精品乱码不99按摩 | 亚洲免费三区 | 女性女同性aⅴ免费观女性恋 | 九色蝌蚪9l视频蝌蚪9l视频 | 中文乱码人妻一区二区三区视频 | 国产在线1区| 成av人在线观看 | 可以在线观看的av | 青青草伊人 | 日韩成人av免费在线观看 | 人妻少妇精品一区二区三区 | 色啪综合 | 2024av| 黄色av网站在线 | 911毛片| 五月天久久久久 | 国产精品人人妻人人爽人人牛 | 嫩草影院在线视频 | 在线观看国产小视频 | 欧美色图日韩 | 国产精华一区二区三区 | 热久久在线 | 最新日本中文字幕 | 日本一区二区成人 | 色就色综合 | 无码人妻精品一区二区蜜桃网站 | 女王脚交玉足榨精调教 | 欧美国产高潮xxxx1819 | 少妇无码一区二区三区 | 狠狠艹视频 | 色欲狠狠躁天天躁无码中文字幕 | av导航网址| 亚洲第一区视频 | av中文字幕免费在线观看 | 欧洲美一区二区三区亚洲 | 中文乱码人妻一区二区三区视频 | 免费日韩一区二区 | 日本激情一区二区三区 | 国产又黄又粗 | 奇米中文字幕 | 国产精品亚洲自拍 | 日韩中文视频 | 国产精品永久 | 中文亚洲欧美 | 亚洲精品网址 | 综合激情视频 | 麻豆视频网站在线观看 | 中国无码人妻丰满熟妇啪啪软件 |