建立迷宫结构

目录

一、功能要求:

二、解决思路:

三、具体代码:

        1、头文件及函数声明

        2、类

       3、主函数及验证数据有效函数

        4、建立迷宫结构

        5、输出排版

        6、呈现效果

四、后续功能


一、功能要求:

        (1)创建迷宫:根据用户输入的行数n(3<=n<=100)和列数m(3<=m<=100),假定入口始终在(1,1)位置,出口始终在(n,m)位置,创建一个n*m个格子的迷宫,要求屏幕中能显示迷宫信息。

        (2)创建障碍:用户输入障碍数k(1<k<n*m),在创建好的迷宫中,随机将k个格子设置为障碍,不能将入口和出口设置为障碍,要求能在迷宫中显示障碍信息。

        (3)建立迷宫结构。

二、解决思路:

        1、建立结点类、边类、迷宫类。

        2、根据输入信息建立迷宫结构。

三、具体代码:

        1、头文件及函数声明
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <cstdlib> // 包含rand()函数的头文件
#include <ctime>
#include <algorithm>
#include <cmath>//pow()函数

using namespace std;
bool isValidInput(int n, int m, int k);//判断输入合法
int getrandom(int x);//获取随机值
void printblank(int n, int val);//调整迷宫格式
int getbit(int sum);//获取sum位数
        2、类
class Node;
class Edge
{
public:
    int x, y; // 水平和垂直方向
    Node *from;
    Node *to;
    Edge(int x, int y, Node *from, Node *to) : x(x), y(y), from(from), to(to) {}
};

class Node
{
public:
    int row; // 横坐标
    int col; // 纵坐标
    int value;
    vector<Node *> nexts; // 所连接的点集
    vector<Edge *> edges; // 从该点出发的边集
    Node(int value, int row, int col) : value(value), row(row), col(col) {}
};

class maze
{
public:
    unordered_map<int, Node *> nodes;
    unordered_set<Edge *> edges;
    maze(){};
    void creatMaze(int n, int m, int k, vector<vector<int>> &myMaze);
    maze creatGraph(vector<vector<int>> mitrix); // 建无向图
    void print(vector<vector<int>> myMaze, maze graph, int n, int m);
};
       3、主函数及验证数据有效函数

        

int main()
{
    int n, m, k;
    while (true)
    {
        cout << "please input the row and col" << endl;
        cin >> n >> m;
        cout << "please input the number of barriers" << endl;
        cin >> k;
        if (isValidInput(n, m, k))
        {
            break;
        }
    }
    vector<vector<int>> myMaze(n + 2, vector<int>(m + 2, 0));
    maze graphMaze;
    vector<Node *> path;
    graphMaze.creatMaze(n, m, k, myMaze);
    graphMaze = graphMaze.creatGraph(myMaze);
    graphMaze.print(myMaze,graphMaze,n,m); 
    return 0;
}


bool isValidInput(int n, int m, int k) // 验证n,m,k是否在范围中
{
    if (n < 3 || m < 3)
    {
        cout << "too small" << endl;
        return false;
    }
    else if (n > 100 || m > 100)
    {
        cout << "too big" << endl;
        return false;
    }
    else if (k <= 1)
    {
        cout << "too few" << endl;
        return false;
    }
    else if (k >= n * m)
    {
        cout << "to many" << endl;
        return false;
    }
    return true;
}
        4、建立迷宫结构

        0代表路,1代表墙,根据行列数及障碍数,随机生成符合条件的迷宫 

void maze::creatMaze(int n, int m, int k, vector<vector<int>> &myMaze){
    srand(static_cast<unsigned int>(time(nullptr)));
    for (int i = 0; i <= n + 1; i++)
    {
        myMaze[i][0] = 1;
        myMaze[i][m + 1] = 1;
    }
    for (int i = 0; i <= m + 1; i++)
    {
        myMaze[0][i] = 1;
        myMaze[n + 1][i] = 1;
    }

    myMaze[n][m] = 2;
    myMaze[1][1] = 2;

    for (int i = 0; i < k; i++)
    {
        int x = getrandom(n);
        int y = getrandom(m);
        while ((x == 1 && y == 1) || (x == n && y == m) || (myMaze[x][y] == 1))
        {
            x = getrandom(n);
            y = getrandom(m);
        }

        myMaze[x][y] = 1;
    }
}

