C++迷宫游戏详解

个人主页:[PingdiGuo_guo]

收录专栏:[C++干货专栏]

大家好呀,我是PingdiGuo_guo,今天我们来学习用C++实现一个迷宫游戏。

目录

1.迷宫的具体步骤

1.1.迷宫的初始化

1.2.寻路算法

1.DFS算法

2.BFS算法

1.3.移动

2.总结


C++迷宫游戏的实现需要考虑迷宫的表示方式、寻路算法以及代码实现。在本篇博客中,我们将逐步实现一个C++迷宫游戏。

1.迷宫的具体步骤

1.迷宫的初始化:包括选择难度,随机生成迷宫,以及玩家移动后的迷宫

2.寻路算法:在迷宫中,我们需要一个正确的算法来判断当前路径是否正确

3.移动:玩家可以按w,a,s,d键来实现移动

1.1.迷宫的初始化

迷宫的初始化具体实现步骤如下:

1. 包含所需的头文件 <bits/stdc++.h>。
2. 使用命名空间 std。
3. 声明迷宫的相关常量,如空格、墙、路径、起点和终点的字符。
4. 声明随机数生成器 gen。
5. 声明迷宫的宽度和高度变量
6. 声明迷宫的二维字符向量 cells。
7. 声明起点和终点的位置变量。
8. 实现函数 generateMaze() 用于生成随机迷宫
   - 使用随机数生成器生成起点和终点的随机位置
   - 遍历迷宫的每个位置,根据一定的概率生成墙或路径,并将起点和终点的字符设置为对应的字符。
9. 实现函数 printMaze() 用于打印迷宫。
   - 遍历迷宫的每个位置,打印对应的字符。
10. 在 main() 函数中:
    - 提示用户输入迷宫的宽度和高度
    - 调整 cells 的大小为指定的宽度和高度,并初始化为空格字符。
    - 生成随机迷宫。
    - 打印迷宫。
11. 返回 0,表示程序成功执行完毕。

以下是具体的代码实现:

​
#include <bits/stdc++.h>

using namespace std;

// Maze cell types
const char EMPTY = ' ';
const char WALL = '#';
const char PATH = '.';
const char START = 'S';
const char MEND = 'G';

// Random number generator
random_device rd;
mt19937 gen(rd());

// Maze dimensions
int width, height;

// Maze grid
vector<vector<char>> cells;

// Start and end positions
pair<int, int> start, mend;

// Generate random maze
void generateMaze() {
    // Set start and end points randomly
    uniform_int_distribution<> dis(0, width - 1);
    start = make_pair(dis(gen), dis(gen));
    mend = make_pair(dis(gen), dis(gen));

    // Generate empty cells with 40% walls
    uniform_real_distribution<double> prob(0.0, 1.0);
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            if (make_pair(i, j) == start) {
                cells[i][j] = START;
            } else if (make_pair(i, j) == mend) {
                cells[i][j] = MEND;
            } else {
                if (prob(gen) <= 0.4) {
                    cells[i][j] = WALL;
                } else {
                    cells[i][j] = PATH;
                }
            }
        }
    }
}

// Print maze
void printMaze() {
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            cout << cells[i][j] << " ";
        }
        cout << endl;
    }
}

int main() {
    // Set maze dimensions
    cout << "宽度: ";
    cin >> width;
    cout << "高度: ";
    cin >> height;

    // Initialize maze cells with empty spaces
    cells.resize(width, vector<char>(height, EMPTY));

    // Generate random maze
    generateMaze();

    // Print maze
    printMaze();

    return 0;
}

​

1.2.寻路算法

接下来,我们需要选择一个最优的寻路算法。在迷宫游戏中,常用的寻路算法有深度优先搜索(DFS)和广度优先搜索(BFS)。这两种算法都可以用于寻找迷宫的路径,但适用的场景和复杂度略有不同。

1.DFS算法

