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