自制贪吃蛇——会移动的蛇

  上篇地址:http://www.cnblogs.com/chinxi/p/7184063.html

  有了主场景,就要加一条蛇进去看看了。这条“蛇”的功能嘛,要有以下几个:

    1、改变方向

    2、新增一个节点

    3、前进

  首先,是枚举和结构体:

 1 enum Direction
 2 {
 3     EN_DIR_UP = 0,
 4     EN_DIR_DOWN,
 5     EN_DIR_LEFT,
 6     EN_DIR_RIGHT,
 7 };
 8 
 9 struct Coordinate
10 {
11     int int_x;
12     int int_y;
13 };
14 
15 typedef struct Snake_Base
16 {
17     Snake_Base* pNext;
18     char char_icon;              //图标
19     Coordinate coordinate_cur;   //当前坐标
20 }SnakeBase;
21 
22 typedef struct Snake_Head
23 {
24     char char_icon;              //图标
25     int int_direction;           //前进方向
26     int int_size;                //当前长度
27     Coordinate coordinate_cur;   //当前坐标
28     Snake_Base* pNext;           //下一节   
29 }SnakeHead;
 1  ///
 2  /// @file    snake.h
 3  /// @author  marrs(chenchengxi993@gmail.com)
 4  /// @date    2017-07-15 09:32:47
 5  ///
 6 
 7 #ifndef __SNAKE_H__
 8 #define __SNAKE_H__
 9 
10 #include "define.h" 
11 
12 namespace marrs{
13 
14 class Snake
15 {
16     public:
17         Snake();
18         ~Snake();
19 
20     public:
21         int init(char char_icon, int int_direction, int int_size, Coordinate coordinate);
22         int change_direction(int int_direction);    
23         int add_new_node(Coordinate coordinate_new, char char_icon_new);
24         int forward();
25         Snake_Base* get_snake_base();
26         SnakeHead* get_snake_head();
27 
28     private:
29         SnakeHead _snake;
30 
31 };
32 
33 }
34 
35 #endif

  改变方向其实很简单,改一下字段的值就行了。新增节点的话,如果不考虑场景,那么只要用头插法,向链表中插入一个新元素即可。至于前进,想到了两种植方法:

  其一,“蛇”类中只处理头节点的坐标,其它坐标放在game.cc中处理,把前一个节点的坐标赋值给后一个节点,然后清除最后一个节点的原坐标在场景中的展示。这种方法需要进行多次拷贝,而且要定义多个临时变量,比较麻烦。

  其二,“蛇”类中,如果“蛇”的长度大于1,则先调用一波add_new_node方法,再把最后一个节点删除,并返回这个节点的信息。如果size=1,则new一个节点出来,把头节点的原坐标赋值给它,之后game.cc中,直接清理返回的坐标,再设置头节点新坐标即可。

  实际上,是先想到第一种方法,而且实现了,后来想到了第二种方法,直接就改了。

  1  /// /// @file    snake.cc
  2  /// @author  marrs(chenchengxi993@gmail.com)
  3  /// @date    2017-07-15 11:02:32
  4  ///
  5 
  6 #include <string.h>
  7 #include <iostream>
  8 #include "snake.h"
  9 
 10 namespace marrs{
 11  
 12 Snake::Snake()
 13 {
 14 }
 15 
 16 Snake::~Snake()
 17 {
 18 }
 19 
 20 int Snake::init(char char_icon, int int_direction, int int_size, Coordinate coordinate)
 21 {
 22     _snake.char_icon = char_icon;
 23     _snake.int_direction = int_direction;
 24     _snake.int_size = int_size;
 25     _snake.coordinate_cur = coordinate;
 26     _snake.pNext = NULL;
 27 
 28     if (int_size > 1)
 29     {
 30         for (int int_idx = 0; int_idx < int_size; ++int_idx)
 31         {
 32             //todo add_new_node
 33         }
 34     }
 35     return 0;
 36 
 37 }
 38 
 39 int Snake::change_direction(int int_direction)
 40 {
 41     _snake.int_direction = int_direction;
 42     return int_direction;
 43 }
 44 
 45 int Snake::add_new_node(Coordinate coordinate_new, char char_icon_new)
 46 {
 47     Snake_Base* pNode = new Snake_Base;
 48     memset(pNode, 0, sizeof(Snake_Base));
 49     pNode->coordinate_cur = _snake.coordinate_cur;
 50     pNode->char_icon = _snake.char_icon;
 51 
 52     if (_snake.pNext == NULL)
 53     {
 54         _snake.pNext = pNode;        
 55     }else{
 56         pNode->pNext = _snake.pNext;
 57         _snake.pNext = pNode;
 58     }
 59     
 60     _snake.coordinate_cur = coordinate_new;
 61     _snake.char_icon = char_icon_new;
 62     ++_snake.int_size;
 63 
 64     return 0;
 65 }
 66 
 67 Snake_Base* Snake::forward()
 68 {
 69     Snake_Base* pReturn = NULL;
 70     if(_snake.int_size > 1)
 71     {
 72         add_new_node(_snake.coordinate_cur, _snake.char_icon);        
 73         Snake_Base* pCur = _snake.pNext;
 74         while(pCur->pNext->pNext)
 75         {
 76             pCur = pCur->pNext;
 77         }
 78         pReturn = pCur->pNext;
 79         pCur->pNext = NULL;    
 80 
 81     }
 82     else
 83     {
 84         pReturn = new Snake_Base;
 85         pReturn->coordinate_cur = _snake.coordinate_cur;
 86     }
 87     
 88     switch(_snake.int_direction)
 89     {
 90         case EN_DIR_UP:
 91             _snake.coordinate_cur.int_x -= 1;
 92             break;
 93         case EN_DIR_DOWN:    
 94             _snake.coordinate_cur.int_x += 1;
 95             break;
 96         case EN_DIR_LEFT:    
 97             _snake.coordinate_cur.int_y -= 1;
 98             break;
 99         case EN_DIR_RIGHT:    
100             _snake.coordinate_cur.int_y += 1;
101             break;
102         default:break;
103 
104     }
105     return pReturn;
106 
107 }
108 
109 Snake_Base* Snake::get_snake_base()
110 {
111     return _snake.pNext;
112 
113 }
114 
115 SnakeHead* Snake::get_snake_head()
116 {
117     return &_snake;
118 
119 }
120 }

   然后,根据需要修改了game.h和game.cc

 1  ///
 2  /// @file    game.h
 3  /// @author  marrs(chenchengxi993@gmail.com)
 4  /// @date    2017-07-15 11:42:03
 5  ///
 6 
 7 #ifndef __GAME_H__
 8 #define __GAME_H__
 9 