DFS算法通过递归的方式进行搜索,每次都先选择一个方向前进,直到无法前进为止,然后回溯到上一个节点继续搜索。DFS算法的复杂度为O(V + E),其中V是节点的数量,E是边的数量。我们可以分析出具体步骤:

1. 定义一个名为DFS的函数,接收当前位置的坐标x和y作为参数,并返回一个布尔值。

2. 首先,判断当前位置是否超出了迷宫的边界,如果是,则返回false。

3. 接着,判断当前位置是否为墙壁(用'#'表示),如果是,则返回false。

4. 然后,判断当前位置是否为终点(用'G'表示),如果是,则返回true,表示已经找到了一条通路。

5. 如果以上条件都不满足,说明当前位置是可走的空地(用'.'表示),将当前位置标记为已访问(用'#'代替原来的空地)

6. 通过递归调用DFS函数,按照上、下、左、右的顺序尝试前进,即DFS(x + 1, y)、DFS(x - 1, y)、DFS(x, y + 1)、DFS(x, y - 1)。

7. 如果在某个方向上的递归调用返回true,表示找到了通路,则返回true。

8. 如果以上递归调用都没有找到通路,则说明当前位置不是通路,将当前位置标记为未访问(用' '代替原来的'#'),进行回溯。

9. 最后,返回false,表示没有找到通路。

通过以上步骤,使用DFS算法可以在迷宫中寻找通路。

以下是具体的代码实现:

​
bool DFS(int x, int y) {
    if (x < 0 || x >= N || y < 0 || y >= N) {
        return false;
    }
    if (maze[x][y] == '#') {
        return false;
    }
    if (maze[x][y] == 'G') {
        return true;
    }
    maze[x][y] = '#';  // 标记为已访问
    if (DFS(x + 1, y) || DFS(x - 1, y) || DFS(x, y + 1) || DFS(x, y - 1)) {
        return true;
    }
    maze[x][y] = '.';  // 回溯,标记为未访问
    return false;
}

​

2.BFS算法

BFS算法使用队列来存储待访问的节点,每次都从队列中取出一个节点进行访问,并将其周围的节点加入队列。BFS算法的复杂度为O(V + E),其中V是节点的数量,E是边的数量。我们可以分析出以下步骤:

1. 定义一个名为BFS的函数,接收起始位置的坐标x和y作为参数,并返回一个布尔值。

2. 创建一个队列(queue),并将起始位置加入队列中。

3. 使用while循环,当队列不为空时执行循环。

4. 在循环中,首先从队列中取出队首元素,即当前位置的坐标。

5. 接着,判断当前位置是否超出了迷宫的边界,如果是,则继续下一次循环。

6. 然后,判断当前位置是否为墙壁(用'#'表示),如果是,则继续下一次循环。

7. 接着,判断当前位置是否为终点(用'G'表示),如果是,则返回true,表示已经找到了一条通路。

8. 若以上条件都不满足说明当前位置是可走的空地(用'.'表示),将当前位置标记为已访问(用'#'代替原来的空地)。

9. 将当前位置的上、下、左、右四个方向的相邻坐标加入队列中,即({x + 1, y})、({x - 1, y})、({x, y + 1})、({x, y - 1})。

10. 循环结束后,说明队列已经为空且没有找到通路,返回false。

通过以上步骤,使用BFS算法可以在迷宫中寻找通路。

bool BFS(int x, int y) {
    queue<pair<int, int>> q;
    q.push({x, y});
    while (!q.empty()) {
        pair<int, int> curr = q.front();
        q.pop();
        int x = curr.first;
        int y = curr.second;
        if (x < 0 || x >= N || y < 0 || y >= N) {
            continue;
        }
        if (maze[x][y] == '#') {
            continue;
        }
        if (maze[x][y] == 'G') {
            return true;
        }
        maze[x][y] = '#';  // 标记为已访问
        q.push({x + 1, y});
        q.push({x - 1, y});
        q.push({x, y + 1});
        q.push({x, y - 1});
    }
    return false;
}

