A* Pathfinding in a hexagonal grid

 ̄綄美尐妖づ 提交于 2019-12-03 22:39:56

The problem resides in your neighbors method: although a hexagon has six neighbors (6), you only push four (4) onto ret. The following figure highlights the issue. The light grey hex represents the current node (i.e. neighbor). The green hexagons are added to ret, but the red hexagons are not.

To fix this, add the following two (2) cases to your neighbors method:

    if( grid[x+1][y-1] && grid[x+1][y-1] ) {
        ret.push(grid[x][y-1]);
    }
    if( grid[x-1][y+1] && grid[x-1][y+1] ) {
        ret.push(grid[x][y+1]);
    }

Regarding your updated manhattan method: it is correct. The following figure uses colors to show the distance from the current central hex (at [0:0] in red) to every other hex. For example, the orange hex tiles are one (1) move from the red. The yellow are two (2) moves from the red. And so on.

You may notice the pattern: If the x- and y-coordinates share the same sign, the distance is equal to the magnitude of the largest coordinate. Otherwise, the distance is the sum of their absolute values. This is exactly the way you've calculated distance in your updated manhattan method. So you're good there.

Regarding heuristic search in general: Here's a simple way to check if a suboptimal solution is the result of a bug in the heuristic implementation or else because of a bug in the algorithm implementation. Just use the heuristic value zero (0) for all values, i.e. use the trivial heuristic. If, while using the trivial heuristic, the path is not optimal, then you know it's not a heuristic problem---it's an algorithm problem.

As already mentioned by someone here, the way I was generating the grid, and also the coordinates were incorrect.

I have another read through Amit Patel's implementation guide and I used his way to generate the grid and also the coordinates system including the coord. conversions.

generate: function(){
        var n_hex = null; 
        var row = 0, col = 0;
        for (var q = -this.grid_r; q <= this.grid_r; q++) {
            var r1 = Math.max(-this.grid_r, -q - this.grid_r);
            var r2 = Math.min(this.grid_r, -q + this.grid_r);
            col = q + this.grid_r;
            this.hexes[ col ] = [];
            for (var r = r1; r <= r2; r++) {
                row = r - r1;
                n_hex = new Hex( [q, r], [col, row], this.layout );
                this.hexes[ col ][ row ] = n_hex;
            }
        }
    },

As I started using the cube coordinates , the only thing I had to change in the a* pathfinding algorithm was the distance calculation:

return Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y), Math.abs(a.z - b.z))

now the path-finding is working on both "pointy" and "flat" layouts :

The "classic" path finding algorithm works as follows:

  • Initialize all cells with zero.
  • Start at the starting point and mark this point with the number 1.
  • Loop start with n = 1:
  • Take all cells with number n and mark all adjacent cells, which contains a zero, with number (n+1). If any of these adjacent cells is the exit, leave loop. If no adjacent cell with number zero found, there's no path to exit.
  • Increment n and goto loop

If exit found then:

  • Start loop at exit:
  • Search adjacent cell with number n and remember this cell.
  • Decrement n and goto loop

All remembered cells builds up the result path (in reverse order).

Cheerz

Hennes

This is a solved problem, with much literature to back it up. The best resource I know is on Red Blob Games: https://www.redblobgames.com/grids/hexagons/.

In brief, the most likely reason is that you chose the wrong coordinate system. Using a Cube coordinate system implementing the A* algorithm is quite simple. See the live demo on the above link.

If you really want to use some other system, then convert to and from when needed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!