private static Neighbors GetNeighbors(RectangularMaze maze, Cell cell) { var position = maze.GetPositionOfCell(cell); var neighborPositions = cell.CellWalls .Select(x => new { wall = x, position = maze.GetPositionOfCell(x.GetOtherCell(cell)) }) .ToArray(); var north = neighborPositions.Where(x => x.position.row == position.row - 1).Select(x => x.wall).FirstOrDefault(); var east = neighborPositions.Where(x => x.position.column == position.column + 1).Select(x => x.wall).FirstOrDefault(); return(new Neighbors(north, east)); }
private static PassableDirections GetPassableDirections(RectangularMaze maze, Cell cell) { var position = maze.GetPositionOfCell(cell); var neighborPositions = cell.CellWalls .Where(x => x.IsPassable) .Select(x => maze.GetPositionOfCell(x.GetOtherCell(cell))) .ToArray(); var northPassable = neighborPositions.Any(x => x.row == position.row - 1); var southPassable = neighborPositions.Any(x => x.row == position.row + 1); var eastPassable = neighborPositions.Any(x => x.column == position.column + 1); var westPassable = neighborPositions.Any(x => x.column == position.column - 1); return(new PassableDirections(northPassable, southPassable, eastPassable, westPassable)); }
public static SKImage RenderWithSkia(this RectangularMaze maze, RenderOptions renderOptions, DistanceInfo distanceInfo, ShortestPathInfo shortestPathInfo) { if (maze == null) { throw new ArgumentNullException(nameof(maze)); } renderOptions = renderOptions ?? new RenderOptions(); var imageWidth = (CellSize * maze.ColumnCount) + (Margin * 2); var imageHeight = (CellSize * maze.RowCount) + (Margin * 2); var imageInfo = new SKImageInfo(imageWidth, imageHeight, SKColorType.Rgba8888, SKAlphaType.Premul); using (var surface = SKSurface.Create(imageInfo)) { surface.Canvas.Clear(SKColors.Black); var whitePaint = new SKPaint { Color = SKColors.White, StrokeWidth = CellLineWidth }; var startPaint = new SKPaint { Color = SKColors.Green, StrokeWidth = CellLineWidth }; var finishPaint = new SKPaint { Color = SKColors.Red, StrokeWidth = CellLineWidth }; var pathPaint = new SKPaint { Color = SKColors.Yellow, StrokeWidth = CellLineWidth }; foreach (var cell in maze.AllCells) { var(row, column) = maze.GetPositionOfCell(cell); var leftX = (column * CellSize) + Margin; var rightX = leftX + CellSize; var topY = (row * CellSize) + Margin; var bottomY = topY + CellSize; var isNorthFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && row == 0 && column > 1; var isSouthFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && row == maze.RowCount - 1 && column > 1; var isEastFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && column == maze.ColumnCount - 1; var isWestFacingExit = (maze.FinishingCell == cell || maze.StartingCell == cell) && column == 0; var passableDirections = GetPassableDirections(maze, cell); if (!passableDirections.North && !isNorthFacingExit) { surface.Canvas.DrawLine(leftX, topY, rightX, topY, whitePaint); } if (!passableDirections.South && !isSouthFacingExit) { surface.Canvas.DrawLine(leftX, bottomY, rightX, bottomY, whitePaint); } if (!passableDirections.East && !isEastFacingExit) { surface.Canvas.DrawLine(rightX, topY, rightX, bottomY, whitePaint); } if (!passableDirections.West && !isWestFacingExit) { surface.Canvas.DrawLine(leftX, topY, leftX, bottomY, whitePaint); } if (renderOptions.ShowGradientOfDistanceFromStart) { const int shadingMargin = 2; var finishingCellDistance = distanceInfo.DistanceFromStartMap[distanceInfo.FarthestCell]; var currentCellDistance = distanceInfo.DistanceFromStartMap[cell]; var intensity = (byte)(255 * (currentCellDistance / (decimal)finishingCellDistance)); var color = new SKColor(0, 0, intensity); var paint = new SKPaint { Color = color }; var shadeWidth = rightX - leftX - (shadingMargin * 2); var shadeHeight = bottomY - topY - (shadingMargin * 2); surface.Canvas.DrawRect(leftX + shadingMargin, topY + shadingMargin, shadeWidth, shadeHeight, paint); } if (renderOptions.HighlightShortestPath && shortestPathInfo.IsCellInPath(cell)) { var paint = cell == maze.StartingCell ? startPaint : cell == maze.FinishingCell ? finishPaint : pathPaint; var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), leftX + LabelMarginX, topY + LabelMarginY, paint); } else if (renderOptions.ShowAllDistances && distanceInfo.DistanceFromStartMap.ContainsKey(cell)) { var distance = distanceInfo.DistanceFromStartMap[cell]; surface.Canvas.DrawText(distance.ToString(), leftX + LabelMarginX, topY + LabelMarginY, whitePaint); } else if (cell == maze.StartingCell) { surface.Canvas.DrawText("S", leftX + LabelMarginX, topY + LabelMarginY, startPaint); } else if (cell == maze.FinishingCell) { surface.Canvas.DrawText("E", leftX + LabelMarginX, topY + LabelMarginY, finishPaint); } } return(surface.Snapshot()); } }