From 1015886a71762aff5bae9644d487fd426bf30768 Mon Sep 17 00:00:00 2001 From: BOTLester <58360400+BOTLester@users.noreply.github.com> Date: Sun, 3 May 2020 22:28:52 +0200 Subject: [PATCH] MinHeap added, A* working --- Game1/Game1.cs | 2 +- Game1/Game1.csproj | 1 + Game1/Sources/Crops/Crops.cs | 6 +- Game1/Sources/Objects/Tractor.cs | 3 +- Game1/Sources/Pathing/A-Star/Astar.cs | 40 ++-- .../Pathing/A-Star/PathSaver/MinHeap.cs | 195 ++++++++++++++++++ .../Sources/Pathing/A-Star/PathSaver/Path.cs | 2 +- .../Pathing/A-Star/PathSaver/PriorityQueue.cs | 2 + 8 files changed, 231 insertions(+), 20 deletions(-) create mode 100644 Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs diff --git a/Game1/Game1.cs b/Game1/Game1.cs index f652f6e..b87c073 100644 --- a/Game1/Game1.cs +++ b/Game1/Game1.cs @@ -34,7 +34,7 @@ namespace Game1 //Generates the map with some random values - input.init(graphics, new Vector2(8,8), 56, 1); //Generates the starting size + input.init(graphics, new Vector2(16,16), 56, 1); //Generates the starting size houseUnit.init(input.getTileSize(), input.getSpacing()); //Generates the house position tractorUnit.init(houseUnit.GetRectangle(), input); //Generates the Tractor tractorUnit.updateSizing(input, 0, houseUnit.getVector()); //Updates the first Size of the Tractor diff --git a/Game1/Game1.csproj b/Game1/Game1.csproj index 91feed1..6d43d60 100644 --- a/Game1/Game1.csproj +++ b/Game1/Game1.csproj @@ -50,6 +50,7 @@ + diff --git a/Game1/Sources/Crops/Crops.cs b/Game1/Sources/Crops/Crops.cs index 23e7641..ccbdcb7 100644 --- a/Game1/Sources/Crops/Crops.cs +++ b/Game1/Sources/Crops/Crops.cs @@ -37,15 +37,15 @@ class Crops } else if (Status == 2) { - return 20; + return 5; } else if (Status == 3) { - return 30; + return 20; } else { - return 40; + return 30; } } diff --git a/Game1/Sources/Objects/Tractor.cs b/Game1/Sources/Objects/Tractor.cs index 6e4ae27..0eb1c83 100644 --- a/Game1/Sources/Objects/Tractor.cs +++ b/Game1/Sources/Objects/Tractor.cs @@ -104,11 +104,10 @@ class Tractor else { //Sets a random Target - path = smartTractor.returnChoice(1); int xTarget = (int)TargetPosition.X / (sizeTile + Spacing); int yTarget = (int)TargetPosition.Y / (sizeTile + Spacing); currentTask = scoreSystem.MessageAndScore(farm.getCrop(xTarget, yTarget).Status, 1); - + path = smartTractor.returnChoice(1); } TargetPosition = path.Reduce().getCords() * (sizeTile + Spacing); diff --git a/Game1/Sources/Pathing/A-Star/Astar.cs b/Game1/Sources/Pathing/A-Star/Astar.cs index 6d54ce8..77b4aea 100644 --- a/Game1/Sources/Pathing/A-Star/Astar.cs +++ b/Game1/Sources/Pathing/A-Star/Astar.cs @@ -65,31 +65,41 @@ class Astar public Path FindPath() { Path path = new Path(); - PriorityQueue openList = new PriorityQueue(); - PriorityQueue closedList = new PriorityQueue(); + //PriorityQueue openList = new PriorityQueue(); + MinHeap openList = new MinHeap(); + //PriorityQueue closedList = new PriorityQueue(); + MinHeap closedList = new MinHeap(); Nodes target = new Nodes(targetPos); Nodes startPos = new Nodes (tractorPos); Nodes current = null; int g = 0; - openList.Enqueue(startPos); + //openList.Enqueue(startPos); + openList.Insert(startPos); - while (openList.Count > 0) + //while (openList.Count > 0) + while (openList.GetSize() > 0) { - current = openList.Peek(); + current = openList.getMin(); + //current = openList.Peek(); //g = current.getG(); - closedList.Enqueue(current); - openList.Dequeue(); + closedList.Insert(current); + //closedList.Enqueue(current); + openList.removeMin(); + //openList.Dequeue(); - if (closedList.Exists(target.getCords())) + if (current.getCords() == target.getCords()) break; + + //if (closedList.Exists(target.getCords())) + // break; + var adjacentNodes = GetAdjacentNodes(current.getCords()); //g++; - foreach(var adjacentNode in adjacentNodes) { - g = g + crops[(int)adjacentNode.getCords().X, (int)adjacentNode.getCords().Y].getCostOnMovement(); + g = current.getG() + crops[(int)adjacentNode.getCords().X, (int)adjacentNode.getCords().Y].getCostOnMovement(); if (closedList.Exists(adjacentNode.getCords())) continue; if (!(openList.Exists(adjacentNode.getCords()))) @@ -99,7 +109,8 @@ class Astar adjacentNode.setH(ComputeHScore(adjacentNode.getCords(), target.getCords())); adjacentNode.calculateF(); adjacentNode.setParent(current); - openList.Enqueue(adjacentNode); + openList.Insert(adjacentNode); + //openList.Enqueue(adjacentNode); } else { @@ -111,6 +122,7 @@ class Astar } } } + //openList.BuildMinHeap(openList.GetList()); } while (current != null) @@ -119,8 +131,10 @@ class Astar current = current.getParent(); } path = path.FlipArray(); - openList.Clear(); - closedList.Clear(); + openList.deleteHeap(); + closedList.deleteHeap(); + //openList.Clear(); + //closedList.Clear(); return path; } diff --git a/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs b/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs new file mode 100644 index 0000000..7f7b2a5 --- /dev/null +++ b/Game1/Sources/Pathing/A-Star/PathSaver/MinHeap.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +class MinHeap +{ + List arr = new List(); + public MinHeap() + { + arr = new List(); + } + + public void Insert(Nodes value) + { + arr.Add(value); + siftUp(arr.Count - 1); + } + + public void removeMin() + { + if (arr.Count == 0) + { + throw new Exception("Heap is empty!"); + } + else + { + arr[0] = arr[arr.Count - 1]; + arr.RemoveAt(arr.Count - 1); + if (arr.Count > 0) + { + siftDown(0); + } + } + } + + private void siftUp(int index) + { + int parentIndex; + Nodes temp; + if (index != 0) + { + parentIndex = getParentIndex(index); + if (arr[parentIndex].getF() > arr[index].getF()) + { + temp = arr[parentIndex]; + arr[parentIndex] = arr[index]; + arr[index] = temp; + siftUp(parentIndex); + } + } + } + + private int getParentIndex(int index) + { + return (index - 1) / 2; + } + + private void siftDown(int nodeIndex) + { + int leftChildIndex, rightChildIndex, minIndex; + Nodes tmp; + + leftChildIndex = getLeftChildIndex(nodeIndex); + + rightChildIndex = getRightChildIndex(nodeIndex); + + if (rightChildIndex >= arr.Count) + { + if (leftChildIndex >= arr.Count) + { + return; + } + else + { + minIndex = leftChildIndex; + } + } + else + { + if (arr[leftChildIndex].getF() <= arr[rightChildIndex].getF()) + { + minIndex = leftChildIndex; + } + else + { + minIndex = rightChildIndex; + } + } + if (arr[nodeIndex].getF() > arr[minIndex].getF()) + { + tmp = arr[minIndex]; + + arr[minIndex] = arr[nodeIndex]; + + arr[nodeIndex] = tmp; + + siftDown(minIndex); + } + } + + private int getRightChildIndex(int nodeIndex) + { + return (2 * nodeIndex) + 2; + } + + private int getLeftChildIndex(int nodeIndex) + { + return (2 * nodeIndex) + 1; + } + + public Nodes getMin() + { + return arr[0]; + } + + public void BuildMinHeap(List input) + { + if (arr.Count > 0) + { + //clear the current heap + //Array.Resize(ref arr, input.Length); + //heapSize = 0; + for (int i = 0; i < arr.Count; i++) + { + arr[i] = input[i]; + } + } + for (int i = arr.Count - 1 / 2; i >= 0; i--) + { + MinHeapify(i); + } + } + + private void MinHeapify(int index) + { + int left = 2 * index; + int right = (2 * index) + 1; + int smallest = index; + if (left < arr.Count && arr[left].getF() < arr[index].getF()) + { + smallest = left; + } + else + { + smallest = index; + } + if (right < arr.Count && arr[right].getF() < arr[smallest].getF()) + { + smallest = right; + } + if (smallest != index) + { + swap(ref arr, index, smallest); + MinHeapify(smallest); + } + } + + private void swap(ref List input, int a, int b) + { + Nodes temp = input[a]; + input[a] = input[b]; + input[b] = temp; + } + + public int GetSize() + { + return arr.Count; + } + + public Boolean Exists(Vector2 coordinates) + { + if (arr.Count == 0) + return false; + foreach (Nodes node in arr) + { + if (node.getCords() == coordinates) + return true; + } + return false; + } + + public List GetList() + { + return arr; + } + + public void deleteHeap() + { + arr.Clear(); + } + +} diff --git a/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs b/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs index 0babd89..db5c550 100644 --- a/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs +++ b/Game1/Sources/Pathing/A-Star/PathSaver/Path.cs @@ -27,7 +27,7 @@ class Path { nodes[i] = nodes[i + 1]; } - + nodes[Count + 1] = null; return temp; } diff --git a/Game1/Sources/Pathing/A-Star/PathSaver/PriorityQueue.cs b/Game1/Sources/Pathing/A-Star/PathSaver/PriorityQueue.cs index bdc6be8..993a304 100644 --- a/Game1/Sources/Pathing/A-Star/PathSaver/PriorityQueue.cs +++ b/Game1/Sources/Pathing/A-Star/PathSaver/PriorityQueue.cs @@ -25,6 +25,7 @@ class PriorityQueue list.Add(x); int i = Count - 1; + while (i > 0) { int p = (i - 1) / 2; @@ -35,6 +36,7 @@ class PriorityQueue } if (Count > 0) list[i] = x; + } public void Dequeue()