使用c++实现经典小游戏《连连看》
背景- 《连连看》的算法逻辑并不复杂,主要是游戏界面如何显式。目前只能用终端显示,所以,写完后,测试了两局,玩的我头昏脑涨的。
- 除了显示,另一个比较复杂的就是如何判断两张牌是否可以消除。鉴于受限于屏幕的大小,所以牌数不会很多,可以采用暴力枚举的方式来判断。
- 效果展示图
- x代表纵坐标,y代表横坐标
- 目前只添加了3种图形,后续可以直接在map中随意添加。
- bool Game::isAllowedToErase():判断两个位置的牌是否可以消除
-
根据判断两牌相邻时,牌的移动方向和剩余转向次数,可以判断两牌是否可以消除
bool Game::isAllowedToErase(const int &_x1, const int &_y1, const int &_x2, const int &_y2, Dir _dir, int _times) const { // 在上面 if (_x1 == _x2 - 1 && _y1 == _y2 && (_dir == Dir::Down || _dir == Dir::Unknown || _times > 0)) { return true; } // 在下面 if (_x1 == _x2 + 1 && _y1 == _y2 && (_dir == Dir::Up || _dir == Dir::Unknown || _times > 0)) { return true; } // 在左边 if (_x1 == _x2 && _y1 == _y2 - 1 && (_dir == Dir::Right || _dir == Dir::Unknown || _times > 0)) { return true; } // 在右边 if (_x1 == _x2 && _y1 == _y2 + 1 && (_dir == Dir::Left || _dir == Dir::Unknown || _times > 0)) { return true; } std::vector
dirs = getAllowedDirs(_x1,_y1,_dir,_times); for(auto dir:dirs){ switch (dir) { case Dir::Up: if(_dir==Dir::Left||_dir==Dir::Right){ if(isAllowedToErase(_x1-1,_y1,_x2,_y2,Dir::Up,_times-1)){ return true; } }else{ if(isAllowedToErase(_x1-1,_y1,_x2,_y2,Dir::Up,_times)){ return true; } } break; case Dir::Down: if(_dir==Dir::Left||_dir==Dir::Right){ if(isAllowedToErase(_x1+1,_y1,_x2,_y2,Dir::Down,_times-1)){ return true; } }else{ if(isAllowedToErase(_x1+1,_y1,_x2,_y2,Dir::Down,_times)){ return true; } } break; case Dir::Left: if(_dir==Dir::Up||_dir==Dir::Down){ if(isAllowedToErase(_x1,_y1-1,_x2,_y2,Dir::Left,_times-1)){ return true; } }else{ if(isAllowedToErase(_x1,_y1-1,_x2,_y2,Dir::Left,_times)){ return true; } } break; case Dir::Right: if(_dir==Dir::Up||_dir==Dir::Down){ if(isAllowedToErase(_x1,_y1+1,_x2,_y2,Dir::Right,_times-1)){ return true; } }else{ if(isAllowedToErase(_x1,_y1+1,_x2,_y2,Dir::Right,_times)){ return true; } } break; default: break; } } return false; }
-
- std::vector
Game::getAllowedDirs():获取牌可以移动的方向 - 通过当前移动方向和剩余转向次数,获取当前牌下一步可选择的移动方向
std::vector
Game::getAllowedDirs(const int& _x,const int& _y,Dir _dir, int _times) const{ std::vector res; switch (_dir) { case Dir::Unknown: if(isValid(_x-1,_y)){ res.push_back(Dir::Up); } if(isValid(_x+1,_y)){ res.push_back(Dir::Down); } if(isValid(_x,_y-1)){ res.push_back(Dir::Left); } if(isValid(_x,_y+1)){ res.push_back(Dir::Right); } break; case Dir::Up: if(isValid(_x-1,_y)){ res.push_back(Dir::Up); } if(_times<=0){ break; } if(isValid(_x,_y-1)){ res.push_back(Dir::Left); } if(isValid(_x,_y+1)){ res.push_back(Dir::Right); } break; case Dir::Down: if(isValid(_x+1,_y)){ res.push_back(Dir::Down); } if(_times<=0){ break; } if(isValid(_x,_y-1)){ res.push_back(Dir::Left); } if(isValid(_x,_y+1)){ res.push_back(Dir::Right); } break; case Dir::Left: if(isValid(_x,_y-1)){ res.push_back(Dir::Left); } if(_times<=0){ break; } if(isValid(_x-1,_y)){ res.push_back(Dir::Up); } if(isValid(_x+1,_y)){ res.push_back(Dir::Down); } break; case Dir::Right: if(isValid(_x,_y+1)){ res.push_back(Dir::Right); } if(_times<=0){ break; } if(isValid(_x-1,_y)){ res.push_back(Dir::Up); } if(isValid(_x+1,_y)){ res.push_back(Dir::Down); } break; default: break; } return res; }
- 通过当前移动方向和剩余转向次数,获取当前牌下一步可选择的移动方向
用c++写小游戏,最痛苦的便是游戏画面显示,本来打算这个游戏想想怎么用可视化的方法写出来,但是为了亲自体验一把cmake,还是选择用终端显示了。可以说,是为了cmake这点醋,包了《连连看》这顿饺子。
(想要源码的可以私信我)