数据结构:maze迷宫求解(C++)

文件中给定地图,检查是否有出口,并标记正确出路

迷宫地图

//1表示墙,0表示是可以走的路
1 1 1 1 1 1 1 1 1 1  
1 1 1 1 1 1 1 1 1 1  
0 0 0 1 1 1 1 1 1 1  
1 1 0 1 1 1 1 1 1 1  
1 1 0 1 1 1 1 1 1 1  
1 1 0 1 1 1 1 1 1 1  
1 1 0 0 0 0 0 0 1 1  
1 1 0 1 1 1 1 0 1 1  
1 1 0 1 1 1 1 0 1 1  
1 1 0 1 1 1 1 1 1 1  

方法一:

//Maze.h
#define _CRT_SECURE_NO_WARNINGS 10
#pragma once

#include<iostream>
#include<stdlib.h>
using namespace std;

#include<stack>
#include<assert.h>

const int N = 10;

struct pos
{
    int Row;
    int Col;
};

void GetMap(int *maze);

void PrintMap(int *maze);

bool CheckAccess(int *maze,pos path);

void GetWay(int *maze, pos entry, stack<pos> &s);
//Maze.cpp
    #include"Maze.h"

    void GetMap(int *maze)
    {
        FILE* pf = fopen("MazeMap.txt", "r");

        assert(pf);
        char value = 0;
        for (size_t i = 0; i<N; i++)
        {
            for (size_t j = 0; j<N;)
            {
                value = fgetc(pf);//the FILE get num is ASCII
                if (value == '0' || value == '1')//when you get "0"&&"1" you can to get the value
                {
                    maze[i*N + j] = value - '0';//to make them be num like themself
                    j++;
                }
                else if (value == EOF)
                {
                    cout << "maze error!" << endl;
                    return;
                }
            }
        }
        fclose(pf);
    }

    void PrintMap(int *maze)
    {
        for (size_t i = 0; i < N; i++)
        {
            for (size_t j = 0; j < N; j++)
            {
                cout << maze[i*N + j] << " ";
            }

            cout << endl;
        }
        cout << endl;
    }

    bool CheckAccess(int *maze, pos path)
    {
        if ((path.Col>0) && (path.Col<N)
            && (path.Row>0) && (path.Row)<N
            && (maze[path.Row*N + path.Col] == 0))
        {
            return true;
        }
        else
            return false;
    }

    void GetWay(int *maze, pos entry, stack<pos> &s)
    {
        assert(maze);
        pos cur = entry;
        maze[cur.Row*N + cur.Col] = 2;//which you have already go change to NO.2 
        s.push(entry);
        pos next = cur;

        while (!s.empty())
        {
            if (s.top().Row == N - 1)
            {
                cout << "find the way" << endl;
                return;
            }

            //上
            next = s.top();
            next.Row -= 1;
            if (CheckAccess(maze, next))
            {
                s.push(next);
                maze[next.Row*N + next.Col] = 2;

                continue;
            }
            //下
            next = s.top();
            next.Row += 1;
            if (CheckAccess(maze, next))
            {
                s.push(next);
                maze[next.Row*N + next.Col] = 2;

                continue;
            }
            //左
            next = s.top();
            next.Col -= 1;
            if (CheckAccess(maze, next))
            {
                s.push(next);
                maze[next.Row*N + next.Col] = 2;

                continue;
            }
            //右
            next = s.top();
            next.Col += 1;
            if (CheckAccess(maze, next))
            {
                s.push(next);
                maze[next.Row*N + next.Col] = 2;

                continue;
            }
            next = s.top();
            s.pop();
            maze[next.Row*N + next.Col] = 3;

        }
        cout << "be faile" << endl;
    }
//main.cpp
#include"Maze.h"

void Test()//普通方法
{
    int maze[N][N] = { 0 };
    pos entry = { 2, 0 };
    stack<pos> s;
    GetMap((int*)maze);
    //PrintMap((int*)maze);
    GetWay((int*)maze, entry, s);
    PrintMap((int*)maze);
}

int main()
{
    Test();
    system("pause");
    return 0;
}

方法二:递归法

不建议,时间、空间开销大

//Maze.h
#define _CRT_SECURE_NO_WARNINGS 10
#pragma once

#include<iostream>
#include<stdlib.h>
using namespace std;

#include<stack>
#include<assert.h>

const int N = 10;

struct pos
{
    int Row;
    int Col;
};

void GetMap(int *maze);

void PrintMap(int *maze);

bool CheckAccess(int *maze,pos path);

void GetWay(int *maze, pos entry, stack<pos> &s);
//Maze.cpp
#include"Maze.h"

void GetMap(int *maze)
{
    FILE* pf = fopen("MazeMap.txt", "r");
    assert(pf);
    char value = 0;
    for (size_t i = 0; i < N; i++)
    {
        for (size_t j = 0; j < N;)
        {
            value = fgetc(pf);
            if (value == '0' || value == '1')
            {
                maze[i*N + j] = value - '0';
                j++;
            }
            else if (value == EOF)
            {
                cout << "maze error!" << endl;
                return;
            }
        }
    }
    fclose(pf);
}

void PrintMap(int *maze)
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            cout << maze[i*N + j] << " ";
        }
        cout << endl;
    }
    cout << endl;
}

bool CheckAccess(int *maze, pos path)
{
    if ((path.Col<N) && (path.Col>0)
        && (path.Row<N) && (path.Row>0)
        && (maze[path.Row*N + path.Col] == 0))
    {
        return true;
    }
    else
        return false;
}

