开发者

Android A* path finding looping infinitely?

I took a bold step in trying to learn this algorithm and implementing it in my game and "understanding" it was the easy part. In trying to implement it, I keep getting an infinite loop that does not quit. I've been through my code over and over again but I must be missing something or not understanding a part of it. Any help would be appreciated.

public class PathFinder {
private LinkedList<Node> openList;
private LinkedList<Node> closedList;

public PathFinder() {
    openList = new LinkedList<Node>();
    closedList = new LinkedList<Node>();
}

private List<Node> buildPath(Node node) {
    LinkedList<Node> path = new LinkedList<Node>();
    while (node.parentNode != null) {
        path.addFirst(node);
        node = node.parentNode;
    }
    return path;
}

public List<Node> findPath(int sx, int sy, int dx, int dy) {
    Node startNode = new Node(sx, sy);
    Node endNode = new Node(dx, dy);
    startNode.costG = 0;
    startNode.costH = startNode.getManhattanCost(endNode);
    startNode.parentNode = null;
    openList.add(startNode);

    while (!openList.isEmpty()) {
        Node currentNode = (Node) openList.removeFirst();
        if (currentNode == endNode) {
            Log.d("android", "found path");
            return buildPath(endNode);
        } else {
            currentNode.createNeighbors();
            List<Node> neighbors = currentNode.getNeighbors();
            for (int i = 0; i < neighbors.size(); i++) {
                Node neighborNode = neighbors.get(i);
                neighborNode.costG += curren开发者_Go百科tNode.costG;
                neighborNode.costH = neighborNode.getManhattanCost(endNode);
                neighborNode.costF = neighborNode.costG + neighborNode.costH;
                boolean isInOpen = openList.contains(neighborNode);
                boolean isInClosed = closedList.contains(neighborNode);

                if ((!isInOpen && !isInClosed) || neighborNode.costG < currentNode.costG) {
                    neighborNode.parentNode = currentNode;
                    neighborNode.costG += currentNode.costG;
                    neighborNode.costF = neighborNode.costG + neighborNode.costH;
                    if (isInClosed) {
                        closedList.remove(neighborNode);
                    }
                    if (!isInOpen) {
                        openList.add(neighborNode);
                    }
                }
            }
            closedList.add(currentNode);
        }
    }
    openList.clear();
    closedList.clear();
    return null;
}

}

public class Node {
public Node parentNode;
public List<Node> neighbors;
public int x;
public int y;
public int costG;
public int costH;
public int costF;

public Node(int x, int y) {
    this.x = x;
    this.y = y;
    neighbors = new ArrayList<Node>();
    costG = 10;
}

public void createNeighbors() {
    neighbors.add(new Node(x + 1, y));
    neighbors.add(new Node(x, y + 1));
    neighbors.add(new Node(x - 1, y));
    neighbors.add(new Node(x, y - 1));
}

public int getManhattanCost(Node node) {
    int i = (int) Math.abs(x - node.x);
    int j = (int) Math.abs(y - node.y);
    costH = i + j;
    return costH;
}

public int getTotalCost() {
    return costG + costH;
}

public List<Node> getNeighbors() {
    return neighbors;
}

}

The sx, sy, dx, and dy are starting position and goal position in a 2d array. I passed int fixed numbers for testing purposes sx = 1, sy = 1, dx = 5, dy = 5. In other words, character is at (1, 1) and the touch point is at (5, 5).


one thing you're missing is having your openList ordered by costF.

Also, you're comparing 2 Node objects with ==, when you should be comparing with equals. Maybe thats why you never reach the goal point ...


This looks like a pretty good tutorial and it's in java, maybe compare you implementation and see if anything pops out Pathfinding for games


This looks like a bug to me: you are adding the costG to the neighbournode twice Once when you first create the node and once in the 'if' statement ?

                neighborNode.costG += currentNode.costG;

Not really sure if that would cause your infinite loop, but it does look like a bug


Solved with much effort: after setting the currentNode, clear the openList.


namespace Intraweb.Dentry { public class SQLDentry : Dentry, IDentry { private string strConnection;

    # region "Functions"

    # region "Get Single Values"

    public object GetValue(string SQL, ValueDataType VluType)
    {
        SqlConnection con = new SqlConnection(strConnection);
        SqlCommand SqlCMD = new SqlCommand(SQL, con);

        try
        {
            object RtVlu;
            con.Open();
            RtVlu = SqlCMD.ExecuteScalar();
            return Convert_Value(RtVlu, VluType);
        }
        catch (Exception e)
        {
            throw new Exception("Error occurred :-" + e.Message);
        }
        finally
        {
            SqlCMD.Dispose();
            con.Close();
            con.Dispose();
        }
    }

