A *寻路 - 停止通过瓷砖移动对角线

时间:2017-03-23 19:45:16

标签: java path-finding 2d-games

我试图绕过A *搜索算法,然后我在迷宫中移动了一个正方形,但正方形将穿过两个角落接触的瓷砖。这是一个例子:

Image - Click here

无论如何都要阻止算法将其添加到路径

public List<Node> findPath(Vector2i start, Vector2i goal){

    List<Node> openList = new ArrayList<Node>();
    List<Node> closeList = new ArrayList<Node>();

    Node current = new Node(start, null, 0, getDistance(start, goal));
    openList.add(current);
    while(openList.size() > 0){
        Collections.sort(openList, nodeSorter);
        current = openList.get(0);
        if(current.tile.equals(goal)){
            List<Node> path = new ArrayList<Node>();
            while(current.parent != null){
                path.add(current);
                current = current.parent;
            }
            openList.clear();
            closeList.clear();
            return path;
        }
        openList.remove(current);
        closeList.add(current);
        for(int i = 0; i < 9; i++){
            if(i == 4) continue;
            int x = current.tile.getX();
            int y = current.tile.getY();
            int xi = (i % 3) - 1;
            int yi = (i / 3) - 1;
            Tile at = getTile(x + xi, y + yi);
            if(at == null || at == Tile.voidTile) continue;
            if(at.isSolid()) continue;

            Vector2i a = new Vector2i(x + xi, y + yi);
            double gCost = current.gCost + getDistance(current.tile, a);
            double hCost = getDistance(a, goal);
            Node node = new Node(a, current, gCost, hCost);
            if(vecInList(closeList, a) && gCost >= current.gCost) continue;
            if(!vecInList(openList, a) || gCost < node.gCost) openList.add(node);
        }
    }
    closeList.clear();
    return null;
}

1 个答案:

答案 0 :(得分:0)

小偏离主题:如果您不想将此类切片添加到打开列表,则不得将它们视为邻居。所以你应该回答的基本问题是创建一个寻路算法 - 我的图中哪些节点被认为是邻居

在您的情况下,您的当前磁贴不是对角线磁贴的邻居 如果他们的两个公共邻居< strong>不可以通过。例如,对于图块{+ 1,+ 1},这些邻居将是{0,+ 1}和{+ 1,0}。等等。所以,让我们检查一下:

// code here...
if(at.isSolid()) continue;

if (Math.abs(xi * yi) == 1) {
  // this is true if we're checking diagonal tile
  if ( !isPassable(getTile(x + xi, y)) && !isPassable(getTile(x, y + yi))  {
    // Both common neigbors are not passable
    // So we won't add this tile as neighbor
    continue;
  }
}

方法isPassable:

private boolean isPassable(Tile tile) {
  return tile != Tile.voidTile && !tile.isSolid();
}

如果处理对角线拼贴,则常见的neigbors总是存在,所以你不应该检查它们是否为空。