C++ "迷宫" 作业

3
这个小程序旨在打印迷宫的所有可能路径,入口/起点始终在左上角的下方一个位置,所有可能的出口始终在右侧墙壁上。 它从文本文件中检索迷宫。
实际上,迷宫只是一堆文本。 迷宫由 n x n 网格组成,其中 "#" 符号表示围墙,而各种字母 [a...z] 表示可行走区域/路径。 字母可以重复,但不能连续相邻。 这个迷宫是 15x15 的。
大写字母 S 总是表示入口,并且位于左侧墙壁的第二高位置。 可能的路径仅通过字母-您不能在 # 符号上行走。 右侧墙上的任何字母都表示出口。
例如,
######
Sa#hln
#bdp##
##e#ko
#gfij#
######

这是一个可能的迷宫。我的小程序应该在读取实际包含迷宫的文本文件后,将所有可能的路径打印出来。

调用该程序会在屏幕上生成以下输出:

Path 1: S,a,b,d,e,f,i,j,k,o
Path 2: S,a,b,d,p,h,l,n
2 total paths

如何实现这个功能?我不需要完整的代码答案,只想知道如何解决这个问题。

到目前为止,除了递归检查相邻方块是否可以行走的实际算法之外,我已经完成了所有工作,而且我不知道如何处理多条路径。

这是我目前所拥有的(我知道我的路径检查是错误的,但我不知道该怎么做):

    #include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <cstdio>
using namespace std;

ifstream file("maze.txt");
vector<char> vec(istreambuf_iterator<char>(file), (istreambuf_iterator<char>())); // Imports characters from file
vector<char> path;                      // Declares path as the vector storing the characters from the file
int x = 18;                             // Declaring x as 18 so I can use it with recursion below
char entrance = vec.at(16);             // 'S', the entrance to the maze
char firstsquare = vec.at(17);          // For the first walkable square next to the entrance
vector<char> visited;                   // Squares that we've walked over already

int main()
{
    if (file) {
        path.push_back(entrance);               // Store 'S', the entrance character, into vector 'path'
        path.push_back(firstsquare);            // Store the character of the square to the right of the entrance
                                                // into vector 'path'.

        while (isalpha(vec.at(x)))
        {
            path.push_back(vec.at(x));
            x++;
        }

        cout << "Path is: ";                    // Printing to screen the first part of our statement

        // This loop to print to the screen all the contents of the vector 'path'.
        for(vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)  // 
        {
        std::cout << *i << ' ';
        }

        cout << endl;
        system ("pause");                       // Keeps the black box that pops up, open, so we can see results.
        return 0;
        }
}

谢谢!


4
你尝试过什么?你在解决方案的某个方面卡住了吗?你是否已经做了基本工作,比如将迷宫从文件中读取并存储到程序的数据结构中? - Greg Hewgill
1
我会使用递归和列表来保存当前状态。每次递归都会进行四次递归调用以进行下一步操作。在每次递归中,检查当前位置是否已经被访问过,以及是否为终止块。 - user684934
我不知道如何做这些,但它们是很好的建议。我会先尝试查找如何读取文本文件,然后再想出递归部分 :) 是的,我可以使用递归。 - forthewinwin
“Sabdbdbdbdbdbdbdbdbdbdbdbdbdefijko”路径怎么样? - Edward Strange
明白了。我只是想知道如何递归解决这个问题...我已经可以处理水平路径,但是如何在所有方向上进行递归并处理多条路径呢? - forthewinwin
显示剩余2条评论
5个回答

2
您需要一些东西才能开始:
  1. 一种在内存中表示迷宫的方式——适合网格类迷宫的“数据结构”
  2. 访问和操作该迷宫的方法
  3. 呈现迷宫的方法——也许是打印出一个迷宫
  4. 跟踪您的进度的方法
  5. 解决手头问题的算法
考虑从一个小得多的迷宫开始——可能是3x3大小的迷宫——有一条直线穿过地图。您的程序应该能够解决这个问题。然后将路径改为稍微弯曲一些。然后让地图变大。使路径更难。在路径上有一些“红鱼”分支。
一个小地图,复杂度逐渐增加,应该会使调试工作容易得多。(如果您不知道如何使用调试器,从一个小问题开始会使学习调试器变得更容易。)
祝你好运!

2

通常的方法(特别是学校作业)是递归地处理它。从指定的起点开始。从那里递归地尝试每个可能的方格(向上、向右、向下)。

唯一真正的“技巧”就是跟踪您已经访问过哪些方格。一种可能性是在进入一个方格时保存其值,然后在递归搜索其他方格之前,将其设置为未使用的其他值(例如,“.”应该适用于您的情况)。


1
@forthewinwin 我建议您也看一下A*算法 - Eitan T
2
对于所有路径,洪水填充类型的算法(递归或使用栈)绝对是最好的选择。A*算法只能找到一条路线。 - IanM_Matrix1
我正在尝试让它朝除了右边以外的其他方向移动...我该怎么做呢?我可以分别为每个方向递增位置,但如何将它们混合在一起呢? - forthewinwin
1
@forthewinwin:处理其他方向基本上意味着在四个方向中递归,进入任何尚未访问过的方向。 - Jerry Coffin
我需要4个单独的循环还是它们会相互嵌套?我猜我需要一个单独的数组/向量来跟踪已访问的字符,对吗? - forthewinwin
显示剩余3条评论

1
首先,我会读取文件并将其放入数据结构中,以便您可以实际处理它。如果这是为了作业,那么任务很可能是让您学习路径查找算法,请尝试查找Dijkstra算法,这应该可以帮助您入门。

我在考虑使用ifstream来读取文件...现在我应该如何将它放入数据结构中呢?我是C++的新手。 - forthewinwin
2
@forthewinwin 嗯,假设您选择一个二维数组作为结构,您将逐个字符读入文件,并将每个字符放置在下一个数组位置中。当您遇到一个新行时,请移动到数组中的下一行。 - RoneRackal

1
一个非常高层次的方法:
创建一棵描述迷宫路径的树。打印出以右侧结束的路径。
如何检测路径是否会绕回自己?(或者你的迷宫不会有这个问题吗?)

1

将符号加载到数组中。然后递归检查每个位置:它能向上、下、左、右移动吗?从那里,您可以将这些布尔答案保存为0或1,并在单独的数组中使用它来继续...根据您的副本数组是否表示您可以或不能朝某个方向继续。

此外,一定要创建一些新方法...我通常尽量不在主方法中包含太多内容...

希望这有所帮助,但愿我有时间再看看它...

-P


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接