自制贪吃蛇——主场景

  昨天突发奇想,想自己实现贪吃蛇。想了许久,定了一个方案,简要说明一下:

    1、主场景用数组表示,通过x和y坐标计算数组下标,每个元素是一个结构体,存着当前位置是什么类型,展示什么图形

    2、蛇用链表表示,每个结点存储着当前坐标,展示的图形等信息,头结点还存着前进方向等信息

    3、定期刷新界面

    4、直接在终端下运行,界面不会太好看

 

  先写个主场景吧。

  首先,是一个枚举和一个结构体:

 1 enum MapStatus
 2 {
 3     EN_MAP_EMPTY = 0,  //空地
 4     EN_MAP_WALL,       //边界
 5     EN_MAP_NEW_NODE,   //新节点
 6     EN_MAP_SNAKE,      //
 7 
 8 };
 9 
10 struct MapBase
11 {
12     int int_type;
13     char char_icon;
14 };

  思考了一下,场景需要的功能有:

    1、获取指定坐标的信息

    2、设置指定坐标的信息

    3、获取场景的大小

    4、重置一个坐标的信息

    5、获取中心坐标

    6、输出

  于是,有了以下类:

 1  ///
 2  /// @file    map.h
 3  /// @author  marrs(chenchengxi993@gmail.com)
 4  /// @date    2017-07-15 09:45:50
 5  ///
 6 
 7 #ifndef __MAP_H__
 8 #define __MAP_H__
 9 
10 #include "define.h" 
11 
12 namespace marrs{
13 
14 class Map
15 {
16     public:
17         Map();
18         Map(int int_x, int int_y);
19         ~Map();
20 
21     public:
22         int init();
23         int get_map_val(int int_x, int int_y, MapBase & map_val);
24         int set_map_val(int int_x, int int_y, MapBase int_val);
25 
26         int get_x_size();
27         int get_y_size();
28 
29         int reset_point(int int_x, int int_y);
30 
31         Coordinate get_map_center_pos();
32 
33         friend ostream & operator << (ostream & output, MapBase & map); 
34 
35         int output_map(int int_x, int int_y);
36 
37     private:
38         int get_map_pos(int int_x, int int_y);
39 
40     private:
41         int _int_x_size;
42         int _int_y_size;
43         MapBase * _p_map;
44         bool _bool_is_init_fail;
45 };
46  
47 }
48 
49 #endif

  重载了输出流运算符只是为了方便输出。场景用一个一维数组存储,目的是为了可以定制场景大小。后期可能会做成可以在游戏中随时设置场景大小。

  各自的实现:

  1  ///
  2  /// @file    map.cc
  3  /// @author  marrs(chenchengxi993@gmail.com)
  4  /// @date    2017-07-15 10:08:01
  5  ///
  6  
  7 #include "map.h"
  8 
  9 namespace marrs{
 10 
 11 Map::Map()
 12 : _int_x_size(20)
 13 , _int_y_size(20)
 14 {
 15     _bool_is_init_fail = init();
 16 }
 17 
 18 Map::Map(int int_x, int int_y)
 19 : _int_x_size(int_x)
 20 , _int_y_size(int_y)
 21 {
 22     _bool_is_init_fail = init();
 23 }
 24 
 25 Map::~Map()
 26 {
 27     delete [] _p_map;
 28 }
 29 
 30 int Map::init()
 31 {
 32     int map_size = _int_x_size * _int_y_size;
 33     _p_map = new MapBase[map_size];
 34     if (_p_map == NULL)
 35     {
 36         return true;
 37     }
 38     int int_pos;
 39 
 40     for (int int_idx = 0; int_idx < _int_x_size; ++int_idx)
 41     {
 42         for (int int_idy = 0; int_idy < _int_y_size; ++int_idy)
 43         {
 44             int_pos = get_map_pos(int_idx, int_idy);
 45             if ((int_idx == 0 && (int_idy == 0 || int_idy == _int_y_size - 1))
 46                 || (int_idx == _int_x_size - 1 && (int_idy == 0 || int_idy == _int_y_size - 1)))
 47             {
 48                 _p_map[int_pos].int_type = EN_MAP_WALL;
 49                 _p_map[int_pos].char_icon = '+';
 50             }
 51             else if (int_idx == 0 || int_idx == _int_x_size - 1)
 52             {
 53                 _p_map[int_pos].int_type = EN_MAP_WALL;
 54                 _p_map[int_pos].char_icon = '=';
 55             }
 56             else if (int_idy == 0 || int_idy == _int_y_size - 1)
 57             {
 58                 _p_map[int_pos].int_type = EN_MAP_WALL;
 59                 _p_map[int_pos].char_icon = '|';
 60             }
 61             else
 62             {
 63                 reset_point(int_idx, int_idy);
 64             }
 65         }
 66     }
 67     return false;
 68 
 69 }
 70 
 71 int Map::get_map_pos(int int_x, int int_y)
 72 {
 73     if (int_x >= _int_x_size || int_y >= _int_y_size)
 74     {
 75         return -1;
 76     }
 77     
 78     int int_pos = int_y * _int_x_size + int_x;
 79     return int_pos;
 80 }
 81 
 82 int Map::get_map_val(int int_x, int int_y, MapBase & map_val)
 83 {
 84     int int_pos = get_map_pos(int_x, int_y);
 85     if (int_pos == -1)
 86     {
 87         return -1;
 88     }
 89     map_val = _p_map[int_pos];
 90     return map_val.int_type;
 91 
 92 }
 93 
 94 int Map::set_map_val(int int_x, int int_y, MapBase map_val)
 95 {
 96     int int_pos = get_map_pos(int_x, int_y);
 97     if (int_pos == -1)
 98     {
 99         return -1;
100     }
101     _p_map[int_pos] = map_val;
102     return map_val.int_type;
103 
104 }
105 
106 int Map::get_x_size()
107 {
108     return _int_x_size;
109 
110 }
111 
112 int Map::get_y_size()
113 {
114     return _int_y_size;
115 
116 }
117 
118 int Map::reset_point(int int_x, int int_y)
119 {
120     int int_pos = get_map_pos(int_x, int_y);
121     _p_map[int_pos].int_type = EN_MAP_EMPTY;
122     _p_map[int_pos].char_icon = ' ';
123     return 0;
124 
125 }
126 
127 Coordinate Map::get_map_center_pos()
128 {
129     Coordinate coordinate;
130     coordinate.int_x = (_int_x_size + 1) / 2;
131     coordinate.int_y = (_int_y_size + 1) / 2;
132     return coordinate;    
133 
134 }
135 
136 ostream & operator << (ostream & output, MapBase & map)
137 {
138     output << map.char_icon;
139     return output;
140 }
141 
142 int Map::output_map(int int_x, int int_y)
143 {
144     int int_pos = get_map_pos(int_x, int_y);
145     cout << _p_map[int_pos] << _p_map[int_pos];
146 
147     return 0;
148 }
149 
150 }
View Code

 

  这时候可以来测试一下场景是不是正常的。写了个game类,之后所有的各种游戏功能都加在里面。

 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 