1.3.移动

在迷宫游戏中,玩家需要根据输入的指令来移动。常见的移动指令有上、下、左、右四个方向。我们可以通过更新玩家的坐标来实现移动。我们可以分析出以下步骤:

1. 定义一个名为movePlayer的函数,接收玩家当前位置的坐标x和y的引用,以及移动的方向direction作为参数,并返回一个布尔值。

2. 根据输入的方向指令,使用条件判断来判断移动的方向。如果是"W"或"w",则判断玩家上方的位置是否为墙壁,如果不是,则更新玩家的坐标x减1;如果是"S"或"s",则判断玩家下方的位置是否为墙壁,如果不是,则更新玩家的坐标x加1;如果是"A"或"a",则判断玩家左边的位置是否为墙壁,如果不是,则更新玩家的坐标y减1;如果是"D"或"d",则判断玩家右边的位置是否为墙壁,如果不是,则更新玩家的坐标y加1。

3. 如果输入的方向指令不是以上四种有效指令,则返回false,表示无效指令。

4. 在玩家移动后,返回true,表示移动成功

在主函数中,使用DFS算法找到了一条路径后,可以进入游戏循环。循环中,首先打印迷宫,然后提示玩家输入移动指令(W上,S下,A左,D右)或者Q退出。根据玩家输入的指令调用movePlayer函数来移动玩家,并判断是否成功找到出口。如果玩家输入Q,则跳出循环,游戏结束。

通过以上步骤,玩家可以在迷宫中根据输入指令进行移动,并且在找到出口时会进行相应的提示。

具体代码实现:

bool movePlayer(int& x, int& y, char direction) {
    // 根据指令更新玩家的坐标
    if (direction == 'W' || direction == 'w') {  // 上
        if (maze[x - 1][y] != '#') {
            x--;
        }
    } else if (direction == 'S' || direction == 's') {  // 下
        if (maze[x + 1][y] != '#') {
            x++;
        }
    } else if (direction == 'A' || direction == 'a') {  // 左
        if (maze[x][y - 1] != '#') {
            y--;
        }
    } else if (direction == 'D' || direction == 'd') {  // 右
        if (maze[x][y + 1] != '#') {
            y++;
        }
    } else {
        return false;  // 无效指令
    }
    return true;
}

在主函数中,我们可以在寻路算法之后添加以下代码,以实现玩家的移动:
// 使用DFS算法寻找路径
bool found = DFS(startX, startY);
if (found) {
    cout << "找到了一条路径!" << endl;
    cout << "请开始游戏!" << endl;

    char direction;
    while (true) {
        printMaze(startX, startY);  // 打印迷宫
        cout << "请输入指令(W上, S下, A左, D右)或者Q退出:" << endl;
        cin >> direction;
        if (direction == 'Q' || direction == 'q') {
            break;
        }
        movePlayer(startX, startY, direction);  // 移动玩家
        if (startX == endX && startY == endY) {
            cout << "恭喜你成功找到出口!" << endl;
            break;
        }
    }
} else {
    cout << "没有找到路径!" << endl;
}

上述代码通过循环接受玩家的输入指令,并根据指令更新玩家的坐标,实现玩家在迷宫中的移动。当玩家到达终点时,游戏结束。

2.总结

本篇博客讲解了实现迷宫的几个步骤与代码,希望大家有所收获。感谢大家的支持与观看,如果有好的建议欢迎留言!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/368105.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【js逆向】scrapy基础

目录 一, 爬虫工程化 二, scrapy简介 三, Scrapy工作流程(重点) 四, scrapy安装 4.1 pip 安装 4.2 wheel安装 五, Scrapy实例 六, 自定义数据传输结构item 七, scrapy使用小总结 一, 爬虫工程化 在之前的学习中我们已经掌握了爬虫这门技术需要的大多数的技术点, 但是我…

