- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我构建了 A* 引擎,用于在具有方形节点的网格中寻找最佳路径。每个节点有八个可能的连接到其他节点(上、下、左、右、topLeft、topRight、downLeft、downRight)。
我无法根据节点的 g 分数更正路径。当我发现当前节点的连接节点(相邻节点)时,必须进行此更正,并且对于已经在开放列表但不在封闭列表或不可行走的每个相邻节点,我需要做一些事情来检查该节点是否更适合路径使用g-score 来做决定。问题是我不知道该怎么做。
我有简单的代码来发现相邻节点:
private ArrayList discoverChildren(Node parent) {
ArrayList discoveredNodes = new ArrayList();
if (parent.upNode != null &&
parent.upNode.isWalkable &&
!closedList.Contains(parent.upNode)) {
if (!openList.Contains(parent.upNode)) {
openList.Add(parent.upNode);
parent.upNode.parent = parent;
calculateScores(parent.upNode);
discoveredNodes.Add(parent.upNode);
} else {
// Here i must check do I need to change path and update scores
}
} ...
最佳答案
我找到了解决方案,但该解决方案在一种情况下没有给出正确的路径。我会把我所有的代码放在一起,这样人们就可以改进和使用这个解决方案。如果您以任何方式改进此代码,请在此处发布,以便我们看到您的解决方案。谢谢!
首先,我更改了我的 calculateScore(...) 方法和他调用的方法。然后我实现上一篇文章中缺少的代码。
节点类:
using System;
using UnityEngine;
using System.Collections;
public class Node {
public Cell cell {get; set;} // Unity Component that is linked to this node
public bool isWalkable {get; set;}
public int x {get; set;}
public int z {get; set;}
public Node rightNode {get; set;}
public Node leftNode {get; set;}
public Node upNode {get; set;}
public Node downNode {get; set;}
public Node upLeftNode {get; set;}
public Node upRightNode {get; set;}
public Node downLeftNode {get; set;}
public Node downRightNode {get; set;}
public Node[] children {get; set;}
public Node parent {get; set;}
public int gScore {get; set;}
public int hScore {get; set;}
public int fScore {get; set;}
public void setGScore(Node start, bool isPenaltyApplied) {
if (start.parent == null) {
gScore = 0;
} else {
if (isPenaltyApplied) {
gScore = start.parent.gScore + 14;
} else {
gScore = start.parent.gScore + 10;
}
}
}
public void setHScore(Node destination, bool isPenaltyApplied) {
if (parent == null) {
hScore = 0;
return;
}
if (parent.hScore == 0) {
hScore = Node.calculateHeuristic(this, destination) * 10;
} else {
hScore = parent.hScore + 10;
}
if (isPenaltyApplied) {
hScore += 10;
}
}
public void updateFScore() {
fScore = gScore + hScore;
}
public Node[] getAllChildren() {
if (this.children == null) {
Node[] children = new Node[8];
children[0] = rightNode;
children[1] = leftNode;
children[2] = upNode;
children[3] = downNode;
children[4] = upLeftNode;
children[5] = upRightNode;
children[6] = downLeftNode;
children[7] = downRightNode;
this.children = children;
}
return this.children;
}
public static int calculateHeuristic(Node from, Node to) {
int distance = 0;
int startX = from.x;
int startZ = from.z;
int destinationX = to.x;
int destinationZ = to.z;
while (startX != destinationX) {
if (startX < destinationX) {
startX++;
} else if (startX > destinationX) {
startX--;
}
distance++;
}
while (startZ != destinationZ) {
if (startZ < destinationZ) {
startZ++;
} else if (startZ > destinationZ) {
startZ--;
}
distance++;
}
return distance;
}
}
引擎类:
using System;
using UnityEngine;
using System.Collections;
public class Engine {
private ArrayList openList;
private ArrayList closedList;
private ArrayList potentialPaths;
public ArrayList path {get; private set;}
public Node startNode {get; set;}
public Node destinationNode {get; set;}
public bool isPathFound {get; set;}
public void startEngine() {
if (startNode != null && destinationNode != null) {
openList = new ArrayList();
closedList = new ArrayList();
traverseNodes();
if (isPathFound) {
path = findPath();
}
}
}
private ArrayList findPath() {
ArrayList bestPath = new ArrayList();
Node currentNode = destinationNode;
while (!object.ReferenceEquals(currentNode, startNode)) {
bestPath.Add(currentNode);
clearUnnecessaryNode(currentNode);
currentNode = currentNode.parent;
}
bestPath.Add(currentNode);
return bestPath;
}
private void clearUnnecessaryNode(Node node) {
Node firstParent = node.parent;
if (object.ReferenceEquals(firstParent, startNode)) {
return;
}
Node secondParent = firstParent.parent;
if (object.ReferenceEquals(node.upRightNode, secondParent)) {
if (node.rightNode != null &&
node.upNode != null &&
node.rightNode.isWalkable &&
node.upNode.isWalkable) {
node.parent = secondParent;
path.Remove(firstParent);
}
}
if (object.ReferenceEquals(node.upLeftNode, secondParent)) {
if (node.leftNode != null &&
node.upNode != null &&
node.leftNode.isWalkable &&
node.upNode.isWalkable) {
node.parent = secondParent;
path.Remove(firstParent);
}
}
if (object.ReferenceEquals(node.downLeftNode, secondParent)) {
if (node.leftNode != null &&
node.downNode != null &&
node.leftNode.isWalkable &&
node.downNode.isWalkable) {
node.parent = secondParent;
path.Remove(firstParent);
}
}
if (object.ReferenceEquals(node.downRightNode, secondParent)) {
if (node.rightNode != null &&
node.downNode != null &&
node.rightNode.isWalkable &&
node.downNode.isWalkable) {
node.parent = secondParent;
path.Remove(firstParent);
}
}
}
private void traverseNodes() {
Node bestNode = startNode;
openList.Add(bestNode);
calculateScores(bestNode, false);
while (!object.ReferenceEquals(bestNode, destinationNode)) {
discoverChildren(bestNode);
closedList.Add(bestNode);
openList.Remove(bestNode);
bestNode = chooseBestNode(bestNode);
if (bestNode == null) {
// Path not found
return;
}
if (object.ReferenceEquals(bestNode, destinationNode)) {
closedList.Add(bestNode);
}
}
// Success
isPathFound = true;
}
private void calculateScores(Node node, bool isPenaltyApplied) {
node.setGScore(startNode, isPenaltyApplied);
node.setHScore(destinationNode, isPenaltyApplied);
node.updateFScore();
}
private ArrayList discoverChildren(Node parent) {
ArrayList discoveredNodes = new ArrayList();
int currentCost = 0;
int newCost = 0;
if (parent.upNode != null &&
parent.upNode.isWalkable &&
!closedList.Contains(parent.upNode)) {
if (!openList.Contains(parent.upNode)) {
openList.Add(parent.upNode);
parent.upNode.parent = parent;
calculateScores(parent.upNode, false);
discoveredNodes.Add(parent.upNode);
} else {
currentCost = parent.upNode.parent.gScore + parent.upNode.gScore;
newCost = parent.gScore + parent.upNode.gScore;
if (newCost < currentCost) {
parent.upNode.parent = parent;
calculateScores(parent.upNode, false);
}
}
}
if (parent.downNode != null &&
parent.downNode.isWalkable &&
!closedList.Contains(parent.downNode)) {
if (!openList.Contains(parent.downNode)) {
openList.Add(parent.downNode);
parent.downNode.parent = parent;
calculateScores(parent.downNode, false);
discoveredNodes.Add(parent.downNode);
} else {
currentCost = parent.downNode.parent.gScore + parent.downNode.gScore;
newCost = parent.gScore + parent.downNode.gScore;
if (newCost < currentCost) {
parent.downNode.parent = parent;
calculateScores(parent.downNode, false);
}
}
}
if (parent.leftNode != null &&
parent.leftNode.isWalkable &&
!closedList.Contains(parent.leftNode)) {
if (!openList.Contains(parent.leftNode)) {
openList.Add(parent.leftNode);
parent.leftNode.parent = parent;
calculateScores(parent.leftNode, false);
discoveredNodes.Add(parent.leftNode);
} else {
currentCost = parent.leftNode.parent.gScore + parent.leftNode.gScore;
newCost = parent.gScore + parent.leftNode.gScore;
if (newCost < currentCost) {
parent.leftNode.parent = parent;
calculateScores(parent.leftNode, false);
}
}
}
if (parent.rightNode != null &&
parent.rightNode.isWalkable &&
!closedList.Contains(parent.rightNode)) {
if (!openList.Contains(parent.rightNode)) {
openList.Add(parent.rightNode);
parent.rightNode.parent = parent;
calculateScores(parent.rightNode, false);
discoveredNodes.Add(parent.rightNode);
} else {
currentCost = parent.rightNode.parent.gScore + parent.rightNode.gScore;
newCost = parent.gScore + parent.rightNode.gScore;
if (newCost < currentCost) {
parent.rightNode.parent = parent;
calculateScores(parent.rightNode, false);
}
}
}
if (parent.upRightNode != null &&
parent.upNode != null &&
parent.rightNode != null &&
parent.upRightNode.isWalkable &&
parent.upNode.isWalkable &&
parent.rightNode.isWalkable &&
!closedList.Contains(parent.upRightNode)) {
if (!openList.Contains(parent.upRightNode)) {
openList.Add(parent.upRightNode);
parent.upRightNode.parent = parent;
calculateScores(parent.upRightNode, true);
discoveredNodes.Add(parent.upRightNode);
} else {
currentCost = parent.upRightNode.parent.gScore + parent.upRightNode.gScore;
newCost = parent.gScore + parent.upRightNode.gScore;
if (newCost < currentCost) {
parent.upRightNode.parent = parent;
calculateScores(parent.upRightNode, true);
}
}
}
if (parent.upLeftNode != null &&
parent.upNode != null &&
parent.leftNode != null &&
parent.upLeftNode.isWalkable &&
parent.upNode.isWalkable &&
parent.leftNode.isWalkable &&
!closedList.Contains(parent.upLeftNode)) {
if (!openList.Contains(parent.upLeftNode)) {
openList.Add(parent.upLeftNode);
parent.upLeftNode.parent = parent;
calculateScores(parent.upLeftNode, true);
discoveredNodes.Add(parent.upLeftNode);
} else {
currentCost = parent.upLeftNode.parent.gScore + parent.upLeftNode.gScore;
newCost = parent.gScore + parent.upLeftNode.gScore;
if (newCost < currentCost) {
parent.upLeftNode.parent = parent;
calculateScores(parent.upLeftNode, true);
}
}
}
if (parent.downRightNode != null &&
parent.downNode != null &&
parent.rightNode != null &&
parent.downRightNode.isWalkable &&
parent.downNode.isWalkable &&
parent.rightNode.isWalkable &&
!closedList.Contains(parent.downRightNode)) {
if (!openList.Contains(parent.downRightNode)) {
openList.Add(parent.downRightNode);
parent.downRightNode.parent = parent;
calculateScores(parent.downRightNode, true);
discoveredNodes.Add(parent.downRightNode);
} else {
currentCost = parent.downRightNode.parent.gScore + parent.downRightNode.gScore;
newCost = parent.gScore + parent.downRightNode.gScore;
if (newCost < currentCost) {
parent.downRightNode.parent = parent;
calculateScores(parent.downRightNode, true);
}
}
}
if (parent.downLeftNode != null &&
parent.downNode != null &&
parent.leftNode != null &&
parent.downLeftNode.isWalkable &&
parent.downNode.isWalkable &&
parent.leftNode.isWalkable &&
!closedList.Contains(parent.downLeftNode)) {
if (!openList.Contains(parent.downLeftNode)) {
openList.Add(parent.downLeftNode);
parent.downLeftNode.parent = parent;
calculateScores(parent.downLeftNode, true);
discoveredNodes.Add(parent.downLeftNode);
} else {
currentCost = parent.downLeftNode.parent.gScore + parent.downLeftNode.gScore;
newCost = parent.gScore + parent.downLeftNode.gScore;
if (newCost < currentCost) {
parent.downLeftNode.parent = parent;
calculateScores(parent.downLeftNode, true);
}
}
}
return discoveredNodes;
}
private Node chooseBestNode(Node closedNode) {
if (openList.Count == 0) {
return null;
}
Node bestNode = (Node)openList[0];
foreach (Node node in openList) {
if (node.fScore < bestNode.fScore) {
bestNode = node;
} else if (node.fScore == bestNode.fScore) {
if (node.gScore < bestNode.gScore) {
bestNode = node;
} else if (object.ReferenceEquals(node, closedNode.upNode) ||
object.ReferenceEquals(node, closedNode.leftNode) ||
object.ReferenceEquals(node, closedNode.rightNode) ||
object.ReferenceEquals(node, closedNode.downNode)) {
// priority have cell that is not in corner of current cell
bestNode = node;
}
}
}
return bestNode;
}
}
关于c# - 如何根据 g-score 修正路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14926161/
BufferedImage image = ImageIO.read(SpriteSheet.class.getResource(path)); BufferedImage image = Image
希望有人能够帮助我解决将我的 React 应用程序推送到 Heroku 时遇到的问题。 heroku 日志反复显示以下错误。 at=error code=H10 desc="App crashed"
我是 Kotlin 的新手,我正在经历这样的例子。 . . package com.example.lambda1 import spark.Spark.get fun main(args: Arra
如果您已经安装了 32 位 JDK,请在中定义一个 JAVA_HOME 变量 Computer>System Properties>System Setting>Enviorment VAriable
我正在开发一个独立于平台的应用程序。我收到一个文件 URL*。在 Windows 上,这些是: file:///Z:/folder%20to%20file/file.txt file://host/f
我在 OSX、Objective-C 上。 我有一个像 这样的路径/NSURL /Users/xxx/Desktop/image2.png 但我将它传递给第三方应用程序,该应用程序会像 excpect
我已经安装了 Android studio 和插件的 DART,FLUTTER 来启动 flutter,但是因为我在创建我的第一个 flutter 项目时无法提供 sdk 路径。 最佳答案 我试图找出
127.0.0.1:8000/api/仅包含来自第二个应用程序的 url,但我将两个 url 模块链接到相同的模式。甚至有可能做到这一点吗? 第一个应用程序: from django.urls imp
对于大量图像(大约 1k,加上相同数量的拇指,在大约 500 个文件夹中),我们要求网站上使用的所有图像 URI 都必须具有 SEO 优化路径。它们已经准备好并提供完整的路径结构(每个文件夹包含一个具
为什么 f 不是一个文件?什么可能导致这种情况? String currentPhotoPath = "file:/storage/sdcard0/Pictures/someFileName.
Gradle 中的项目名称或路径中允许使用哪些字符? 它是否与特定操作系统的目录名称中允许的字符相同(例如: http://en.wikipedia.org/wiki/Filename#Reserve
我有一个包含文件夹路径的表格。我需要找到层次结构中这些文件夹之间的所有“差距”。我的意思是,如果表格包含这 3 个文件夹: 'A' 'A\B\C' 'A\B\C\D\E\F\G' 我需要在层次结构中找
我在 Linux 服务器上的/home/subversion 中安装了 svn - 那里有一个 ROOT 文件夹,其中包含 db 和 conf 等文件夹。没有映射到项目名称的文件夹,请有人告诉我如何列
对于我的图像位置:/src/assets/bitmap/sample.jpg 给出了关键配置: context: resolve('src') output: { path: resolve('b
我需要创建带有圆角的 SVG 路径,以将它们导出到 DXF 进行切割。我的问题是角应该是圆弧,而不是贝塞尔曲线。 使用 arc 命令相对容易处理直角,因为半径也是从拐角到圆弧起点的距离。对于其他角度,
大家好,我正在玩 Airflow,我正在阅读这篇很有帮助的 tutorial .我正在寻求帮助以更好地了解 Admin->Connection 如何在 Conn Type: File (path) 方
我的目标是定义R将用于安装和搜索库的单个路径。我read可以通过更改Rprofile.site安装路径中的R文件来完成。我在那里尝试了两个命令: .libPaths("D:/RLibrary") .L
我有一个问题:当我在一个页面中时,我想返回到上一页。我使用 $routeProvider。如何读取之前的 url? 我尝试在我的 Controller 中使用此代码但不起作用... angular.m
我正在尝试将一个文件从我的主干合并到一个分支(wc),并且对于看起来位于当前合并操作中不涉及的分支上的路径出现奇怪的未找到路径错误。 例如,在我们的 svn 项目中,我们有: 分行 分支 0 分支 1
我有一个树数据序列化如下: 关系:P到C是“一对多”,C到P是“一对一”。所以列 P 可能有重复的值,但列 C 有唯一的值。 P, C 1, 2 1, 3 3, 4 2, 5 4, 6 # in da
我是一名优秀的程序员,十分优秀!