基本思路
在Linux系统下利用Ncurses图形库,创建游戏的终端页面
通过pthread库函数创建多线程任务,供游戏中食物和蛇的不断更新
Ncurses
Ncurses 提供字符终端处理库,包括面板和菜单
为了能够使用ncurses库,必须在源程序中将
pthread
在Linux下创建线程的API为pthread_create
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg);
函数参数:
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
PS: 使用这个函数在编译的时候也要 链库-lpthread
代码实现
#include#include #include //定义按键 #define UP 1 #define DOWN -1 #define LEFT 2 #define RIGHT -2 int key; int dir; //初始化ncurses字符终端 void initNcurse() { initscr(); keypad(stdscr,1); noecho(); } struct snake { int hang; int lie; struct snake *next; }; struct snake *head=NULL; struct snake *tail=NULL; struct snake food; //初始化食物 void initFood() { int x = rand()%20;//rand产生一个随机数 int y = rand()%20; food.hang=x; food.lie=y; } //吃到食物 int hasFood(int hang,int lie) { if(food.hang==hang && food.lie==lie){ return 1; } return 0; } //吃到自己 int hasSnakeNode(int hang,int lie) { struct snake *p=head; while(p !=NULL){ if(p->hang==hang && p->lie==lie){ return 1; } p=p->next; } return 0; } void addNode() { struct snake *new = (struct snake *)malloc(sizeof(struct snake)); 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; } new->next=NULL; tail->next=new; tail=new; } //初始化蛇 void initSnake() { dir=RIGHT; //默认初始方向向右 struct snake *p; while(head != NULL ){ p=head; head =head->next; free(p); } initFood(); head = (struct snake *)malloc(sizeof(struct snake)) ; head->hang=1; head->lie=2; head->next=NULL; tail= (struct snake *)malloc(sizeof(struct snake)); tail=head; addNode(); addNode(); addNode(); } //构建地图 void gamePic() { int hang; int lie; move(0,0); for(hang=0;hang<20;hang++){ if(hang==0){ for(lie=0;lie<20;lie++){ printw("--"); } printw("n"); } 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 g n a hang: %d,lie: %dn",food.hang,food.lie); } } } void deleNode(){ struct snake *p = head; head = head->next; free(p); } void moveSnake(){ addNode(); if(hasFood(tail->hang,tail->lie)){ initFood(); }else{ deleNode(); } //撞墙嗝屁 if(tail->hang<0 || tail->hang==20 || tail->lie==0 || tail->lie==20){ initSnake(); } } //刷新界面 void *refreshJiemian(){ while(1){ moveSnake(); gamePic(); refresh(); usleep(200000);//单位为微秒 } } void turn(int direction){ if(abs(dir) != abs(direction)){ dir = direction; } } void *changeDir(){ while(1){ key = getch(); switch(key){ case KEY_UP: turn(UP); break; case KEY_DOWN: turn(DOWN); break; case KEY_LEFT: turn(LEFT); break; case KEY_RIGHT: turn(RIGHT); break; } } } int main(){ pthread_t t1; pthread_t t2; initNcurse();//初始化终端 initSnake();//初始化蛇 gamePic();//构建界面地图 pthread_create(&t1,NULL,refreshJiemian,NULL); pthread_create(&t2,NULL,changeDir,NULL); while(1); getch();//getch替换getc或者getchar. endwin();//释放ncurses使用的所有内存 return 0; }
游戏运行界面:
PS:游戏能跑起来,但是还存在许多bug



