4

I am stuck for last 4 days in an algorithm. I am working on Mahjong Safari type game (http://www.pogo.com/games/mahjongsafari), and I want to develop path between two tiles with least number of tiles.

I already applied A* algorithm with Manhattan Hueristic, but that generates shortest path with lots of turns. There is no need of shortest path, I just need path with min turns (preferably 2). Below is image from Mahjong Safari game, which generates path between 2 tiles. You will notice that the path from A to B and path from B to A are different.

enter image description here

Please help me, in any code or any algorithm name or any logic you think could work.

EDIT: The Solution I applied for this:

I used genuine A* Algorithm first to find shortest path, and I used Manhattan distance as heuristic goal estimate. To straighten the path more, and choose path with least number of turns, i used following tactic in each iteration:

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();
    }

}

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • 2
    This isn't really a programming question. You should probably post this question in [http://math.stackexchange.com/](http://math.stackexchange.com/) – David K Mar 12 '13 at 12:26
  • You could try adding a turning cost to your heuristic. Also, see [this post](http://stackoverflow.com/q/10329005/21727). – mbeckish Mar 12 '13 at 12:48
  • @mbeckish You are right about turning cost, I will try it. – Wajahat Karim Mar 12 '13 at 13:00
  • 4
    @DavidK - I couldn't disagree more. How can a question about an algorithm needed for a program not be a programming question? – mbeckish Mar 12 '13 at 13:08
  • @mbeckish - This question is specifically being asked without even referencing a language. If there's no language to write code, and you are purely working with an algorithm, at that point it has become math. It was my understanding that this forum was for specific programming questions, though I concede that you have much more experience here than me. – David K Mar 12 '13 at 13:16
  • @DavidK - It is acceptable here to ask for an algorithm without specifying a language. That way, people can post answers in their favorite language (or pseudocode), and the OP can then implement the algorithm in his/her language of choice. I agree that there is some overlap between devising programming algorithms and mathematics, but in my opinion this question falls squarely on the programming side of the spectrum. – mbeckish Mar 12 '13 at 13:20
  • @mbeckish - Thanks for clarifying for a newbie, and user2159914, sorry for hijacking your post! :) – David K Mar 12 '13 at 13:27
  • @DavidK I am also new to this forum... Its no problem... I have also learnt few things here today... – Wajahat Karim Mar 12 '13 at 13:35
  • @user2159914 - You're welcome. Maybe you can post your solution as an answer to this question so future readers can benefit. – mbeckish Mar 12 '13 at 17:26
  • I have edited my question, and posted the solution to this question. Thanks – Wajahat Karim Mar 13 '13 at 14:22
  • @user2159914 instead of editing your question you can also answer your own question which is a more elegant solution. Also take a look at http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ for that. – lambda Mar 13 '13 at 15:46

3 Answers3

0

You could use Dijkstra's shortest path algorithm, but in every node you should not only store the shortest path, but also the direction of that path, so you know whether you need to increase the count.

Thinking a little more, I guess you would need to store all shortest paths with their direction in every node, in order to pick the best one.

Vincent van der Weele
  • 12,927
  • 1
  • 33
  • 61
  • Thanks Huester for the comments, actually I used A* and computed all paths and then searched for least turns path, but problem is that it takes too long to compute and my game hangs while computation. – Wajahat Karim Mar 12 '13 at 12:59
0

Your problem is more simple than using a heuristic, since you don't need expectation, but it can enhance the speed of finding the optimal in case your search is not "complete" .. but rather you just want the path with minimal turns, hence you can go with Greedy Search where:

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

Here is a simple code in Java that illustrate:

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;
    }
}
Khaled.K
  • 5,828
  • 1
  • 33
  • 51
0

The Solution I applied for this:

I used genuine A* Algorithm first to find shortest path, and I used Manhattan distance as heuristic goal estimate. To straighten the path more, and choose path with least number of turns, i used following tactic in each iteration:

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();
    }

}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880