鱼C论坛

 找回密码
 立即注册
查看: 6060|回复: 3

[原创] Linux终端贪吃蛇--

[复制链接]
发表于 2015-7-10 12:23:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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],以此类推,那么找到尾节点就不是问题、

至此,游戏大概思路就这样,主线程处理按键输入,另一线程让贪吃蛇按照既定方向前进

不说,直接上代码
  1. #include <curses.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <time.h>
  6. #include <pthread.h>

  7. #define Q_line 22
  8. #define width 78
  9. #define height 22

  10. int array[22][78][2]={0};
  11. int head_x = 10;
  12. int head_y = 10;
  13. int rear_x = 10;
  14. int rear_y = 10;
  15. int fool_x;
  16. int fool_y;
  17. int way = 3;
  18. pthread_t id;
  19. //0 left 1 up 2 right 3down


  20. int getchoice();//获取键盘输入
  21. void strat_game();//开始游戏
  22. void creat_fool();//产生一个食物节点
  23. void go();//贪吃蛇的运行前进
  24. void refresh_win();//刷新界面
  25. void creat_fool();//
  26. int check_fool();//检测当前方向的前一个节点是不是食物
  27. void go_catch();//吃掉食物
  28. void find_rear();//找到后一个尾节点
  29. void all_check();//检测是不是墙壁或者吃到自身
  30. void snake_die();//死亡方法

  31. int main()
  32. {
  33.     int choice;
  34.     int first =0,key;
  35.     initscr();
  36.     noecho();
  37.     cbreak();
  38.     keypad(stdscr,1);
  39.     mvprintw(5,5,"My Greedy Snake Game V1.0");
  40.     mvprintw(6,10,"Power by HeLe");
  41.     mvprintw(Q_line,5,"Press space to start");
  42.     refresh();

  43.     while((key = getchoice()) != 'q'){
  44.         switch(key){
  45.             case ' ':if(!first){strat_game();first=1;}
  46.             break;
  47.             case KEY_UP:if(way != 3){way = 1;array[head_x][head_y][1] = 1;}
  48.             break;
  49.             case KEY_DOWN:if(way != 1){way = 3;array[head_x][head_y][1] = 3;}
  50.             break;
  51.             case KEY_LEFT:if(way !=2){ way = 0;array[head_x][head_y][1] = 0;}
  52.             break;
  53.             case KEY_RIGHT:if(way != 0) {way = 2;array[head_x][head_y][1] = 2;}
  54.             break;
  55.         }
  56.     }
  57.     endwin();
  58.     exit(EXIT_SUCCESS);
  59. }

  60. void snake_die()
  61. {
  62.     mvprintw(Q_line-1,5,"Snake has die,Press Q to quti");
  63.     refresh();
  64.     pthread_exit("Ok");
  65.    
  66. }

  67. void all_check(int tway)        //check die
  68. {
  69.     if(head_x > Q_line || head_x < 1 || head_y > 77 || head_y < 1)snake_die();
  70.     switch(tway){
  71.         case 0:if(array[head_x][head_y-1][0] == 1)snake_die();
  72.         break;
  73.         case 1:if(array[head_x-1][head_y][0] == 1)snake_die();
  74.         break;
  75.         case 2:if(array[head_x][head_y+1][0] == 1)snake_die();
  76.         break;
  77.         case 3:if(array[head_x+1][head_y][0] == 1) snake_die();
  78.         break;
  79.     }
  80. }

  81. void refresh_win()
  82. {
  83.     int x,y;
  84.     clear();
  85.     for(x = 1; x <= height;x++ )
  86.     {
  87.         for(y = 1; y <= width; y++)
  88.         {
  89.             if(array[x][y][0] == 1)
  90.             {
  91.                 mvprintw(x,y,"%s","*");
  92.             }
  93.             if(x == rear_x && y==rear_y){
  94.                 mvprintw(x,y,"%s","$");
  95.             }
  96.             if(x==head_x && y == head_y){
  97.                 mvprintw(x,y,"%s","@");
  98.             }
  99.         }
  100.     }
  101.     for(x = 0 ,y =0;y < 78;y++)
  102.     {
  103.         mvprintw(x,y,"-");
  104.         mvprintw(y,x,"|");
  105.         mvprintw(Q_line+1,y,"-");
  106.         mvprintw(y,width,"|");
  107.     }
  108.     move(height,width);
  109.     refresh();
  110.     usleep(200000);
  111.     go();
  112. }

  113. int getchoice(){
  114.     int key;
  115.     key = getch();
  116.     return key;
  117. }

  118. void creat_fool()
  119. {
  120.     srand((unsigned)time(NULL));
  121.     fool_x = rand() %21+1;
  122.     fool_y = rand()%77+1;
  123.     while(array[fool_x][fool_y][0] == 1)
  124.     {
  125.         fool_x = rand()%22+1;
  126.         fool_y = rand()%78+1;
  127.     }
  128.     array[fool_x][fool_y][0] = 1;
  129. }

  130. void strat_game()
  131. {
  132.     clear();
  133.     //box(stdscr,'|','-');
  134.     array[10][10][0] = 1;
  135.     array[10][10][1] = 3;
  136.     creat_fool();
  137.     if((pthread_create(&id,NULL,(void*)refresh_win,NULL)) !=0){
  138.         endwin();
  139.         exit(1);
  140.     }  
  141. }

  142. int check_fool()
  143. {
  144.     switch(way)
  145.     {
  146.         case 0:if(head_x == fool_x && (head_y-1) == fool_y)return 1;
  147.         else return 0;
  148.         break;
  149.         case 1:if((head_x-1) == fool_x && head_y == fool_y)return 1;
  150.         else return 0;
  151.         break;
  152.         case 2:if(head_x == fool_x && (head_y+1) == fool_y)return 1;
  153.         else return 0;
  154.         break;
  155.         case 3:if((head_x+1) == fool_x && head_y == fool_y)return 1;
  156.         else return 0;
  157.         break;
  158.     }
  159. }
  160. void go_catch(int tway)
  161. {
  162.     array[fool_x][fool_y][0] = 1;
  163.     array[fool_x][fool_y][1] = tway;
  164.     head_x = fool_x;
  165.     head_y = fool_y;
  166.     creat_fool();
  167. }

  168. void find_rear()
  169. {
  170.     array[rear_x][rear_y][0] = 0;
  171.     switch(array[rear_x][rear_y][1]){
  172.         case 0:rear_y--;
  173.         break;
  174.         case 1:rear_x--;
  175.         break;
  176.         case 2:rear_y++;
  177.         break;
  178.         case 3:rear_x++;
  179.         break;
  180.     }
  181. }

  182. void go()
  183. {
  184.     switch(way)
  185.     {
  186.         case 0:if(check_fool()){
  187.             go_catch(0);
  188.         }
  189.         else {
  190.             all_check(0);
  191.             array[head_x][--head_y][0] = 1;
  192.             array[head_x][head_y][1] = 0;
  193.             array[rear_x][rear_y][0] = 0;
  194.             find_rear();
  195.         }
  196.         break;
  197.         case 1:if(check_fool()){
  198.             go_catch(1);
  199.         }
  200.         else {
  201.             all_check(1);
  202.             array[--head_x][head_y][0] = 1;
  203.             array[head_x][head_y][1] = 1;
  204.             array[rear_x][rear_y][0] = 0;
  205.             find_rear();
  206.         }
  207.         break;
  208.         case 2:if(check_fool()){
  209.             go_catch(2);
  210.         }
  211.         else {
  212.             all_check(2);
  213.             array[head_x][++head_y][0] = 1;
  214.             array[head_x][head_y][1] = 2;
  215.             array[rear_x][rear_y][0] = 0;
  216.             find_rear();
  217.         }
  218.         break;
  219.         case 3:if(check_fool()){
  220.             go_catch(3);
  221.         }
  222.         else {
  223.             all_check(3);
  224.             array[++head_x][head_y][0] = 1;
  225.             array[head_x][head_y][1] = 3;
  226.             array[rear_x][rear_y][0] = 0;
  227.             find_rear();
  228.         }
  229.         break;
  230.     }
  231.     refresh_win();
  232. }
复制代码




如果有童鞋有更好的实现方法,可以说说我实现下,哈! 毕竟这个贪吃蛇完全出于我的手!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-7-10 12:27:05 | 显示全部楼层
图片效果
Screenshot from 2015-07-10 12:27:11.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-12-26 02:57:00 From FishC Mobile | 显示全部楼层
刚学习不久,很多看不懂,只能默默支持一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-8-21 23:00:19 | 显示全部楼层
厉害了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 14:10

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表