public (int totalSteps, List <(T tile, int distance)> poi) FloodFillDistanceFinder(int xStart, int yStart, IEnumerable <T> pointsOfInterest) { var poi = pointsOfInterest.ToHashSet(); var poiFound = new List <(T, int)>(); var frontier = new List <(int x, int y)> { (xStart, yStart) }; var floodedGrid = new Grid <bool>(false, originAtBottom); floodedGrid[xStart, yStart] = true; int steps = 0; while (frontier.Any()) { var nextFrontier = new List <(int x, int y)>(); foreach ((int x, int y) in frontier) { var neighbours = GetNeighbours(x, y); var floodNeighbours = floodedGrid.GetNeighbours(x, y); foreach (var key in neighbours.Keys) { if (!floodNeighbours[key]) { var neighbourCoords = DirectionHelper.StepInDirection(key, x, y, 1); if (poi.Contains(neighbours[key])) { poiFound.Add((neighbours[key], steps + 1)); } if (passableTerrain.Contains(neighbours[key])) { nextFrontier.Add(neighbourCoords); } floodedGrid[neighbourCoords.x, neighbourCoords.y] = true; } } } frontier = nextFrontier; steps++; } return(steps - 1, poiFound); }
public Dictionary <Direction, T> GetNeighbours(int x, int y, bool includeDiagonal = false) { var directions = Enum.GetValues(typeof(Direction)); var neighbours = new Dictionary <Direction, T>(); foreach (Direction dir in directions) { if (includeDiagonal || ((int)dir % 2) == 0) { var actualDirection = originAtBottom ? dir : dir.Opposite(); var(modX, modY) = DirectionHelper.StepInDirection(dir, x, y, 1); if (modX >= 0 && modY >= 0 && modX < grid.GetLength(0) && modY < grid.GetLength(1)) { neighbours.Add(actualDirection, grid[modX, modY]); } else { neighbours.Add(actualDirection, defaultTile); //Alternative: not adding to dictionary, downside, different behaviour from Grid } } } return(neighbours); }