为什么在这种寻路算法中路径会反向?

问题描述

我正在创建一个二维自上而下的游戏,敌人的AI会不断跟随玩家并避开障碍物。我对路径查找算法进行了一些研究,并决定实施广度优先搜索,但是由于某种原因,即使网格正确,路径的xy坐标也会反转。
代码


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BFSTest {
    // 1 = normal node
    // 0 = obstacle
    // S = start
    // D = destination
    private static char[][] nodes = {
            {'S','1','1'},{'0','0',{'1','D'}
        };
  
    public static void main(String[] args) {
        shortestPath();
    }

    public static List<Node> shortestPath() {
        // key node,value parent
        Map<Node,Node> parents = new HashMap<Node,Node>();
        Node start = null;
        Node end = null;

        // find the start node
        for (int row = 0; row < nodes.length; row++) {
            for (int column = 0; column < nodes[row].length; column++) {
                if (nodes[row][column] == 'S') {
                    start = new Node(row,column,nodes[row][column]);
                    break;
                }
            }
        }

        if (start == null) {
            throw new RuntimeException("can't find start node");
        }

        // traverse every node using breadth first search until reaching the destination
        List<Node> temp = new ArrayList<Node>();
        temp.add(start);
        parents.put(start,null);

        boolean reachDestination = false;
        while (temp.size() > 0 && !reachDestination) {
            Node currentNode = temp.remove(0);
            List<Node> children = getChildren(currentNode);
            for (Node child : children) {
                // Node can only be visited once
                if (!parents.containsKey(child)) {
                    parents.put(child,currentNode);
                    char value = child.getValue();
                    if (value == '1') {
                        temp.add(child);
                    } else if (value == 'D') {
                        temp.add(child);
                        reachDestination = true;
                        end = child;
                        break;
                    }
                }
            }
        }
        if (end == null) {
            throw new RuntimeException("can't find end node");
        }
        // get the shortest path
        Node node = end;
        List<Node> path = new ArrayList<Node>();
        while (node != null) {
            path.add(0,node);
            node = parents.get(node);
        }
        printPath(path);
        return path;
    }

    private static List<Node> getChildren(Node parent) {
        List<Node> children = new ArrayList<Node>();
        int x = parent.getX();
        int y = parent.getY();
        if (x - 1 >= 0) {
            Node child = new Node(x - 1,y,nodes[x - 1][y]);
            children.add(child);
        }
        if (y - 1 >= 0) {
            Node child = new Node(x,y - 1,nodes[x][y - 1]);
            children.add(child);
        }
        if (x + 1 < nodes.length) {
            Node child = new Node(x + 1,nodes[x + 1][y]);
            children.add(child);
        }
        if (y + 1 < nodes[0].length) {
            Node child = new Node(x,y + 1,nodes[x][y + 1]);
            children.add(child);
        }
        return children;
    }

    private static void printPath(List<Node> path) {
        for (int row = 0; row < nodes.length; row++) {
            for (int column = 0; column < nodes[row].length; column++) {
                String value = nodes[row][column] + "";

                // mark path with X
                for (int i = 1; i < path.size() - 1; i++) {
                    Node node = path.get(i);
                    if (node.getX() == row && node.getY() == column) {
                        value = "X";
                        break;
                    }
                }
                if (column == nodes[row].length - 1) {
                    System.out.println(value);
                } else {
                    System.out.print(value + "  ");
                }
            }
        }
        System.out.println("Path: " + path);
    }
}

class Node {
    
    private int x;
    private int y;
    private char value;

    public Node(int x,int y,char value) {
        this.x = x;
        this.y = y;
        this.value = value;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public char getValue() {
        return value;
    }

    @Override
    public String toString() {
        return "(x: " + x + " y: " + y + ")";
    }

    @Override
    public int hashCode() {
        return x * y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;
        if (this.getClass() != o.getClass()) return false;
        Node node = (Node) o;
        return x == node.x && y == node.y;
    }
    /* Output:
     * S  X  X  X
     * 0  0  0  X
     * 0  0  0  X
     * 1  1  1  D
     * Path: [(x: 0 y: 0),(x: 0 y: 1),(x: 0 y: 2),(x: 0 y: 3),(x: 1 y: 3),(x: 2 y: 3),(x: 3 y: 3)]
     */
}

谢谢!

解决方法

考虑一下。请记住,您的第一个数组索引是row,第二个是column。现在,按照常规的xy

  • y索引始终引用(因为您是垂直计数行);
  • x索引始终引用(因为您是水平计数列)。

因此,索引网格的正确方法是nodes[y][x]