栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

C++之《连连看》

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++之《连连看》

简介

使用c++实现经典小游戏《连连看》

背景
  1. 《连连看》的算法逻辑并不复杂,主要是游戏界面如何显式。目前只能用终端显示,所以,写完后,测试了两局,玩的我头昏脑涨的。
  2. 除了显示,另一个比较复杂的就是如何判断两张牌是否可以消除。鉴于受限于屏幕的大小,所以牌数不会很多,可以采用暴力枚举的方式来判断。
实现效果
  1. 效果展示图
  2. x代表纵坐标,y代表横坐标
  3. 目前只添加了3种图形,后续可以直接在map中随意添加。
关键算法
  1. 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;
      }
      
  2. 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这点醋,包了《连连看》这顿饺子。


(想要源码的可以私信我)

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038322.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号