void GetWay(int *maze, pos entry, stack<pos> &s)
{
    assert(maze);
    pos next = entry;
    maze[next.Row*N + next.Col] = 2;//将可通过的坐标标记为2  
    s.push(entry);


    //探测上下左右四个方向是否可通  
    if (entry.Row == N - 1)
    {
        cout << "找到通路" << endl;
        return;
    }
    //上  
    next = entry;
    next.Row -= 1;
    if (CheckAccess(maze, next))
    {
        GetWay(maze, next, s);
    }
    //右  
    next = entry;
    next.Col += 1;
    if (CheckAccess(maze, next))
    {
        GetWay(maze, next, s);
    }
    //下  
    next = entry;
    next.Row += 1;
    if (CheckAccess(maze, next))
    {
        GetWay(maze, next, s);
    }
    //左  
    next = entry;
    next.Col -= 1;
    if (CheckAccess(maze, next))
    {
        GetWay(maze, next, s);
    }
}
//main.cpp
#include"Maze.h"

void Test()//普通方法
{
    int maze[N][N] = { 0 };
    pos entry = { 2, 0 };
    stack<pos> s;
    GetMap((int*)maze);
    //PrintMap((int*)maze);
    GetWay((int*)maze, entry, s);
    PrintMap((int*)maze);
}

int main()
{
    Test();
    system("pause");
    return 0;
}

方法三:最优解求法

转载

//Maze.cpp
#define _CRT_SECURE_NO_WARNINGS 
#include <iostream> 
using namespace std;  
#include <assert.h> 
#include <stack> 
#include<iomanip> 

const int N = 10;//定义全局变量迷宫的大小(假设迷宫整体为正方形,行列相等) 

struct Pos  
{  
    int Row;  
    int Col;  
};  

//void GetMaze(int (*maze)[N])//读取迷宫 
//void GetMaze(int **maze)//读取迷宫(需要动态开辟空间) 
//void GetMaze(int maze[][N])//读取迷宫 
void GetMaze(int *maze)//读取迷宫 
{  
    FILE* pf = fopen("MazeMap.txt","r");  
    assert(pf);  
    char value = 0;  
    for(size_t i = 0; i<N; i++)  
    {  
        for (size_t j = 0; j<N;)  
        {  
            value = fgetc(pf);  
            if(value == '0' || value == '1')  
            {  
                maze[i*N+j] = value - '0';  
                j++;  
            }  
            else if(value == EOF)  
            {  
                cout<<"maze error!"<<endl;  
                return;  
            }  
        }  
    }  
    fclose(pf);  
}  
void PrintMaze(int *maze)//打印迷宫 
{  
    cout<<setw(3);  
    for(size_t i = 0; i<N; i++)  
    {  
        for (size_t j = 0; j<N; j++)  
        {  
            cout<<maze[i*N+j]<<setw(3);  
        }  
        cout<<endl;  
    }  
}  
bool CheckIsAccess(int* maze,Pos cur,Pos next)//检查坐标是否合法 
{  
    //下一个坐标非法 
    if(    (next.Row < 0) || (next.Row >= N)   
        || (next.Col < 0) || (next.Col >= N))  
    {  
        return false;  
    }  
    //下一个坐标合法 
    if(maze[next.Row*N + next.Col] == 0)  
    {  
        return true;  
    }  
    //下一个坐标是以前走过的坐标 
    if(maze[next.Row*N + next.Col] > maze[cur.Row*N + cur.Col]+1)  
    {  
        return true;  
    }  
    return false;  
}  
void GetMazeMinPath(int* maze,Pos entry,stack<Pos>& path,stack<Pos>& min)//找通路 
{  
    assert(maze);  
    path.push(entry);  
    Pos cur = entry;  
    Pos next = cur;  

    //找到通路 

    if(cur.Col == N-1)  
    {  
        if(min.empty() || path.size()<min.size())  
        {  
            min = path;  
            //cout<<"找到通路"<<endl; 
        }  
        path.pop();  
        return;  
    }  
    //探测上下左右四个方向是否可通 
    //上 
    next = cur;  
    next.Row -= 1;  
    if(CheckIsAccess(maze,cur,next))  
    {  
        maze[next.Row*N+next.Col] = maze[cur.Row*N+cur.Col] + 1;  
        GetMazeMinPath(maze,next,path,min);  
    }  
    //右 
    next = cur;  
    next.Col += 1;  
    if(CheckIsAccess(maze,cur,next))  
    {  
        maze[next.Row*N+next.Col] = maze[cur.Row*N+cur.Col] + 1;  
        GetMazeMinPath(maze,next,path,min);  
    }  
    //下 
    next = cur;  
    next.Row += 1;  
    if(CheckIsAccess(maze,cur,next))  
    {  
        maze[next.Row*N+next.Col] = maze[cur.Row*N+cur.Col] + 1;  
        GetMazeMinPath(maze,next,path,min);  
    }  
    //左 
    next = cur;  
    next.Col -= 1;  
    if(CheckIsAccess(maze,cur,next))  
    {  
        maze[next.Row*N+next.Col] = maze[cur.Row*N+cur.Col] + 1;  
        GetMazeMinPath(maze,next,path,min);  
    }  
    path.pop();  
}  
int main()  
{  
    int maze[N][N];  
    Pos entry = {2,0};  
    stack<Pos> path;  
    stack<Pos> minpath;  
    GetMaze((int*)maze);  
    maze[2][0] = 2; //将迷宫入口赋值为2 
    PrintMaze((int*)maze);  
    cout<<endl<<endl;  
    GetMazeMinPath((int*)maze,entry,path,minpath);  
    PrintMaze((int*)maze);  
    system("pause");  
    return 0;  
}  

借鉴:http://blog.csdn.net/snow_5288/article/details/53457201?locationNum=1&fps=1

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/sinat_36101354/article/details/60776516
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