fix start/end nodes not being properly handled in algorithm with ChangeController

essentially, the start and end nodes were being marked as Seen and/or Expanded instead of as Start/End nodes. The end node was easy to correct, but the start node was difficult without messing with the algorithm's performance (potentially), so I opted for a dirtier but probably more performant measure by just removing the Change value type.
This commit is contained in:
Xevion
2020-11-24 20:42:38 -06:00
parent e637eac65b
commit bfff8fdb57
4 changed files with 45 additions and 27 deletions
+10 -10
View File
@@ -28,10 +28,8 @@ namespace Algorithms {
ChangeController.AddChange(new Change(start.x, start.y, GridNodeType.Start, GridNodeType.Empty));
ChangeController.AddChange(new Change(end.x, end.y, GridNodeType.End, GridNodeType.Empty));
var startNode = new Node(start, true);
var endNode = new Node(end, true);
Node startNode = _nodeGrid.Grid[start.x, start.y];
Node endNode = _nodeGrid.Grid[end.x, end.y];
_path = new Stack<Node>();
_openList = new List<Node>();
@@ -41,11 +39,12 @@ namespace Algorithms {
Node current = startNode;
// add start node to Open List
startNode.State = NodeState.Open;
_openList.Add(startNode);
while (_openList.Count != 0) {
current = _openList.First();
_openList.Remove(current);
current = _openList[0];
_openList.RemoveAt(0);
current.State = NodeState.Closed;
ChangeController.AddChange(new Change(
@@ -56,8 +55,6 @@ namespace Algorithms {
if (current.Position == endNode.Position)
break;
RecordState();
Node[] adjacentNodes = this._nodeGrid.GetAdjacentNodesArray(current);
for (int i = 0; i < adjacentNodes.Length; i++) {
Node node = adjacentNodes[i];
@@ -68,7 +65,8 @@ namespace Algorithms {
node.Cost = node.Weight + node.Parent.Cost;
node.State = NodeState.Open;
ChangeController.AddChange(new Change(node.Position.x, node.Position.y, GridNodeType.Seen, GridNodeType.Empty));
ChangeController.AddChange(new Change(node.Position.x, node.Position.y, GridNodeType.Seen,
GridNodeType.Empty));
// Insert the new node into the sorted open list in ascending order
int index = _openList.BinarySearch(node);
@@ -83,12 +81,14 @@ namespace Algorithms {
return null;
}
// Fix start position being overriden
ChangeController.RemovePositions(start, 1);
// if all good, return path
Node temp = _closedList[_closedList.IndexOf(current)];
if (temp == null) return null;
do {
_path.Push(temp);
RecordState();
temp = temp.Parent;
} while (temp != null && !temp.Equals(startNode));
+4
View File
@@ -12,4 +12,8 @@
this.Old = oldType;
this.Time = UnityEngine.Time.realtimeSinceStartup;
}
public override string ToString() {
return $"Change({X}, {Y}, {Old} -> {New})";
}
}
+23 -1
View File
@@ -13,11 +13,12 @@ public class ChangeController {
private readonly List<Change> _changes;
public int Count => _changes.Count;
public Change CurrentChange => _changes[Index];
public double CurrentRuntime => _changes[Index].Time - _changes[0].Time;
public ChangeController(GridNodeType[,] initial) {
_initial = initial;
Current = initial;
Index = 0;
Index = -1;
_changes = new List<Change>();
}
@@ -104,4 +105,25 @@ public class ChangeController {
else
Move(diff);
}
/// <summary>
/// Removes all Change values referencing a specific position.
/// Intended for fixing start and end positions.
/// Works in reverse, i.e. count = 1 removes the last position if any.
/// </summary>
/// <param name="position">The Vector2Int position to look for.</param>
/// <param name="count">Maximum number of Change values to remove. -1 for all.</param>
public void RemovePositions(Vector2Int position, int count = -1) {
if (count == 0)
return;
for (int i = _changes.Count - 1; i >= 0; i--)
if (_changes[i].X == position.x && _changes[i].Y == position.y) {
_changes.RemoveAt(i);
// Return if the count is now zero.
if (--count == 0)
return;
}
}
}
+2 -10
View File
@@ -13,7 +13,6 @@ public class Manager : MonoBehaviour {
private ChangeController _state;
private int _curIndex;
private Stack<Node> _path;
private float _lastStart;
private float _runtime;
public Camera mainCamera;
@@ -45,16 +44,10 @@ public class Manager : MonoBehaviour {
_runtime += increment;
if (CurrentIndex < _state.Count)
this.LoadNextState();
LoadNextState();
else {
try {
_lastStart = Time.realtimeSinceStartup;
GeneratePath();
CurrentIndex = 0;
// _curIndex = path != null && path.Count > 30 ? 0 : _states.Count;
}
catch (ArgumentOutOfRangeException) {
}
}
}
@@ -79,9 +72,8 @@ public class Manager : MonoBehaviour {
_state.MoveTo(CurrentIndex);
gridController.LoadGridState(_state.Current);
float change = _state.CurrentChange.Time - _lastStart;
string pathCount = _path != null ? $"{_path.Count}" : "N/A";
debugText.text = $"{change * 1000.0:F1}ms\n" +
debugText.text = $"{_state.CurrentRuntime * 1000.0:F1}ms\n" +
$"{this.CurrentIndex:000} / {_state.Count:000}\n" +
$"Path: {pathCount} tiles";
}