MAX31865读取PT100/PT1000电阻值

1、芯片介绍 MAX31865是简单易用的热敏电阻至数字输出转换器,优化用于铂电阻温度检测器(RTD)。外部电阻设置RTD灵敏度,高精度Δ- Σ ADC将RTD电阻与基准电阻之比转换为数字输出。MAX31865输入具有高达45V的过压保护,提供可配置的RTD及电缆开路、短路条件检测。 2、芯片特点…

金和OA jc6 UploadFileBlock 任意文件上传漏洞复现

0x01 产品简介 金和OA协同办公管理系统软件(简称金和OA),本着简单、适用、高效的原则,贴合企事业单位的实际需求,实行通用化、标准化、智能化、人性化的产品设计,充分体现企事业单位规范管理、提高办公效率的核心思想,为用户提供一整套标准的办公自动化解决方案,以帮助…

光伏移动业主端:操作便捷,功能齐全

鹧鸪云 为了满足日益增长的移动设备使用需求&#xff0c;提高用户体验&#xff0c;鹧鸪云研发出移动业主端&#xff0c;旨在提供更加高效、便捷的操作体验&#xff0c;具有省时省力、方便操作、功能齐全等优势&#xff0c;能够带来更好的使用体验和智能化服务。 优势&#xf…

2024年【道路运输企业安全生产管理人员】考试报名及道路运输企业安全生产管理人员作业模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 道路运输企业安全生产管理人员考试报名是安全生产模拟考试一点通总题库中生成的一套道路运输企业安全生产管理人员作业模拟考试&#xff0c;安全生产模拟考试一点通上道路运输企业安全生产管理人员作业手机同步练习。…

Cmake语法学习3:语法

1.双引号 1.1 命令参数 1&#xff09;介绍 命令中多个参数之间使用空格进行分隔&#xff0c;而 cmake 会将双引号引起来的内容作为一个整体&#xff0c;当它当成一个参数&#xff0c;假如你的参数中有空格&#xff08;空格是参数的一部分&#xff09;&#xff0c;那么就可以使…

LLM之RAG理论(九)| 如何在LLM应用程序中提高RAG结果:从基础到高级

如果你正在用LLM&#xff08;大型语言模型&#xff09;构建产品或者功能&#xff0c;你可能会使用一种名为RAG&#xff08;检索增强生成&#xff09;的技术。RAG允许用户将LLM的训练数据中不可用的外部数据集成到LLM的文本生成过程中&#xff0c;这可以大大减少幻觉的产生&…

PADS VX 2.7安装记录

PADS 画PCB&#xff0c;Orcad用来画原理图&#xff0c;是一种常见的layout PCB板的方式。 一、资源&#xff1a; 资源1&#xff1a;百度云安装包&#xff1a;PADS VX 2.7 提取码&#xff1a;dbjm 二、安装 2.1 双击打开安装包 在PADS VX 2.7/PADSVX.2.7_ESDM文件夹下双击se…

DevOps落地笔记-11|持续集成:软件持续集成,发布信手拈来

上一讲我主要介绍了如何快速的构建环境&#xff0c;以及测试阶段对环境的要求。现在测试环境已经不是阻碍软件开发的障碍了&#xff0c;但另一个问题又出现了&#xff1a;每次测试结果不是不理想&#xff0c;就是问题太多无法继续测试。这是因为&#xff0c;团队成员平时都在自…

mysql升级到8.x

1.下载和安装 1.1.下载 mysql下载地址&#xff1a; https://dev.mysql.com/downloads/mysql/5.5.html?os31&version5.1 应该下载这个类似版本 mysql-8.0.36-linux-glibc2.17-x86_64-minimal.tar.xz 1.2 安装 解压&#xff1a; tar xvf mysql-8.0.36-linux-glibc2.17…

学习Spring的第十三天