    public object GetValue(string SQL, ValueDataType VluType, SqlTransaction SqlTrn, SqlConnection con)
    {
        SqlCommand SqlCMD = new SqlCommand(SQL, con);

        try
        {
            SqlCMD.Transaction = SqlTrn;
            object RtVlu;
            RtVlu = SqlCMD.ExecuteScalar();
            return Convert_Value(RtVlu, VluType);
        }
        catch (Exception e)
        {
            throw new Exception("Error occurred :-" + e.Message, e);
        }
        finally
        {
            SqlCMD.Dispose();
            con.Close();
        }
    }

    #endregion

    # region "Execute Commands"

    public bool RunCommand(string strSQL, SqlTransaction SqlTrn, SqlConnection con)
    {
        SqlCommand Sqlcmd = new SqlCommand();

        try
        {
            Sqlcmd.CommandType = CommandType.Text;
            Sqlcmd.Connection = con;
            Sqlcmd.Transaction = SqlTrn;

            Sqlcmd.CommandText = strSQL;
            Sqlcmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            con.Close();
            SqlTrn.Rollback();
            throw new Exception("Error Occured :-" + e.Message, e);
        }
        finally
        {
            Sqlcmd.Dispose();
        }
    }

    public bool RunCommand(string strSQL)
    {
        SqlCommand Sqlcmd = new SqlCommand();
        SqlConnection con = new SqlConnection(strConnection);

        try
        {
            Sqlcmd.CommandType = CommandType.Text;
            Sqlcmd.Connection = con;

            Sqlcmd.CommandText = strSQL;
            con.Open();
            Sqlcmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception e)
        {
            throw new Exception("Error Occured :-" + e.Message, e);
        }
        finally
        {
            Sqlcmd.Dispose();
            con.Close();
            con.Dispose();
        }
    }

    # endregion

    # region "Fill Tables with Normal Sql Queries"


    public DataTable GetDataTable(string strSQL)
    {
        SqlConnection con = new SqlConnection(strConnection);
        SqlCommand SqlCmd = new SqlCommand(strSQL, con);

        try
        {
            DataTable dt = new DataTable();
            con.Open();
            dt.Load(SqlCmd.ExecuteReader());
            return dt;
        }
        catch (Exception e)
        {
            throw new Exception("Error occurred :-" + e.Message);
        }
        finally
        {
            con.Close();
            SqlCmd.Dispose();
            con.Dispose();
        }
    }

    public DataSet GetDataSet(string strSQL)
    {
        SqlConnection con = new SqlConnection(strConnection);
        SqlDataAdapter da = new SqlDataAdapter(strSQL, con);

        try
        {
            DataSet dt = new DataSet();
            con.Open();
            da.Fill(dt);
            return dt;
        }
        catch (Exception e)
        {
            throw new Exception("Error occurred :-" + e.Message);
        }
        finally
        {
            con.Close();
            da.Dispose();
            con.Dispose();
        }
    }

    public SqlDataReader GetDataReader(string strSQL, SqlConnection con)
    {
        SqlDataReader dr = null;
        SqlCommand SqlCmd = new SqlCommand();

        try
        {
            SqlCmd.CommandType = CommandType.Text;
            SqlCmd.Connection = con;
            SqlCmd.CommandText = strSQL;
            dr = SqlCmd.ExecuteReader();
            return dr;
        }
        catch (Exception e)
        {
            dr.Close();
            con.Close();
            throw new Exception("Error occurred :-" + e.Message);
        }
        finally 
        {
            SqlCmd.Dispose();
        }
    }

    public SqlDataReader GetDataReader(string strSQL,SqlTransaction SqlTrn, SqlConnection con)
    {
        SqlDataReader dr=null;
        SqlCommand SqlCmd = new SqlCommand();

        try
        {
            SqlCmd.CommandType = CommandType.Text;
            SqlCmd.Connection = con;
            SqlCmd.CommandText = strSQL;
            dr = SqlCmd.ExecuteReader();
            return dr;
        }
        catch (Exception e)
        {
            dr.Close();
            con.Close();
            SqlTrn.Rollback();
            throw new Exception("Error occurred :-" + e.Message);
        }
        finally
        {
            SqlCmd.Dispose();
        }

    }
    # endregion

    # endregion


    # region "Constructors"

        public SQLDentry(string ConnectionString):base(true, ConnectionString)
        {
            strConnection = ConnectionString;
        }

    #endregion



}

}

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