Android A *路径查找无限循环?

时间:2011-07-13 04:03:50

标签: java android algorithm artificial-intelligence

我采取了大胆的步骤,试图学习这个算法,并在我的游戏中实现它并“理解”它是容易的部分。在尝试实现它时,我不断得到一个无法退出的无限循环。我一遍又一遍地通过我的代码,但我必须遗漏一些东西或者不理解它的一部分。任何帮助将不胜感激。

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 += currentNode.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;
}

}

sx,sy,dx和dy是2d数组中的起始位置和目标位置。 为了测试目的,我传递了固定数字sx = 1,sy = 1,dx = 5,dy = 5.换句话说,字符位于(1,1),触摸点位于(5,5)。

5 个答案:

答案 0 :(得分:1)

您缺少的一件事是按照costF排序您的openList。

另外,当您应该与equals进行比较时,您将2个Node对象与==进行比较。也许这就是为什么你永远不会达到目标点......

答案 1 :(得分:0)

这看起来像一个非常好的教程,它在java中,可能比较你的实现,看看是否有任何弹出Pathfinding for games

答案 2 :(得分:0)

这对我来说似乎是一个错误:您将两次成本G添加到neighbournode 一旦你第一次创建节点,一次在'if'语句中?

                neighborNode.costG += currentNode.costG;

不确定这是否会导致无限循环,但它确实看起来像一个错误

答案 3 :(得分:0)

付出很多努力:设置currentNode后,清除openList。

答案 4 :(得分:-2)

命名空间Intraweb.Dentry {     公共类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



}

}