12 namespace marrs{
13 
14 class Game
15 {
16     public:
17         int init();    
18         int output_map();    
19         int refresh_map();
20 
21     private:
22         Map _map;
23 };
24  
25 }
26 
27 #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 
15     output_map();
16     return 0;
17 
18 }
19 
20 int Game::output_map()
21 {
22     int int_map_x_size = _map.get_x_size();
23     int int_map_y_size = _map.get_y_size();
24 
25     for (int int_idx = 0; int_idx < int_map_x_size; ++int_idx)
26     {
27         for (int int_idy = 0; int_idy < int_map_y_size; ++int_idy)
28         {
29             _map.output_map(int_idx, int_idy);
30         }
31         cout << endl;
32     }
33     return 0;
34     
35 }
36 
37 int Game::refresh_map()
38 {
39     int int_map_y_size = _map.get_y_size();
40     printf("\033[%dA", int_map_y_size);
41     output_map();
42     return 0;
43 
44 }
45 
46 }
View Code

 

 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.refresh_map();
17         sleep(1);
18     }
19     
20 
21 
22 
23     return 0;
24 }

  编译之后,预期的结果,是打印个框出来,并且5秒之后退出。

  结果如下:

[ccx@ubuntu ~/Retro_Snaker/bin]$>./game.exe 
++====================================++
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
||                                    ||
++====================================++
[ccx@ubuntu ~/Retro_Snaker/bin]$>

  符合预期。

 

  未完待续....

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

posted @ 2017-07-15 20:17  曾经时光  阅读(449)  评论(2编辑  收藏  举报