int getrandom(int x)
{
    int num = rand() % x + 1; // 1到n,1到m
    return num;
}

       

        现在的0,1图并无实际含义,需将其转化为图,为了后续搜索路径功能,用数字代表路径,故将n行m列的迷宫用数字表示,从1到n*m,障碍为0(这里改的有点乱,为了以后表示路径,此时大于1的数为路,0为障碍,注意区分)

maze maze::creatGraph(vector<vector<int>> mitrix)
{
    maze graph;
    int row = mitrix.size() - 2;
    int col = mitrix[0].size() - 2;
    for (int i = 1; i <= row; i++)
    {
        for (int j = 1; j <= col; j++)
        {
            int curValue = (i - 1) * col + j;
            if (mitrix[i][j] != 1)
            {
                if (graph.nodes.find(curValue) == graph.nodes.end())
                {
                    graph.nodes[curValue] = new Node(curValue, i, j);
                }
                vector<pair<int, int>> direction = {{i + 1, j}, {i - 1, j}, {i, j - 1}, {i, j + 1}}; // 其次代表右,左,上,右
                for (auto dir : direction)
                {
                    int curRow = dir.first;
                    int curCol = dir.second;
                    int dirValue = (curRow - 1) * col + curCol;
                    if (mitrix[curRow][curCol] != 1 && curCol > 0 && curRow > 0)
                    {
                        if (graph.nodes.find(dirValue) == graph.nodes.end())
                        {
                            graph.nodes[dirValue] = new Node(dirValue, curRow, curCol);
                        }
                        Node *fromNode = graph.nodes[curValue];
                        Node *toNode = graph.nodes[dirValue];
                        Edge *curEdge1 = new Edge(curRow - i, curCol - j, fromNode, toNode);
                        Edge *curEdge2 = new Edge(i - curRow, j - curCol, fromNode, toNode);
                        fromNode->nexts.push_back(toNode);
                        fromNode->edges.push_back(curEdge1);
                        toNode->edges.push_back(curEdge2);
                        graph.edges.insert(curEdge1);
                        graph.edges.insert(curEdge2);
                    }
                }
            }
        }
    }
    return graph;
}
        5、输出排版

        由于结点value值是1到n*m,为了使其排版对齐,识别最大值的位数,并设置前后距离

void maze::print(vector<vector<int>> myMaze, maze graph, int n, int m)
{
    int bit = getbit(n * m);
    for (int row = 0; row < n + 2; row++)
    {
        for (int col = 0; col < m + 2; col++)
        {
            cout << myMaze[row][col] << " ";
        }
        if (row >= 1 && row <= n)
        {
            cout << "           ";
            for (int i = 1; i <= m; i++)
            {
                int val = (row - 1) * m + i;
                if (graph.nodes.find(val) != graph.nodes.end())
                {
                    cout << graph.nodes[val]->value;
                    switch (bit)
                    {
                    case 1:
                        cout << " ";
                        break;

                    default:
                        printblank(bit, val);
                        break;
                    }
                }
                else
                {
                    cout << 0;
                    printblank(bit, 0);
                }
            }
        }

        cout << endl;
    }
}
int getbit(int sum)
{
    int bit = 0;
    while (sum != 0)
    {
        bit++;
        sum /= 10;
    }
    return bit;
}
void printblank(int bit, int val)
{ // 例如:对于两位数,val为1位就输出2个空格,为2位就输出一个空格
    float x = pow(10, bit);
    if (val == 0)
    {
        while (bit > 0)
        {
            cout << " ";
            bit--;
        }
    }
    else
    {
        while (x > 1)
        {
            if (x / val <= 10)
            {
                cout << " ";
                break;
            }
            else
                cout << " ";
            x /= 10;
        }
    }
}
        6、呈现效果

        输入行列数及障碍数,左面含义是,外面一周是墙,左上角和右上角的2代表起点和终点,0代表路,1代表障碍。

        右面的图含义是,实际有意义的地图(也就是墙里面的),从1往后排,此时0代表阻碍。

四、后续功能

        1、用队列实现搜索迷宫的最优路径(bfs)。

                https://blog.csdn.net/Lincooo/article/details/140187776?spm=1001.2014.3001.5501

        2、用递归实现搜索迷宫的所有路径(dfs)。

  • 11
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值