矩形网格算法中转弯最少的路径

时间:2013-03-12 12:23:31

标签: algorithm tiles-game

我在算法中被困了4天。我正在制作麻将Safari类型游戏(http://www.pogo.com/games/mahjongsafari),我想在两块瓷砖之间开发路径,用最少数量的瓷砖。

我已经在曼哈顿Hueristic中应用了A *算法,但是这会产生很多转弯的最短路径。不需要最短的路径,我只需要最小转弯的路径(最好是2)。下面是Mahjong Safari游戏中的图像,该游戏生成2个图块之间的路径。你会注意到从A到B的路径和从B到A的路径是不同的。

enter image description here

请以任何代码或任何算法名称或您认为可行的任何逻辑帮助我。

编辑:我申请的解决方案:

我首先使用真正的A *算法来找到最短路径,并且我使用曼哈顿距离作为启发式目标估计。为了更多地拉直路径,并选择具有最少匝数的路径,我在每次迭代中使用了以下策略:

Tile first = currentNode.parent;
Tile curr  = currentNode;
Tile last  = successorOfCurrentNode;
if (first != null)
{
    if ((first.X == curr.X && first.Y != curr.Y) && (curr.Y == last.Y && curr.X != last.X))
    {
        // We got turn
    currentNode.Cost += 10;
    currentNode.calcuateTotalCost();

        successorOfCurrentNode.Cost += 5;
    successorOfCurrentNode.calcuateTotalCost();
    }
    else if ((first.X != curr.X && first.Y == curr.Y) && (curr.X == last.X && curr.Y != last.Y))
    {
        // We got turn
    currentNode.Cost += 10;
    currentNode.calcuateTotalCost();

        successorOfCurrentNode.Cost += 5;
    successorOfCurrentNode.calcuateTotalCost();
    }

}

3 个答案:

答案 0 :(得分:0)

您可以使用Dijkstra's shortest path algorithm,但在每个节点中,您不仅应存储最短路径,还应存储该路径的方向,以便了解是否需要增加计数。

再想一想,我猜你需要在每个节点中存储所有最短路径及其方向,以便选择最佳路径。

答案 1 :(得分:0)

你的问题比使用启发式更简单,因为你不需要期望,但它可以提高找到最佳的速度,以防你的搜索不“完整”..但你只是想要的路径与最小转弯,因此你可以选择Greedy Search:

h(A) > h(B) ~ turns(A) < turns(B)

h* = MIN(turns(x))

h(x): heuristic of path X

turns(x): number of turns in path X

h*: highest possible heuristic, path with minimum number of turns

这是Java中的一个简单代码,用于说明:

class TileGame
{
    // example of a game board
    int [][] matrix = new int [10][10];

    // return possible next-state
    public ArrayList<Path> next (Path p)
    {
        // based on your rules, you decide valid transitions
        ArrayList<Path> n = new ArrayList<Path>();
        ArrayList<Point> t = new ArrayList<Point>();

        // add up, down, right, and left
        t.add(new Point(p.current.x+1, p.current.y));
        t.add(new Point(p.current.x-1, p.current.y));
        t.add(new Point(p.current.x, p.current.y+1));
        t.add(new Point(p.current.x, p.current.y-1));

        // don't allow going back to previous tile, cause infinite loops
        t.remove(p.previous);

        for (Point i : t)
        {
            if (i.x == p.current.x == p.previous.x || i.y == p.current.y == p.previous.y)
                n.add(new Path(i, p.current, p.turns));
            else
                n.add(new Path(i, p.current, p.turns+1));
        }

        return n;
    }

    // ..

}

private class Path
{
    public Point current, previous;
    public int turns;

    public Path(Point curr, Point prev, int tur)
    {
        current = curr;
        previous = prev;
        turns = tur;
    }
}

答案 2 :(得分:0)

我申请的解决方案:

我首先使用真正的A *算法来找到最短路径,并且我使用曼哈顿距离作为启发式目标估计。为了更多地拉直路径,并选择具有最少匝数的路径,我在每次迭代中使用了以下策略:

enter code here

Tile first = currentNode.parent;
Tile curr  = currentNode;
Tile last  = successorOfCurrentNode;
if (first != null)
{
    if ((first.X == curr.X && first.Y != curr.Y) && (curr.Y == last.Y && curr.X != last.X))
    {
        // We got turn
        currentNode.Cost += 10;
        currentNode.calcuateTotalCost();

        successorOfCurrentNode.Cost += 5;
        successorOfCurrentNode.calcuateTotalCost();
    }
    else if ((first.X != curr.X && first.Y == curr.Y) && (curr.X == last.X && curr.Y != last.Y))
    {
        // We got turn
        currentNode.Cost += 10;
        currentNode.calcuateTotalCost();

        successorOfCurrentNode.Cost += 5;
        successorOfCurrentNode.calcuateTotalCost();
    }

}