昨天突发奇想,想自己实现贪吃蛇。想了许久,定了一个方案,简要说明一下:
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 }
这时候可以来测试一下场景是不是正常的。写了个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("