关于#算法#的问题,如何解决?

问题遇到的现象和发生背景

用a*算法解决迷宫问题,当启发式函数值相等的时候设定的优先级是右下上左,但是会出现有的点没有先向右而是向下走不知道为什么,下面是全部代码,求指点

用代码块功能插入代码,请勿粘贴截图
#include 
#include 
#include 
#include 
#include <string>
#include 
#include 
#include 
#include 

using namespace std;

typedef struct NODE
{
    int x, y;    // 节点所在位置
    int F, G, H; // G:从起点开始,沿着产的路径,移动到网格上指定方格的移动耗费。
        // H:从网格上那个方格移动到终点B的预估移动耗费,使用曼哈顿距离。
        // F = G + H
    NODE(int a, int b) { x = a, y = b; }
    // 重载操作符,使优先队列以F值大小为标准维持堆
    bool operator<(const NODE& a) const
    {
        return F == a.F ? G > a.G : F > a.F;
    }
} Node;

// 定义方向
const int next_position[4][2] = {  {1,0}, {0,1},{0,-1}, {-1,0} };
priority_queue open; // 优先队列,就相当于open表

int createMaze();       //创建随机迷宫
int createFreeMaze();   //创建自定义迷宫
void createWall();      //创建迷宫外墙
int maze[100][100];   //迷宫数组
bool close[100][100]; // 访问情况记录,close列表
int valueF[100][100]; // 记录每个节点对应的F值
int pre[100][100][2]; // 存储每个节点的父节点
int row = 0;
int col = 0;//行和列
//迷宫矩阵,2代表墙壁,0代表通道
//创建迷宫外墙
void createWall()
{
    //创建迷宫外墙,第一行、第一列、最后一行、最后一列均为墙壁
    for (int i = 0; i < col; i++)//第一行
        maze[0][i] = 2;
    for (int i = 1; i < row; i++)//第一列
        maze[i][0] = 2;
    for (int i = 1; i < col; i++)//最后一行
        maze[row - 1][i] = 2;
    for (int i = 1; i < row - 1; i++)//最后一列
        maze[i][col - 1] = 2;
}

//创建随机迷宫
int createMaze()
{
    srand(time(0));
    for (int i = 1; i < row - 1; i++)
    {
        for (int j = 1; j < col - 1; j++)
        {
            if ((rand() % 100 + 1) % 4 == 0)
                maze[i][j] = 2;
            else
                maze[i][j] = 0;
        }
    }
    maze[1][1] = 0;
    maze[row - 2][col - 2] = 0;
    return 0;
}

//创建自定义迷宫
int createFreeMaze()
{
    for (int i = 1; i < row - 1; i++)
    {
        //第一行,第一格为入口
        if (i == 1)
        {
            printf("迷宫第%d行,共%d格:  ", i, col - 3);
            for (int j = 2; j < col - 1; j++)
                scanf_s("%d", &maze[i][j]);
        }
        //最后一行,最后一格为出口
        else if (i == row - 2)
        {
            printf("迷宫第%d行,共%d格:", i, col - 3);
            for (int j = 1; j < col - 2; j++)
                scanf_s("%d", &maze[i][j]);
        }
        else
        {
            printf("迷宫第%d行,共%d格:", i, col - 2);
            for (int j = 1; j < col - 1; j++)
                scanf_s("%d", &maze[i][j]);
        }
    }
    maze[1][1] = 0;           //入口为通道
    maze[row - 2][col - 2] = 0;   //出口为通道
    return 0;
}

//曼哈顿距离函数
int Manhattan(int x, int y, int x1, int y1)
{
    return abs(x - x1) + abs(y - y1);
}

bool isValidNode(int x, int y)
{
    if (x <= 0 || x >= row - 1 || y <= 0 || y >= col - 1)
        return false; // 判断边界
    if (maze[x][y] == 2)
        return false; // 判断障碍物
    return true;
}

