Project · Algorithms

Path finder

Find the shortest path in a grid using BFS.

All C# source files below are loaded together in the playground. Files written by a run live in its virtual directory.

Program.cs

var grid = new[]
{
    "S..#....",
    ".#.#.##.",
    ".#...#..",
    ".####.#.",
    "......#E",
};

var rows = grid.Length;
var cols = grid[0].Length;
var start = Find('S');
var end = Find('E');

// Breadth-first search visits cells in order of distance from S.
var cameFrom = new Dictionary<(int R, int C), (int R, int C)> { [start] = start };
var queue = new Queue<(int R, int C)>();
queue.Enqueue(start);
var moves = new[] { (0, 1), (1, 0), (0, -1), (-1, 0) };

while (queue.Count > 0)
{
    var cell = queue.Dequeue();
    if (cell == end) break;
    foreach (var (dr, dc) in moves)
    {
        var next = (R: cell.R + dr, C: cell.C + dc);
        var inside = next.R >= 0 && next.R < rows && next.C >= 0 && next.C < cols;
        if (!inside || grid[next.R][next.C] == '#' || cameFrom.ContainsKey(next)) continue;
        cameFrom[next] = cell;
        queue.Enqueue(next);
    }
}

if (!cameFrom.ContainsKey(end))
{
    Console.WriteLine("No path");
    return;
}

var path = new HashSet<(int R, int C)>();
for (var at = end; at != start; at = cameFrom[at]) path.Add(at);

for (var r = 0; r < rows; r++)
{
    var line = grid[r].ToCharArray();
    for (var c = 0; c < cols; c++)
    {
        if (line[c] == '.' && path.Contains((r, c))) line[c] = '*';
    }
    Console.WriteLine(new string(line));
}
Console.WriteLine($"Shortest path: {path.Count} steps");

(int R, int C) Find(char mark)
{
    for (var r = 0; r < rows; r++)
    {
        var c = grid[r].IndexOf(mark);
        if (c >= 0) return (r, c);
    }
    throw new InvalidOperationException($"No {mark} on the grid");
}

PathFinder.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <AssemblyName>PathFinder</AssemblyName>
  </PropertyGroup>
</Project>