迷宫问题(栈)

迷宫问题(栈与队列)

[问题描述]

利用栈操作实现迷宫问题求解。

[基本要求]

(1)从文件中读取数据,生成模拟迷宫地图,不少于20行20列。

(2)给出任意入口和出口,显示输出迷宫路线。

文件内容:

解题思路:

这道题和八皇后问题比较类似。八皇后问题是在满足一定条件下,在一张图中寻找皇后放置的合适位置。这里则是根据出口和入口,在一张迷宫图中寻找路线,路线上的各点需满足:不重复不为墙壁

我们首先从文件中读取数据,生成迷宫地图。之后找出所有的迷宫口,并选定入口和出口。从入口出发,每次都对上下左右的四个位置进行探测,若该点满足条件(不重复且不为墙壁),则加入保存路线的栈route中(这里我们用visit[][]数组标注某一位置是否可行)。若未到达指定出口,且某一位置无法继续前进时,则将栈顶位置弹栈,处理前一位置,若仍无法继续前进,继续弹栈,直到可以前进为止。

按照此方法找到的路线即为从入口到出口的路线,路线上的各点保存在栈route中,最后打印输出包含路线的迷宫图即可。

程序代码:

# include <iostream>
# include <fstream>
# include <string.h>
# include <stack>
# define maxn 30
using namespace std;

//地图类型的结构体
typedef struct Point {
    int col;  //行
    int row;  //列
}Point;

//创建迷宫
void Create();
//打印迷宫
void Print();
//生成出入口
void FindGate();
//判断位置是否可行
bool Judge(int x, int y);
//走迷宫
void GoMaze();

int m = 0, n = 0;      //迷宫的行、列
int maze[maxn][maxn];  //迷宫地图
int gate[maxn][2];     //保存迷宫出入口
int vis[maxn][maxn];   //记录走过的位置
//在迷宫的前进方式
int way[4][2] = { {0,1},{-1,0},{1,0},{0,-1} };
stack<Point>route;     //保存路线的栈
int path[maxn][maxn] = { {0} };  //路线

int main()
{
    Create();    //创建迷宫
    Print();     //打印迷宫图
    int select;
    while (1) {
        cout << "\n开始游戏!" << endl;
        FindGate();  //生成出入口
        GoMaze();    //走迷宫
        cout << endl;
        Print();     //打印迷宫图(包含路线)
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                path[i][j] = 0;
                vis[i][j] = 0;
            }
        }
        cout << "\n是否继续游戏? (1:是 2:否)" << endl;
        cout << "请输入:";
        cin >> select;
        if (select != 1) {
            break;
        }
    }
    cout << "\n游戏结束!" << endl;
    return 0;
}

//创建迷宫
void Create()
{
    fstream file;
    file.open("迷宫样例.txt", ios::in);
    if (file.fail()) {
        cout << "文件打开失败" << endl;
        exit(0);
    }
    char str[100];
    char c;
    int i = 0;
    file.getline(str, 100);
    while (str[i] != ' ' && i < strlen(str)) {
        m *= 10;
        m = m + str[i] - 48;
        i++;
    }
    i++;
    while (str[i] != ' ' && i < strlen(str)) {
        n *= 10;
        n = n + str[i] - 48;
        i++;
    }
    int k = 1, j;
    file.getline(str, 100);
    while (!file.eof()) {
        j = 1;
        for (int i = 0; i < strlen(str); i = i + 2)
        {
            maze[k][j] = str[i] - 48;
            j++;
        }
        k++;
        file.getline(str, 100);
    }
    j = 1;
    for (int i = 0; i < strlen(str); i = i + 2) {
        maze[k][j] = str[i] - 48;
        j++;
    }
}

//打印迷宫及路线
void Print()
{
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (maze[i][j]) {
                cout << "D";
            }
            else if (path[i][j]) {
                cout << "*";
            }
            else {
                cout << " ";
            }
        }
        cout << endl;
    }
}

