分享自己写的一个贪吃蛇的游戏(Linux)


作者: dave_cn 发表于 2010-07-18 21:20 原文链接 阅读: 148 评论: 2

转载请注明出处。http://www.cnblogs.com/dave_cn/

本程序需要ncurses库,ubuntu下安装ncurses可以执行下面命令:

sudo apt-get install libncurses5-dev 

关于ncurses的用法,读者可以Google之。

程序运行的效果如下:

其中包含两个窗口,一个为game窗口,一个为日志窗口。 

 

 

 代码如下:

   1 /**

  2   * Snake
  3   * author: dave_cn
  4   * date  : 2010/7/14
  5   * info  :
  6   *        @ ...... food
  7    */
  8  #include  < stdio.h >
  9  #include  < stdlib.h >
 10  #include  < string .h >
 11  #include  < sys / time.h >
 12  #include  < sys / types.h >
 13  #include  < unistd.h >
 14  #include  < ncurses.h >
 15 
 16  #define  TBool            int
 17  #define  True             1
 18  #define  False            0    
 19  #define  SHAPE_FOOD       '@'
 20  #define  SHAPE_SNAKE      '*'
 21  #define  GAMEWIN_YLEN     15
 22  #define  GAMEWIN_XLEN     60
 23  #define  LOGWIN_YLEN      7
 24  #define  LOGWIN_XLEN      (GAMEWIN_XLEN)
 25  #define  LOGBUF_NUM       (LOGWIN_YLEN-2)
 26  #define  LOGBUF_LEN       (GAMEWIN_XLEN-2)
 27  #define  MAXLEVEL         12
 28 
 29  #define  GetSnakeTail(s)  ((s)->head->front)
 30 
 31  WINDOW  * logwin;
 32  #define  INITRUNLOG()     logwin = newlogw()
 33  #define  RUNLOG(str)      runlog(logwin, str)
 34  #define  DESTROYRUNLOG()  delwin(logwin)
 35 
 36  int  g_level;
 37 
 38  enum  TDirection {
 39      DIR_UP,
 40      DIR_DOWN,
 41      DIR_LEFT,
 42      DIR_RIGHT
 43  };
 44 
 45  struct  TFood {
 46       int  y;
 47       int  x;
 48  };
 49 
 50  struct  TSnakeNode {
 51       int  y;
 52       int  x;
 53       struct  TSnakeNode  * front;
 54  };
 55 
 56  struct  TSnake {
 57       int     length;
 58       struct  TSnakeNode  * head;
 59       enum    TDirection  dir;
 60  };
 61 
 62  int  refreshgamew(WINDOW  * win,  struct  TSnake  * psnake);
 63  void  movesnake( struct  TSnake  * psnake);
 64  int  checksnake( struct  TFood  * pfood,  struct  TSnake  * psnake);
 65  void  snakegrowup( struct  TFood  * pfood,  struct  TSnake  * psnake);
 66  void  gameover(WINDOW  * win,  char   * str);
 67  struct  TSnakeNode  * newsnakenode( struct  TSnakeNode  ** ppsnode,  int  y,  int  x);
 68  WINDOW *  newgamew();
 69  struct  TSnake *  initsnake();
 70  void  destroysnake( struct  TSnake  * psnake);
 71  void  drawsnakew(WINDOW  * win,  struct  TSnake  * psnake);
 72  void  drawfoodw(WINDOW  * win,  struct  TFood  * pfood,  struct  TSnake  * psnake);
 73  TBool checkfood( struct  TFood  * pfood,  struct  TSnake  * psnake);
 74  WINDOW *  newlogw();
 75  void  runlog(WINDOW  * win,  char   * str);
 76  void  cleanline(WINDOW  * win,  int  y,  int  x);
 77 
 78  int  main()
 79  {
 80      initscr();
 81      raw();
 82      noecho();
 83      keypad(stdscr, TRUE);
 84      curs_set( 0 );
 85      refresh();
 86 
 87      g_level  =   1 ;
 88      INITRUNLOG();
 89      RUNLOG( "   Press 'q' or 'Q' to quit. " );
 90      RUNLOG( "   Press 'w/s/a/d' or 'W/S/A/D' to move the snake. " );
 91      RUNLOG( " Info: " );
 92      
 93      WINDOW  * gwin  =  newgamew();
 94       struct  TSnake  * psnake  =  initsnake();
 95      drawsnakew(gwin, psnake);
 96      
 97       while  (refreshgamew(gwin, psnake)  >=   0 ) ;
 98      
 99      getch();
100      
101      destroysnake(psnake);
102      delwin(gwin);
103      DESTROYRUNLOG();
104      endwin();
105      
106       return   0 ;
107  }
108 
109  int  refreshgamew(WINDOW  * win,  struct  TSnake  * psnake)
110  {
111       static  TBool ffood  =  False;
112       struct  TFood pfood;
113      
114       if  ( ! ffood) {
115          drawfoodw(win,  & pfood, psnake);
116          ffood  =  True;
117      }
118 
119       int  key  =   - 1 ;
120      
121      fd_set  set ;
122      FD_ZERO( & set );
123      FD_SET( 0 & set );
124      
125       struct  timeval timeout;
126      timeout.tv_sec  =   0 ;
127      timeout.tv_usec =  ( 6   -  ( int )(g_level / 3 ))  *   100 * 1000 ;
128      
129       if  (select( 1 & set , NULL, NULL,  & timeout)  <   0 )
130           return   - 1 ;
131      
132       if  (FD_ISSET( 0 & set )) {
133           while  ((key  =  getch())  ==   - 1 ) ;
134      
135           switch  (key) {
136           case   ' w ' :
137           case   ' W ' :
138              (psnake -> dir  ==  DIR_DOWN)  ?  : (psnake -> dir  =  DIR_UP);
139               break ;
140          
141           case   ' s ' :
142           case   ' S ' :
143              (psnake -> dir  ==  DIR_UP)  ?  : (psnake -> dir  =  DIR_DOWN);
144               break ;
145          
146           case   ' a ' :
147           case   ' A ' :
148              (psnake -> dir  ==  DIR_RIGHT)  ?  : (psnake -> dir  =  DIR_LEFT);
149               break ;
150          
151           case   ' d ' :
152           case   ' D ' :
153              (psnake -> dir  ==  DIR_LEFT)  ?  : (psnake -> dir  =  DIR_RIGHT);
154               break ;
155          
156           case   ' q ' :
157           case   ' Q ' :
158              RUNLOG( " Quit Game! " );
159              gameover(win,  " Quit Game! " );
160               return   - 1 ;
161          
162           default :
163               break ;
164          }
165      }
166 
167      movesnake(psnake);
168      drawsnakew(win, psnake);
169       switch  (checksnake( & pfood, psnake)) {
170       case   0 :
171           break ;
172          
173       case   1 :
174          ffood  =  False;
175           if  ( ++ g_level  >  MAXLEVEL) {
176              RUNLOG( " Win!!! " );
177              gameover(win,  " Win!!! " );
178               return   - 1 ;
179          }
180          mvwprintw(win, GAMEWIN_YLEN - 1 2 "  Level: %d  " , g_level);
181          mvwprintw(win, GAMEWIN_YLEN - 1 30 "  Speed: %d  " , ( int )(g_level / 3 ));
182          wrefresh(win);
183          RUNLOG( " Level UP! " );
184          snakegrowup( & pfood, psnake);
185           break ;
186          
187       default :
188          RUNLOG( " Game over! " );
189          gameover(win,  " Game over! " );
190           return   - 1 ;
191      }
192      
193       return   1 ;
194  }
195 
196  /* *
197   * stuct TSnake是一个倒置的首尾相连的链表,head->front指向snake的尾部
198   * 如: [a]<-[b]<-[c]<-[d]    a为head
199   *      |              ^     snake移动的时候,只用head指向d,
200   *      `--------------'     并且修改d的(y,x)为snake头移动到的位置.
201    */
202  void  movesnake( struct  TSnake  * psnake)
203  {
204       int  hy  =  psnake -> head -> y;
205       int  hx  =  psnake -> head -> x;
206      
207      psnake -> head  =  GetSnakeTail(psnake);
208      
209       switch  (psnake -> dir) {
210       case  DIR_UP:
211          psnake -> head -> =  hy  -   1 ;
212          psnake -> head -> =  hx;
213           break ;
214      
215       case  DIR_DOWN:
216          psnake -> head -> =  hy  +   1 ;
217          psnake -> head -> =  hx;
218           break ;
219      
220       case  DIR_LEFT:
221          psnake -> head -> =  hy;
222          psnake -> head -> =  hx  -   1 ;
223           break ;
224      
225       case  DIR_RIGHT:
226          psnake -> head -> =  hy;
227          psnake -> head -> =  hx  +   1 ;
228           break ;
229          
230       default :
231           break ;
232      }
233  }
234 
235  int  checksnake( struct  TFood  * pfood,  struct  TSnake  * psnake)
236  {
237       if  ( psnake -> head -> <=   0   ||  psnake -> head -> >=  GAMEWIN_YLEN
238         ||  psnake -> head -> <=   0   ||  psnake -> head -> >=  GAMEWIN_XLEN)
239      {
240           return   - 1 ;
241      }
242 
243       struct  TSnakeNode  * pnode  =  GetSnakeTail(psnake);
244       int  i  =   0 ;
245       for  (; i  <  psnake -> length  -   1 ++ i, pnode  =  pnode -> front)
246           if  (psnake -> head -> ==  pnode -> &&  psnake -> head -> ==  pnode -> x)
247               return   - 1 ;
248 
249       if  (psnake -> head -> ==  pfood -> &&  psnake -> head -> ==  pfood -> x)
250           return   1 ;
251      
252       return   0 ;
253  }
254 
255  void  snakegrowup( struct  TFood  * pfood,  struct  TSnake  * psnake)
256  {
257       struct  TSnakeNode  * pnode  =  ( struct  TSnakeNode  * )malloc( sizeof ( struct  TSnakeNode));
258      
259       switch  (psnake -> dir) {
260       case  DIR_UP:
261          pnode -> =  psnake -> head -> -   1 ;
262          pnode -> =  psnake -> head -> x;
263           break ;
264      
265       case  DIR_DOWN:
266          pnode -> =  psnake -> head -> +   1 ;
267          pnode -> =  psnake -> head -> x;
268           break
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值