• 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<Dir> 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;
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
    2. std::vector Game::getAllowedDirs():获取牌可以移动的方向
      • 通过当前移动方向和剩余转向次数,获取当前牌下一步可选择的移动方向
        std::vector<Dir> Game::getAllowedDirs(const int& _x,const int& _y,Dir _dir, int _times) const{
            std::vector<Dir> 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;
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79

    结语

           用c++写小游戏,最痛苦的便是游戏画面显示,本来打算这个游戏想想怎么用可视化的方法写出来,但是为了亲自体验一把cmake,还是选择用终端显示了。可以说,是为了cmake这点醋,包了《连连看》这顿饺子。


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

  • 相关阅读:
    2.1、如何在FlinkSQL中读取&写出到Kafka
    goroutine 调度
    使用cpolar发布群晖NAS上的网页(2)
    Qt | 拖放、拖动的使用、将文件拖入使用示例
    贝叶斯推理三种方法:MCMC 、HMC和SBI
    O3DE社区发布2310.0版本
    idea2022没有springboot脚手架
    自定义mvc框架复习
    大学生动物介绍网页设计作品 dreamweaver作业静态HTML网页设计模板 保护动物网页作业制作
    使用node实现websocket
  • 原文地址:https://blog.csdn.net/weixin_50749380/article/details/126214093