简体   繁体   中英

Find shortest path using A*

I am making a game where a pawn must be escorted to node F. The values stored in the 2D array represent:

Pawn (starting point): I    
Destination: F

For example,

Node [row=2, col=1]
Node [row=2, col=2]
Node [row=1, col=2]
Node [row=0, col=2]
Node [row=0, col=3]
Node [row=0, col=4]
Node [row=1, col=4]
Node [row=2, col=4]
Node [row=2, col=5]

Search Path without diagonals
     0   1   2   3   4   5   6
0    -   -   *   *   *   -   -
1    -   -   *   B   *   -   -
2    -   I*  *   B   *  *F   -
3    -   -   -   B   -   -   -
4    -   -   -   -   -   -   -
5    -   -   -   -   -   -   -

The problem with my implementation is that it goes through move by move. I want to be able to detect when the direction changes and only add this move, how can I accomplish this? For example, instead of visiting all the nodes one by one like in my example from before, I want:

Node [row=2, col=1] 
Node [row=2, col=2] // Right

Node [row=0, col=2] // Top

Node [row=0, col=4] // Right

Node [row=2, col=4] // Bottom
Node [row=2, col=5] // Right

How can I accomplish this?

I didn't check the algorithm implementation, but tt appears that you're getting your result as a list of Node objects. It probably looks like something like this:

List<Node> path = aStar.findPath();

Then all you need to do is to exclude all intermediate nodes from the result. You can do this after an actual algorithm (DISCLAIMER: untested code):

List<Node> path = aStar.findPath();
//a path with intermediate nodes removed
List<Node> filteredPath = new ArrayList<>(path.size());
for(int i=0; i<path.size(); i++) {
    Node current = path.get(i);
    //the first and the last element get into the result in any case
    if(i==0 || i==path.size()-1) {
          filteredPath.add(current);
    } else {
          //for the elements in between we are detecting the direction change
          Node previous = path.get(i-1);
          Node next = path.get(i+1);
          //is the step from the previous node to this one vertical
          boolean isPreviousStepVertical = current.getCol()==previous.getCol();
          //is the step from this node to the next one vertical
          boolean isNextStepVertical = current.getCol()==next.getCol();
          //we only add the nodes for which the direction has changed
          if(isPreviousStepVertical!=isNextStepVertical) {
               filteredPath.add(current);
          }

    } 
}

The idea is to check for each node if the direction actually changes (from vertical to horizontal, or vice versa) and only keep the necessary nodes.

I assume that a pawn can't move diagonally and can't move back to the already visited cell. Otherwise, you'd need to calculate the actual vectors of direction between nodes and compare them to each over.

UPDATE: To make your AStar implementation work as intended you need to comment out four lines that correspond to diagonal moves in addAdjacentUpperRow and addAdjacentLowerRow , eg:

checkNode(currentNode, col - 1, upperRow, getDiagonalCost()); // Comment this if diagonal movements are not allowed

After this, everything works as expected: https://ideone.com/77MAxg

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM