|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
这几天看了下linux程序设计,昨天没事干,突发奇想写个贪吃蛇怎么样,因为想想这个游戏也简单!代码全是自己写!
要是有win下的童鞋,注意,这个是linux 版的,用到curses库和pthread库(多线程库)
前提都要安装相关的库
curses库 sudo apt-get install libncurses5-dev
pthread 库sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev
编译的时候带上两库 gcc greedsnake.c -o greedsnake -lcurses -lpthread
注:代码全是自己想和写的,没有参照网上代码,故代码质量较差,高人勿喷!而且这个是刚刚完工的版本,存在bug,但是对于刚入门linuxC的来说
已经满意啦!
游戏实现:
0,因为终端贪吃蛇,所以用字符表示它的身体了,哈
1,首先是用键盘几个方向键控制贪吃蛇的方向,我这里用全局变量way表示,0 向左,1 向上,2 向右,3 向下
2,当头部触及到食物的时候,向前走一步,把食物纳为自己身体,同时最后一节身体不丢失,实现身长+1
3,触及到墙壁或者自己身体的时候,那么蛇死
游戏重点分析:
一 运行分析
因为我没有接触到多线程那些,昨天刚开始写的时候只用了curses库,发现贪吃蛇既要向已定的方向移动,又要监视键盘的输入,刚开始我都没有想到要用多线程,后面写完主体实现后发现,运行点击键盘就崩溃程序,百思不得妻姐,后来脑子一闪,想到了java中的多线程,因为接触C都从来没有用过多线程,所以就仓促百度了下实现过程:
这里,监视键盘输入做为主线程,而游戏运动作为游戏开始后再创立的线程,这样就能实现键盘输入和游戏运行互不影响
二 如何让终端描绘贪吃蛇
错误观点:因为使用curses库终端就是一个24×80的屏幕(默认大小),我这里首先想到用一个二维数组,刚开始全部赋值0,表示终端对应x,y坐标不显示任何东西,而要是array[x][y] = 1 那么对应就是贪吃蛇的身体一个点,我首先用这种思想试了,贪吃蛇成功走起,但是bug非常多,每前进一步,头部向前移,尾部点消失,就是这个关键,尾部点的坐标,一开始我是用rear_x 和rear_y保存尾部点,但是,当蛇向前移的时候,下一个尾部点的对应坐标是什么呢?是它的四个方向的哪一个?刚开始想的是哪个方向点不为空就是谁,但是为题来了,当蛇身体有一部分在身边如何判断?(就是它尾部点周围方向又有其他身体点,如蛇的缠绕在一起,尾部周围可能都是点,——) 所以二维行不通,
正确:那就使用三维数组把,假设那个点存在,那么就保留当前点的时候蛇的前进方向,这样,有了rear_x rear_y就能通过当前点的方向找到下一个尾部节点,比如array[x][y][0] = 1 array[x][y][1] = 2表示当前点为蛇的身体一节点,该节点的前进方向是2(向右)那么这个节点的后一个节点就是
array[x][y+1][0],以此类推,那么找到尾节点就不是问题、
至此,游戏大概思路就这样,主线程处理按键输入,另一线程让贪吃蛇按照既定方向前进
不说,直接上代码
- #include <curses.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <pthread.h>
- #define Q_line 22
- #define width 78
- #define height 22
- int array[22][78][2]={0};
- int head_x = 10;
- int head_y = 10;
- int rear_x = 10;
- int rear_y = 10;
- int fool_x;
- int fool_y;
- int way = 3;
- pthread_t id;
- //0 left 1 up 2 right 3down
-
- int getchoice();//获取键盘输入
- void strat_game();//开始游戏
- void creat_fool();//产生一个食物节点
- void go();//贪吃蛇的运行前进
- void refresh_win();//刷新界面
- void creat_fool();//
- int check_fool();//检测当前方向的前一个节点是不是食物
- void go_catch();//吃掉食物
- void find_rear();//找到后一个尾节点
- void all_check();//检测是不是墙壁或者吃到自身
- void snake_die();//死亡方法
- int main()
- {
- int choice;
- int first =0,key;
- initscr();
- noecho();
- cbreak();
- keypad(stdscr,1);
- mvprintw(5,5,"My Greedy Snake Game V1.0");
- mvprintw(6,10,"Power by HeLe");
- mvprintw(Q_line,5,"Press space to start");
- refresh();
- while((key = getchoice()) != 'q'){
- switch(key){
- case ' ':if(!first){strat_game();first=1;}
- break;
- case KEY_UP:if(way != 3){way = 1;array[head_x][head_y][1] = 1;}
- break;
- case KEY_DOWN:if(way != 1){way = 3;array[head_x][head_y][1] = 3;}
- break;
- case KEY_LEFT:if(way !=2){ way = 0;array[head_x][head_y][1] = 0;}
- break;
- case KEY_RIGHT:if(way != 0) {way = 2;array[head_x][head_y][1] = 2;}
- break;
- }
- }
- endwin();
- exit(EXIT_SUCCESS);
- }
- void snake_die()
- {
- mvprintw(Q_line-1,5,"Snake has die,Press Q to quti");
- refresh();
- pthread_exit("Ok");
-
- }
- void all_check(int tway) //check die
- {
- if(head_x > Q_line || head_x < 1 || head_y > 77 || head_y < 1)snake_die();
- switch(tway){
- case 0:if(array[head_x][head_y-1][0] == 1)snake_die();
- break;
- case 1:if(array[head_x-1][head_y][0] == 1)snake_die();
- break;
- case 2:if(array[head_x][head_y+1][0] == 1)snake_die();
- break;
- case 3:if(array[head_x+1][head_y][0] == 1) snake_die();
- break;
- }
- }
- void refresh_win()
- {
- int x,y;
- clear();
- for(x = 1; x <= height;x++ )
- {
- for(y = 1; y <= width; y++)
- {
- if(array[x][y][0] == 1)
- {
- mvprintw(x,y,"%s","*");
- }
- if(x == rear_x && y==rear_y){
- mvprintw(x,y,"%s","$");
- }
- if(x==head_x && y == head_y){
- mvprintw(x,y,"%s","@");
- }
- }
- }
- for(x = 0 ,y =0;y < 78;y++)
- {
- mvprintw(x,y,"-");
- mvprintw(y,x,"|");
- mvprintw(Q_line+1,y,"-");
- mvprintw(y,width,"|");
- }
- move(height,width);
- refresh();
- usleep(200000);
- go();
- }
- int getchoice(){
- int key;
- key = getch();
- return key;
- }
- void creat_fool()
- {
- srand((unsigned)time(NULL));
- fool_x = rand() %21+1;
- fool_y = rand()%77+1;
- while(array[fool_x][fool_y][0] == 1)
- {
- fool_x = rand()%22+1;
- fool_y = rand()%78+1;
- }
- array[fool_x][fool_y][0] = 1;
- }
- void strat_game()
- {
- clear();
- //box(stdscr,'|','-');
- array[10][10][0] = 1;
- array[10][10][1] = 3;
- creat_fool();
- if((pthread_create(&id,NULL,(void*)refresh_win,NULL)) !=0){
- endwin();
- exit(1);
- }
- }
- int check_fool()
- {
- switch(way)
- {
- case 0:if(head_x == fool_x && (head_y-1) == fool_y)return 1;
- else return 0;
- break;
- case 1:if((head_x-1) == fool_x && head_y == fool_y)return 1;
- else return 0;
- break;
- case 2:if(head_x == fool_x && (head_y+1) == fool_y)return 1;
- else return 0;
- break;
- case 3:if((head_x+1) == fool_x && head_y == fool_y)return 1;
- else return 0;
- break;
- }
- }
- void go_catch(int tway)
- {
- array[fool_x][fool_y][0] = 1;
- array[fool_x][fool_y][1] = tway;
- head_x = fool_x;
- head_y = fool_y;
- creat_fool();
- }
- void find_rear()
- {
- array[rear_x][rear_y][0] = 0;
- switch(array[rear_x][rear_y][1]){
- case 0:rear_y--;
- break;
- case 1:rear_x--;
- break;
- case 2:rear_y++;
- break;
- case 3:rear_x++;
- break;
- }
- }
- void go()
- {
- switch(way)
- {
- case 0:if(check_fool()){
- go_catch(0);
- }
- else {
- all_check(0);
- array[head_x][--head_y][0] = 1;
- array[head_x][head_y][1] = 0;
- array[rear_x][rear_y][0] = 0;
- find_rear();
- }
- break;
- case 1:if(check_fool()){
- go_catch(1);
- }
- else {
- all_check(1);
- array[--head_x][head_y][0] = 1;
- array[head_x][head_y][1] = 1;
- array[rear_x][rear_y][0] = 0;
- find_rear();
- }
- break;
- case 2:if(check_fool()){
- go_catch(2);
- }
- else {
- all_check(2);
- array[head_x][++head_y][0] = 1;
- array[head_x][head_y][1] = 2;
- array[rear_x][rear_y][0] = 0;
- find_rear();
- }
- break;
- case 3:if(check_fool()){
- go_catch(3);
- }
- else {
- all_check(3);
- array[++head_x][head_y][0] = 1;
- array[head_x][head_y][1] = 3;
- array[rear_x][rear_y][0] = 0;
- find_rear();
- }
- break;
- }
- refresh_win();
- }
复制代码
如果有童鞋有更好的实现方法,可以说说我实现下,哈! 毕竟这个贪吃蛇完全出于我的手!! |
|