//A*算法函数
void Astar(int x0, int y0, int x1, int y1)
{
    // 起点加入open列表
    Node node(x0, y0);
    node.G = 0;
    node.H = Manhattan(x0, y0, x1, y1);
    node.F = node.G + node.H;
    valueF[x0][y0] = node.F;
    open.push(node);

    while (!open.empty())
    {
        Node node_current = open.top();                   //取优先队列头元素,即周围单元格中代价最小的点
        open.pop();                                       //从open列表中移除
        close[node_current.x][node_current.y] = true;     // 访问该点,加入close列表
        if (node_current.x == x1 && node_current.y == y1) // 到达终点
            break;

        // 遍历node_top周围的4个位置
        for (int i = 0; i < 4; i++)
        {
            Node node_next(node_current.x + next_position[i][0], node_current.y + next_position[i][1]); // 创建一个node_top周围的点
            // 该节点坐标合法 且没有被访问
            if (isValidNode(node_next.x, node_next.y) && !close[node_next.x][node_next.y])
            {
                // 计算从起点并经过node_top节点到达该节点所花费的代价
                node_next.G = node_current.G+1;
                // 计算该节点到终点的曼哈顿距离
                node_next.H = Manhattan(node_next.x, node_next.y, x1, y1);
                // 从起点经过node_top和该节点到达终点的估计代价
                node_next.F = node_next.G + node_next.H;

                // node_next.F < valueF[node_next.x][node_next.y] 说明找到了更优的路径,进行更新
                // valueF[node_next.x][node_next.y] == 0 说明该节点还未加入open表中,则加入
                if (node_next.F < valueF[node_next.x][node_next.y] || valueF[node_next.x][node_next.y] == 0)
                {
                    // 保存该节点的父节点
                    pre[node_next.x][node_next.y][0] = node_current.x;
                    pre[node_next.x][node_next.y][1] = node_current.y;
                    valueF[node_next.x][node_next.y] = node_next.F; // 修改该节点对应的valueF值
                    open.push(node_next);
                }
            }
        }
    }
}

void PrintPath(int x1, int y1)
{
    //OPEN表为空,无解情况
    if (pre[x1][y1][0] == 0 || pre[x1][y1][1] == 0)
    {
        printf("\n没有找到出口!\n");
        return;
    }
    int x = x1, y = y1;
    int a, b;
    while (x != -1 || y != -1)
    {
        maze[x][y] = 1; // 将可行路径上的节点赋值为1
        a = pre[x][y][0];
        b = pre[x][y][1];
        x = a;
        y = b;
    }
    // ' '表示未经过的节点, '█'表示障碍物, '◇'表示可行节点
    string s[3] = { "  ", "◇", "█" };
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
            cout << s[maze[i][j]];
        cout << endl;
    }
}

int main(int argc, char* argv[])
{
    int i, j;

    printf("请输入迷宫行数row(0);
    scanf_s("%d", &row);
    printf("请输入迷宫列数col(0);
    scanf_s("%d", &col);

    createWall();//创建迷宫外墙

    int choice;
    printf("请选择创建随机迷宫还是自定义迷宫(1为随机迷宫,2为自定义迷宫):");
    scanf_s("%d", &choice);
    if (choice == 1)
    {
        createMaze();   //创建迷宫
    }
    else if (choice == 2)
    {
        printf("\n请输入自定义迷宫的墙壁和通道,2代表墙壁,0代表通道\n");
        createFreeMaze();
    }

    printf("\n显示迷宫:\n");
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            if (maze[i][j] == 2)
                printf("█");
            else
                printf("  ");
        }
        printf("\n");
    }
    fill(close[0], close[0] + row * col, false);    // 将visit数组赋初值false
    fill(valueF[0], valueF[0] + row * col, 0);      // 初始化F全为0
    fill(pre[0][0], pre[0][0] + row * col * 2, -1); // 路径同样赋初值-1

    //  // 起点 // 终点
    int x0 = 1, y0 = 1, x1 = row - 2, y1 = col - 2;


    printf("\n显示路径:\n");
    Astar(x0, y0, x1, y1); // A*算法
    PrintPath(x1, y1);     // 打印路径

    return 0;
}

运行结果及报错内容

img


比如(6,4)那个点,应该先向右走,但是他却先向下了不知道为什么

A*算法源代码很多开源项目都包含,参考之。