C++ 将数组转换为节点

C++ 将数组转换为节点,c++,arrays,graph,artificial-intelligence,nodes,C++,Arrays,Graph,Artificial Intelligence,Nodes,让我先说我对节点和图有非常基本的知识 我的目标是制作一个迷宫的解算器,它存储为数组。我确切地知道如何实现求解算法(我实际上实现了其中的几个),但我的问题是,我对如何实现解算器将在每个空单元中使用的节点感到非常困惑 以下是一个示例阵列: char maze[5][9] = "#########", "# # #", "# ## ## #", "# # #", "#########" 我的解算器从左上

让我先说我对节点和图有非常基本的知识

我的目标是制作一个迷宫的解算器,它存储为数组。我确切地知道如何实现求解算法(我实际上实现了其中的几个),但我的问题是,我对如何实现解算器将在每个空单元中使用的节点感到非常困惑

以下是一个示例阵列:

char maze[5][9] = 
        "#########",
        "#  #    #",
        "# ## ## #",
        "#     # #",
        "#########"
我的解算器从左上角开始,解算(出口)在右下角

我已经阅读了关于节点如何工作以及如何实现图的内容,因此我认为我需要这样做:

  • 起点将成为一个节点
  • 每个节点都将列和行号作为属性
  • 每个节点还将访问状态作为属性
  • 已访问状态可以是
    已访问
    已访问并导致死胡同
    未访问
  • 每次访问一个节点时,每个直接相邻、空且未访问的单元都会成为被访问节点的子节点
  • 每个被访问的节点都放在solutionPath堆栈的顶部(并在映射上标记为“*”)
  • 每个导致死角的节点都将从堆栈中移除(并在映射上标记为“~”)
成品迷宫示例:

"#########",
"#*~#****#",
"#*##*##*#",
"#****~#*#",
"#########"

基本上,我的问题是,我的思维方式是否真的很愚蠢(因为我对节点缺乏经验),如果是,你能解释一下原因吗?如果可能的话,还可以提供其他网站,让我检查在现实世界的应用程序中哪些实现了图形示例,以便我更好地掌握它。

答案实际上取决于您发现问题中最重要的内容。如果您正在搜索效率速度-您添加的节点太多了。没有必要这么多

有效的方法 您的解算器只需要在路径的起点和终点以及地图上每个可能的角点处使用节点。像这样:

"#########",
"#oo#o  o#",
"# ## ## #",
"#o  oo#o#",
"#########"
没有真正的必要测试地图上的其他地方——你要么走过去,要么根本不需要测试

如果它对你有帮助的话-我得到了一个模板
digraph
类,我为简单的图形表示设计了这个类。它写得不是很好,但它非常适合显示可能的解决方案

#include <set>
#include <map>

template <class _nodeType, class _edgeType>
class digraph
{
public:
    set<_nodeType> _nodes;
    map<pair<unsigned int,unsigned int>,_edgeType> _edges;
};
其中,
findWay
有一个
向量findWay(int[][]map,pair begin,pair end)
的原型,并实现了您想要的算法。在函数内部,您可能需要另一个bool类型的二维数组,该数组指示测试的位置

当算法找到一条路径时,你通常必须反向读取,但我想这取决于算法

在您的特定示例中,myMap将包含:

bool myMap[9][5] = {0,0,0,0,0,0,0,0,0,
                    0,1,1,0,1,1,1,1,0,
                    0,1,0,0,1,0,0,1,0,
                    0,1,1,1,1,1,0,1,0,
                    0,0,0,0,0,0,0,0,0};

findWay
将返回一个
向量
,该向量包含
(1,1)、(1,2)、(1,3)、(2,3)、(3,3)、(4,3)、(4,2)、(4,1)、(5,1)、(6,1)、(7,1)、(7,2)、(7,3)
答案实际上取决于你发现问题中最重要的部分。如果您正在搜索效率速度-您添加的节点太多了。没有必要这么多

有效的方法 您的解算器只需要在路径的起点和终点以及地图上每个可能的角点处使用节点。像这样:

"#########",
"#oo#o  o#",
"# ## ## #",
"#o  oo#o#",
"#########"
没有真正的必要测试地图上的其他地方——你要么走过去,要么根本不需要测试

如果它对你有帮助的话-我得到了一个模板
digraph
类,我为简单的图形表示设计了这个类。它写得不是很好,但它非常适合显示可能的解决方案

#include <set>
#include <map>

template <class _nodeType, class _edgeType>
class digraph
{
public:
    set<_nodeType> _nodes;
    map<pair<unsigned int,unsigned int>,_edgeType> _edges;
};
其中,
findWay
有一个
向量findWay(int[][]map,pair begin,pair end)
的原型,并实现了您想要的算法。在函数内部,您可能需要另一个bool类型的二维数组,该数组指示测试的位置

当算法找到一条路径时,你通常必须反向读取,但我想这取决于算法

在您的特定示例中,myMap将包含:

bool myMap[9][5] = {0,0,0,0,0,0,0,0,0,
                    0,1,1,0,1,1,1,1,0,
                    0,1,0,0,1,0,0,1,0,
                    0,1,1,1,1,1,0,1,0,
                    0,0,0,0,0,0,0,0,0};

findWay
将返回一个
向量
,该向量包含
(1,1),(1,2),(1,3),(2,3),(3,3),(4,3),(4,2),(4,1),(5,1),(6,1),(7,1),(7,2),(7,3)
,迷宫中的每个打开(即非墙)位置都是一个节点。每个节点都应该与其邻居有边。一旦将二维数组表示转换为通用的图结构,就应该能够在其上实现所需的任何图遍历算法。有很多方法可以优化它(例如使用加权图),但这应该可以让你开始。我不打算对整个迷宫进行预处理,因为这样我将访问每个单元,即使我不必访问。我正在研究如何边走边制作节点。我想不必进行预处理,但根据你在迷宫中使用的算法,它可能想知道有多少节点是先验的。例如,Djisktra算法的大多数公式都假设在开始时有一组节点和边。图形实际上隐式表示为网格形式,每个开放点上都有节点,相邻开放点之间有边。如果您了解映射并将其构建到code.FWIW中,您应该能够在此表示上实现任何您想要的图形算法。很久以前,我编写了一个直接在网格表示上工作的BFS实现。它甚至没有谈到节点和边,但实际上它就是这么做的。您可以在这里找到它:节点-边缘关系被烘焙到代码中:当访问迷宫中的一个单元时,它“知道”该单元与其空间邻居相连。迷宫中没有显式的边,只有隐式的边。迷宫中的每个开放(即非墙)位置都是一个节点。每个节点都应该与其邻居有边。一旦你皈依了