//生成出入口
void FindGate()
{
    int k = 1;  //出入口序号
    for (int i = 1; i <= m; i++) {
        if (maze[i][1] == 0) {
            cout << "(" << k << ")";
            cout << i << " " << 1 << endl;
            gate[k][0] = i;
            gate[k][1] = 1;
            k++;
        }
        if (maze[i][n] == 0) {
            cout << "(" << k << ")";
            cout << i << " " << n << endl;
            gate[k][0] = i;
            gate[k][1] = n;
            k++;
        }
    }
    for (int i = 2; i < n; i++) {
        if (maze[1][i] == 0) {
            cout << "(" << k << ")";
            cout << 1 << " " << i << endl;
            gate[k][0] = 1;
            gate[k][1] = i;
            k++;
        }
        if (maze[m][i] == 0) {
            cout << "(" << k << ")";
            cout << m << " " << i << endl;
            gate[k][0] = m;
            gate[k][1] = i;
            k++;
        }
    }
}

//判断位置是否可行
bool Judge(int x, int y)
{
    if (x > m || x < 1 || y > n || y < 1 || maze[x][y] || vis[x][y]) {
        //超过边界或该点为墙壁或上一次走过,则不通
        return false;
    }
    else {
        return true;
    }
}

//走迷宫
void GoMaze()
{
    int x, y, x1, y1, x2, y2;
    cout << "请输入入口序号:";
    cin >> x;
    x1 = gate[x][0];
    y1 = gate[x][1];
    cout << "请输入出口序号:";
    cin >> y;
    x2 = gate[y][0];
    y2 = gate[y][1];
    Point current;     //现在所处的位置
    current.col = x1;
    current.row = y1;
    path[current.col][current.row] = 1;
    vis[current.col][current.row] = 1;
    route.push(current);  //将入口放入路线
    //到达终点前会一直寻找路线
    while (current.col != x2 || current.row != y2) {
        int t = 0;  //判断是否可以继续前进
        while (!t) {
            for (int i = 0; i < 4; i++) {
                current.col = current.col + way[i][0];
                current.row = current.row + way[i][1];
                if (Judge(current.col, current.row)) {
                    //可以继续前进
                    t = 1;
                    route.push(current);   //将该位置放入路线
                    path[current.col][current.row] = 1;
                    vis[current.col][current.row] = 1;
                    break;
                }
                else {
                    //不通
                    current.col = current.col - way[i][0];
                    current.row = current.row - way[i][1];
                    continue;
                }
            }
            if (!t) {
                //若不能继续前进,则弹栈
                if (!route.empty()) {
                    route.pop();
                }
                path[current.col][current.row] = 0;
                //更新当前位置
                if (!route.empty()) {
                    current.col = route.top().col;
                    current.row = route.top().row;
                }
            }
        }
    }
}

运行结果:

       DDD    DDDDDD DDDD
DDDDDD     DD      D DDDD
DD     DDD DD DDDDDD DDDD
DD DDD DDD D  DDDDDD DDDD
DD DDDDDDD   D
DD     DDDD  D DDDDDDDDDD
DDDD DDD   DDD DDDDDDDDDD
DDDD     D DDD DDDDDDDDDD
DDDD DDD D D        DDDDD
DDDD DDD D D DDDDDD DDDDD
DDDD     D D    DDD DDDDD
DDDDDDDDDD DDDD DDD DDDDD
DDD      D DDDD DDD DDDDD
DDD DDDD    D   DDD
DDD DDDDDDDDD DDDDD DDDDD
DDD      DDDD DDDDD DDDDD
DDD DDDD DDDD DDDDD DDDDD
DDD DDDD DDDD DDDDD DDDDD
DDD DDDD            DDDDD
DDD DDDD DD DDD DDDDDDDDD
DDD         DDD DDDDDDDDD
DDD DDDDDD DDDD        DD
DDD DDDDDD DDDDDD DDDD DD
DDD DDDDDD DDDDDD DDDD DD
    DDDDDD DDDD   DDDD

