From 304218151a57928b137334499cdebd8ec0dca7d2 Mon Sep 17 00:00:00 2001
From: Pablu23 <43807157+Pablu23@users.noreply.github.com>
Date: Tue, 10 Jan 2023 22:41:29 +0100
Subject: [PATCH] Add project files.
---
.gitignore | 7 +
AStar Pathfinding.csproj | 53 +++++++
AStar Pathfinding.sln | 25 +++
Input.txt | 20 +++
Program.cs | 322 +++++++++++++++++++++++++++++++++++++++
README.md | 5 +
6 files changed, 432 insertions(+)
create mode 100644 .gitignore
create mode 100644 AStar Pathfinding.csproj
create mode 100644 AStar Pathfinding.sln
create mode 100644 Input.txt
create mode 100644 Program.cs
create mode 100644 README.md
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..926e4d2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.idea/
+.vs/
+bin/
+obj/
+Properties/
+App.config
+*.DotSettings.user
\ No newline at end of file
diff --git a/AStar Pathfinding.csproj b/AStar Pathfinding.csproj
new file mode 100644
index 0000000..5501bbf
--- /dev/null
+++ b/AStar Pathfinding.csproj
@@ -0,0 +1,53 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {A7DEE69C-2567-45A5-9694-795832A800E0}
+ Exe
+ AStar_Pathfinding
+ AStar Pathfinding
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AStar Pathfinding.sln b/AStar Pathfinding.sln
new file mode 100644
index 0000000..d218314
--- /dev/null
+++ b/AStar Pathfinding.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29411.108
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AStar Pathfinding", "AStar Pathfinding.csproj", "{A7DEE69C-2567-45A5-9694-795832A800E0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A7DEE69C-2567-45A5-9694-795832A800E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A7DEE69C-2567-45A5-9694-795832A800E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7DEE69C-2567-45A5-9694-795832A800E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A7DEE69C-2567-45A5-9694-795832A800E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E46F2074-9111-48FB-8443-52F330576EAE}
+ EndGlobalSection
+EndGlobal
diff --git a/Input.txt b/Input.txt
new file mode 100644
index 0000000..5a3b82a
--- /dev/null
+++ b/Input.txt
@@ -0,0 +1,20 @@
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+X X XX X X X X
+X XXX X X X X X
+X X X XXXXXXXXXXXXX XXXXXXX
+X XX XX X X X
+X XXX XX X X X
+X X X XXXX X
+X X E XXXXXX X
+X X X XXXXXXX X
+X XX XXXX X
+X X X
+X X X
+X X X
+X X XXXXXXXXXXXX X
+X X XXXXXXXXXXXXX X
+X XXXX XXXX X X XXXXX X
+X X X XXXXXS X X
+X X X X X X
+X X X X XX XX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..9f9682a
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,322 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AStar_Pathfinding
+{
+ public enum TypeOfNode { Start, Normal, End, Wall };
+
+ public readonly struct Coordinates
+ {
+ public readonly int X;
+ public readonly int Y;
+
+ public Coordinates(int x, int y)
+ {
+ X = x;
+ Y = y;
+ }
+ }
+
+ public class Node
+ {
+ public TypeOfNode TypeOfNode;
+ //Vorherige Node / weg zu dieser Node
+ public Node Previous;
+ // X und Y position
+ public Coordinates Coordinates;
+ //G = Distance from starting node / H = Distance from end node / F = G + H
+ public int G, H, F;
+
+ public Node(Coordinates coordinates)
+ {
+ Coordinates = coordinates;
+ TypeOfNode = TypeOfNode.Normal;
+ }
+ }
+
+ public class Map
+ {
+ private int Width { get; set; }
+ private int Height { get; set; }
+ private Node _start;
+ private Node _end;
+ private readonly Node[,] _map;
+
+ // Auch offene Liste gennant
+ private readonly List _searching = new List();
+ // Auch geschlossene Liste gennant
+ public readonly List Searched = new List();
+
+ public Map(int wi, int he)
+ {
+ Width = wi;
+ Height = he;
+
+ _map = new Node[wi, he];
+ for (int i = 0; i < Width; i++)
+ {
+ for (int j = 0; j < Height; j++)
+ {
+ _map[i, j] = new Node(new Coordinates(i, j));
+ }
+ }
+ }
+ public void SetStart(Coordinates cor)
+ {
+ _map[cor.X, cor.Y].Coordinates = cor;
+ _map[cor.X, cor.Y].TypeOfNode = TypeOfNode.Start;
+ _start = _map[cor.X, cor.Y];
+ }
+ public void SetEnd(Coordinates cor)
+ {
+ _map[cor.X, cor.Y].Coordinates = cor;
+ _map[cor.X, cor.Y].TypeOfNode = TypeOfNode.End;
+ _end = _map[cor.X, cor.Y];
+ }
+
+ public Node GetEnd()
+ {
+ return _end;
+ }
+ public void SetWalls(List walls)
+ {
+ foreach (int[] t in walls)
+ {
+ _map[t[0], t[1]].TypeOfNode = TypeOfNode.Wall;
+ }
+ }
+
+ //Errechnet die G Cost / die Distanz zu dem Startpunkt
+ private void CalculateGCost(int x, int y, Node previous)
+ {
+ int cost = 10;
+
+ if (_map[x, y].TypeOfNode == TypeOfNode.Start || _map[x, y].TypeOfNode == TypeOfNode.End) return;
+ if (previous.Coordinates.X != x && previous.Coordinates.Y != y)
+ {
+ cost += 4;
+ }
+
+ _map[x, y].G = previous.G + cost;
+ _map[x, y].Previous = previous;
+ }
+
+ //Errechnet für die ganze Karte die H Cost / die Distanz zu dem Endpunkt
+ public void CalculateAllHCost()
+ {
+ for (int i = 0; i < Width; i++)
+ {
+ for (int j = 0; j < Height; j++)
+ {
+ CalculateHCost(i, j);
+ }
+ }
+ }
+
+ //Errechnet für dieses eine Feld die H Cost / die Distanz zu dem Endpunkt
+ private void CalculateHCost(int x, int y)
+ {
+ if (_map[x, y].TypeOfNode == TypeOfNode.End) return;
+ //Wie weit das ende von dem jetzigen Punkt entfernt ist
+ _map[x, y].H = (Math.Abs(_end.Coordinates.X - x) + Math.Abs(_end.Coordinates.Y - y)) * 10;
+ }
+
+ //F Cost ist H Cost + G Cost
+ private void CalculateFCost(int x, int y) => _map[x, y].F = _map[x, y].G + _map[x, y].H;
+ public void StartPathFinding()
+ {
+ _searching.Add(_start);
+ ShowMap();
+ Search();
+ }
+ //Findet die benachbarten Nodes und fügt sie in die offene Liste hinzu, wenn sie dort nicht schon sind mit einem besseren vorgänger.
+ private void PathFinding(int x, int y)
+ {
+ for (int i = -1; i < 2; i++)
+ {
+ for (int j = -1; j < 2; j++)
+ {
+ if (!((x + i >= 0 && x + i < Width) & (y + j >= 0 && y + j < Height))) continue;
+ if (_map[x + i, y + j].TypeOfNode == TypeOfNode.Wall) continue;
+ if (_map[x + i, y + j].G == 0 & _map[x + i, y + j].TypeOfNode != TypeOfNode.Start)
+ {
+ _map[x + i, y + j].Previous = _map[x, y];
+ _searching.Add(_map[x + i, y + j]);
+ }
+ else if (_map[x + i, y + j].G > _map[x, y].G + (i == 0 && j == 0 ? 10 : 14))
+ {
+ _map[x + i, y + j].Previous = _map[x, y];
+ var t = Searched.Find(
+ item => item.Coordinates.X == x +
+ i && item.Coordinates.Y == y + j);
+ Searched.Remove(t);
+ _searching.Add(_map[x + i, y + j]);
+ }
+ }
+ }
+ }
+ //Anweisungen wie der Weg gefunden wird
+ private void Search()
+ {
+ Node node;
+ do
+ {
+ foreach (var item in _searching)
+ {
+ CalculateGCost(item.Coordinates.X, item.Coordinates.Y, item.Previous);
+ CalculateFCost(item.Coordinates.X, item.Coordinates.Y);
+ }
+
+ //Sucht die niedrigste F Cost
+ int lowestF = _searching.Min(c => c.F);
+ //Sucht in der offenen Liste nach den Nodes mit der niedrigsten F Cost
+ var nodes = _searching.FindAll(c => c.F == lowestF);
+ //Sucht unter den niedrigsten F Cost Nodes nach der niedrigsten H Cost
+ int lowestH = nodes.Min(c => c.H);
+ //Wählt die Node mit der niedrigsten F und H Cost aus
+ node = nodes.Find(c => c.H == lowestH);
+
+ //Sollte die Node zufälligerweise die End-Node sein, wird die Suche nach der End-Node abgebrochen
+ if (node.TypeOfNode == TypeOfNode.End)
+ break;
+
+ //Sucht für die Node mit der niedrigsten F und H Cost die Nachbarn und fügt sie der offenen Liste hinzu
+ PathFinding(node.Coordinates.X, node.Coordinates.Y);
+ //Entfernt die Node von der offenen Liste
+ _searching.Remove(node);
+ //und fügt sie der geschlossenen Liste hinzu
+ Searched.Add(node);
+ } while (_searching.Count != 0 && node.TypeOfNode != TypeOfNode.End);
+ }
+ public void ShowMap()
+ {
+ for (int i = 0; i < Width; i++)
+ {
+ for (int j = 0; j < Height; j++)
+ {
+ Console.SetCursorPosition(i, j);
+
+ switch (_map[i,j].TypeOfNode)
+ {
+ case TypeOfNode.Start:
+ Console.ForegroundColor = ConsoleColor.Blue;
+ break;
+ case TypeOfNode.End:
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ break;
+ default:
+ Console.ForegroundColor = ConsoleColor.Gray;
+ break;
+ }
+
+ //Schreibt ein X wenn es sich bei dem Feld um eine Wand / das Ende / den Start handelt
+ Console.WriteLine(_map[i, j].TypeOfNode == TypeOfNode.Wall |
+ _map[i, j].TypeOfNode == TypeOfNode.End |
+ _map[i, j].TypeOfNode == TypeOfNode.Start ? "X" : " ");
+ }
+ }
+ }
+
+ public void ShowPath(Node node)
+ {
+ while (true)
+ {
+ System.Threading.Thread.Sleep(100);
+ Console.SetCursorPosition(node.Coordinates.X, node.Coordinates.Y);
+ Console.BackgroundColor = ConsoleColor.White;
+ Console.WriteLine("*");
+ Console.BackgroundColor = ConsoleColor.Black;
+ switch (node.TypeOfNode)
+ {
+ case TypeOfNode.Start:
+ //Die Reihe ist fertig, es wird an das ende der Map gesetzt um weiter Infos
+ //auf der Konsole auszugeben ohne die Karte zu überschreiben
+ Console.SetCursorPosition(0, Height + 1);
+ break;
+ default:
+ //Zeigt die nächste Node in der Reihe
+ node = node.Previous;
+ continue;
+ }
+
+ break;
+ }
+ }
+ }
+
+ internal static class Program
+ {
+ private static void Main()
+ {
+ Console.ReadKey(true);
+
+ int lineCount = 0;
+ int longestLine = 0;
+ string line;
+
+ List walls = new List();
+
+ Coordinates start = new Coordinates();
+ Coordinates end = new Coordinates();
+
+ System.IO.StreamReader file =
+ new System.IO.StreamReader(@"..\..\Input.txt");
+ while ((line = file.ReadLine()) != null)
+ {
+ if (line.Length > longestLine)
+ {
+ longestLine = line.Length;
+ }
+
+ int counter2 = 0;
+ foreach (char x in line)
+ {
+ switch (x)
+ {
+ case 'X':
+ walls.Add(new[] { counter2, lineCount });
+ break;
+
+ case 'S':
+ start = new Coordinates(counter2, lineCount);
+ break;
+
+ case 'E':
+ end = new Coordinates(counter2, lineCount);
+ break;
+ }
+ counter2++;
+ }
+ lineCount++;
+ }
+
+ var map = new Map(longestLine, lineCount);
+
+ map.SetStart(start);
+ map.SetEnd(end);
+ map.SetWalls(walls);
+
+ file.Dispose();
+ var sw = new System.Diagnostics.Stopwatch();
+ sw.Start();
+ map.CalculateAllHCost();
+ map.StartPathFinding();
+ sw.Stop();
+
+ map.ShowMap();
+ map.ShowPath(map.GetEnd());
+
+ Console.WriteLine("The Path took {0} ms to calculate", sw.ElapsedMilliseconds);
+
+ foreach (var node in map.Searched)
+ {
+ //Alle untersuchten Nodes werden einmal aufgeführt
+ Console.WriteLine("{0,-6} : G = {1,-4}| H = {2,-4}| F = {3,-4}",
+ node.Coordinates.X + ", " + node.Coordinates.Y, node.G, node.H, node.F);
+ }
+
+ Console.ReadKey(true);
+ }
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..29118c7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# AStar Pathfinding
+
+A Project i did for fun awhile ago.
+Its still fun to run sometimes.
+Probably not the fastest Astar out there
\ No newline at end of file