10 #include "map.h"
11 #include "snake.h"
12 
13 namespace marrs{
14 
15 class Game
16 {
17     public:
18         int init();    
19         int output_map();    
20         int refresh_map();
21         int gen_random_point();
22         int reset_random_point();
23         
24         int forward();
25         int check_collision();
26 
27     private:
28         Map _map;
29         Snake _snake;    
30         Coordinate _random_point;
31 };
32  
33 }
34 
35 #endif

  新增了一些方法。 

  1  ///
  2  /// @file    game.cc
  3  /// @author  marrs(chenchengxi993@gmail.com)
  4  /// @date    2017-07-15 18:05:24
  5  ///
  6  
  7 #include <iostream>
  8 #include "game.h"
  9 
 10 namespace marrs{
 11 
 12 int Game::init()
 13 {
 14     Coordinate coordinate = _map.get_map_center_pos();
 15     _snake.init('O', EN_DIR_DOWN, 1, coordinate);    
 16     
 17     MapBase map;
 18     map.char_icon = 'O';
 19     map.int_type = EN_MAP_SNAKE;
 20     _map.set_map_val(coordinate.int_x, coordinate.int_y, map);
 21 
 22     reset_random_point();
 23 
 24     output_map();
 25     return 0;
 26 
 27 }
 28 
 29 int Game::output_map()
 30 {
 31     int int_map_x_size = _map.get_x_size();
 32     int int_map_y_size = _map.get_y_size();
 33 
 34     for (int int_idx = 0; int_idx < int_map_x_size; ++int_idx)
 35     {
 36         for (int int_idy = 0; int_idy < int_map_y_size; ++int_idy)
 37         {
 38             _map.output_map(int_idx, int_idy);
 39         }
 40         cout << endl;
 41     }
 42     return 0;
 43     
 44 }
 45 
 46 int Game::refresh_map()
 47 {
 48     int int_map_y_size = _map.get_y_size();
 49     printf("33[%dA", int_map_y_size);
 50     output_map();
 51     return 0;
 52 
 53 }
 54 
 55 int Game::gen_random_point()
 56 {
 57     while(_random_point.int_x == 0)
 58     {
 59         _random_point.int_x = random(_map.get_x_size());
 60     }
 61     while(_random_point.int_x == 0)
 62     {
 63         _random_point.int_y = random(_map.get_y_size());
 64     }
 65     return 0;
 66     
 67 }
 68 
 69 int Game::reset_random_point()
 70 {
 71     _random_point.int_x = 0;
 72     _random_point.int_y = 0;
 73     return 0;
 74 }
 75 
 76 int Game::forward()
 77 {
 78     int int_ret = check_collision();
 79     if(int_ret)
 80     {
 81         return int_ret;
 82     }
 83 
 84     Snake_Base* snake_tmp = _snake.forward();
 85     
 86     
 87     _map.reset_point(snake_tmp->coordinate_cur.int_x, snake_tmp->coordinate_cur.int_y);
 88     delete snake_tmp;
 89     MapBase map_tmp;
 90     map_tmp.int_type = EN_MAP_SNAKE;
 91     map_tmp.char_icon = _snake.get_snake_head()->char_icon;
 92     _map.set_map_val(_snake.get_snake_head()->coordinate_cur.int_x,
 93                 _snake.get_snake_head()->coordinate_cur.int_y,
 94                 map_tmp);
 95 
 96     return 0;
 97 }
 98 
 99 int Game::check_collision()
100 {
101 
102     return 0;
103 }
104 
105 }

  可以测试一下

 1  ///
 2  /// @file    main.cc
 3  /// @author  marrs(chenchengxi993@gmail.com)
 4  /// @date    2017-07-15 18:20:18
 5  ///
 6  
 7 #include "game.h" 
 8 using namespace marrs;
 9 