开始游戏!
(1)1 1
(2)5 25
(3)14 25
(4)25 1
(5)25 25
(6)1 2
(7)25 2
(8)1 3
(9)25 3
(10)1 4
(11)25 4
(12)1 5
(13)1 6
(14)1 7
(15)1 11
(16)25 11
(17)1 12
(18)1 13
(19)1 14
(20)25 16
(21)25 17
(22)25 18
(23)1 21
(24)25 23
(25)25 24
请输入入口序号:1
请输入出口序号:5

*******DDD    DDDDDD DDDD
DDDDDD*    DD      D DDDD
DD*****DDD DD DDDDDD DDDD
DD*DDD DDD D  DDDDDD DDDD
DD*DDDDDDD   D
DD***  DDDD  D DDDDDDDDDD
DDDD*DDD***DDD DDDDDDDDDD
DDDD*****D*DDD DDDDDDDDDD
DDDD DDD D*D        DDDDD
DDDD DDD D*D DDDDDD DDDDD
DDDD     D*D    DDD DDDDD
DDDDDDDDDD*DDDD DDD DDDDD
DDD******D*DDDD DDD DDDDD
DDD*DDDD*** D   DDD
DDD*DDDDDDDDD DDDDD DDDDD
DDD******DDDD DDDDD DDDDD
DDD DDDD*DDDD DDDDD DDDDD
DDD DDDD*DDDD DDDDD DDDDD
DDD DDDD********    DDDDD
DDD DDDD DD DDD*DDDDDDDDD
DDD         DDD*DDDDDDDDD
DDD DDDDDD DDDD********DD
DDD DDDDDD DDDDDD DDDD*DD
DDD DDDDDD DDDDDD DDDD*DD
    DDDDDD DDDD   DDDD***

是否继续游戏? (1:是 2:否)
请输入:1

开始游戏!
(1)1 1
(2)5 25
(3)14 25
(4)25 1
(5)25 25
(6)1 2
(7)25 2
(8)1 3
(9)25 3
(10)1 4
(11)25 4
(12)1 5
(13)1 6
(14)1 7
(15)1 11
(16)25 11
(17)1 12
(18)1 13
(19)1 14
(20)25 16
(21)25 17
(22)25 18
(23)1 21
(24)25 23
(25)25 24
请输入入口序号:2
请输入出口序号:4

       DDD    DDDDDD DDDD
DDDDDD     DD      D DDDD
DD     DDD DD DDDDDD DDDD
DD DDD DDD D  DDDDDD DDDD
DD DDDDDDD   D***********
DD     DDDD  D*DDDDDDDDDD
DDDD DDD   DDD*DDDDDDDDDD
DDDD     D DDD*DDDDDDDDDD
DDDD DDD D D  ******DDDDD
DDDD DDD D D DDDDDD*DDDDD
DDDD     D D    DDD*DDDDD
DDDDDDDDDD DDDD DDD*DDDDD
DDD      D DDDD DDD*DDDDD
DDD DDDD    D   DDD*
DDD DDDDDDDDD DDDDD*DDDDD
DDD******DDDD DDDDD*DDDDD
DDD*DDDD*DDDD DDDDD*DDDDD
DDD*DDDD*DDDD DDDDD*DDDDD
DDD*DDDD*  *********DDDDD
DDD*DDDD*DD*DDD DDDDDDDDD
DDD*    ****DDD DDDDDDDDD
DDD*DDDDDD DDDD        DD
DDD*DDDDDD DDDDDD DDDD DD
DDD*DDDDDD DDDDDD DDDD DD
****DDDDDD DDDD   DDDD

是否继续游戏? (1:是 2:否)
请输入:2

游戏结束!

以上便是我对这道题的看法,很高兴与大家分享。

猜你喜欢

转载自blog.csdn.net/CXR_XC/article/details/128765054