非自定义bean注解开发 设置非自定义bean : 用bean去修饰一个方法 , 最后去返回 , spring就把返回的这个对象,放到Spring容器 一 :名字 : 如果bean配置了参数 , 名字就是参数名 , 如果没有 , 就是方法名字 二 : 如果方法产生对象时 , 需要注入数据 , 在方法参数设置即可 , …

Acwing---802.区间和

区间和 1.题目2.基本思想3.代码实现 1.题目 假定有一个无限长的数轴&#xff0c;数轴上每个坐标上的数都是 0。 现在&#xff0c;我们首先进行 n 次操作&#xff0c;每次操作将某一位置 x 上的数加 c。 接下来&#xff0c;进行 m次询问&#xff0c;每个询问包含两个整数 l 和…

基于Web停车场管理系统

技术架构&#xff1a; Spring MVC JSP MySQL 有需要该项目的小伙伴可以私信我你的Q。 功能描述&#xff1a; 基于Web停车场管理系统主要用于实现停车场相关信息管理&#xff0c;基本功能包括&#xff1a;系统信息管理模块、车位信息管理模块、IC卡信息管理模块、固定车主…

【Docker篇】Linux安装Docker、docker安装mysql、redis、rabbitmq

1.Linux安装docker 官方帮助文档&#xff1a;Install Docker Engine on CentOS | Docker Docs 1.1安装命令 # 1. 卸载之前的dockersudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate…

编程实例分享,眼镜店电脑系统软件,配件验光管理顾客信息记录查询系统软件教程

编程实例分享&#xff0c;眼镜店电脑系统软件&#xff0c;配件验光管理顾客信息记录查询系统软件教程 一、前言 以下教程以 佳易王眼镜店顾客档案管理系统软件V16.0为例说明 如上图&#xff0c; 点击顾客档案&#xff0c;在这里可以对顾客档案信息记录保存查询&#xff0c;…

Windows Server 2025 Active Directory 新变化

自 Windows Server 2016 以来&#xff0c;AD DS 尚未收到任何重大更新&#xff0c;并且 Server 2019/2022 中的功能级别没有增加。随着长期服务渠道 (LTSC) 中操作系统的下一个版本的发布&#xff0c;该版本暂且被称为 Windows Server 2025。 Windows Server 2025 新功能级别 …

C++ 日期类的实现

目录 前言 日期类中的成员函数和成员变量 日期类中成员函数的详解和实现 1.天数前后的判断 2.天数加减的实现 3.前置 && 后置 4.计算天数差值 前言 日期类的实现将综合前面所学的&#xff08;类的6个默认成员函数&#xff09;&#xff0c;进一步理解和掌握类的…

SOME/IP SD 协议介绍(四)服务发现通信行为

服务发现通信行为 启动行为 服务发现将根据服务实例处于以下三个阶段之一&#xff1a; • 初始等待阶段 • 重复阶段 • 主要阶段 一旦系统启动并且用于服务实例的接口连接已建立&#xff0c;服务发现将进入该服务实例的初始等待阶段。 在进入初始等待阶段并在发送第一条服…

【C++栈和队列:数据结构中的经典组合,高效处理先进先出与后进先出问题的最佳方案】

[本节目标] 1. stack的介绍和使用 2. queue的介绍和使用 3. priority_queue的介绍和使用 4. 容器适配器 1. stack的介绍和使用 1.1 stack的介绍 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的…

c语言--求第n个斐波那契数列(递归、迭代)

目录 一、概念二、用迭代求第n个斐波那契数1.分析2.完整代码3.运行结果4.如果求第50个斐波那契数呢&#xff1f;看看会怎么样。4.1运行结果&#xff1a;4.2画图解释 三、用迭代的方式求第n个斐波那契数列1.分析2.完整代码3.运行结果4.求第50个斐波那契数4.1运行结果4.2运行结果…
最新文章