10 int main()
11 {
12     Game game;
13     game.init();
14     for(int int_idx = 0; int_idx < 5; ++int_idx)
15     {
16         game.forward();    
17         game.refresh_map();
18         sleep(1);
19     }
20     
21 
22 
23 
24     return 0;
25 }

  预期的结果,是“OO”向下移动了五个位置,一秒一次。

  执行程序:

  开始

 1 [ccx@ubuntu ~/Retro_Snaker/bin]$>./game.exe 
 2 ++====================================++
 3 ||                                    ||
 4 ||                                    ||
 5 ||                                    ||
 6 ||                                    ||
 7 ||                                    ||
 8 ||                                    ||
 9 ||                                    ||
10 ||                                    ||
11 ||                                    ||
12 ||                  OO                ||
13 ||                                    ||
14 ||                                    ||
15 ||                                    ||
16 ||                                    ||
17 ||                                    ||
18 ||                                    ||
19 ||                                    ||
20 ||                                    ||
21 ++====================================++

  结束

 1 [ccx@ubuntu ~/Retro_Snaker/bin]$>./game.exe 
 2 ++====================================++
 3 ||                                    ||
 4 ||                                    ||
 5 ||                                    ||
 6 ||                                    ||
 7 ||                                    ||
 8 ||                                    ||
 9 ||                                    ||
10 ||                                    ||
11 ||                                    ||
12 ||                                    ||
13 ||                                    ||
14 ||                                    ||
15 ||                                    ||
16 ||                                    ||
17 ||                  OO                ||
18 ||                                    ||
19 ||                                    ||
20 ||                                    ||
21 ++====================================++
22 [ccx@ubuntu ~/Retro_Snaker/bin]$>

  可以看到,它从第12行,移到了第17行,符合预期。

  未完待续....

  github:https://github.com/ccx19930930/Retro_Snaker

原文地址:https://www.cnblogs.com/chinxi/p/7185309.html