private static bool CheckMapPassable(IEnumerable <OffsetCoords> currentCoords, OffsetCoords targetCoords) { var matrix = new Matrix <bool>(2002, 2002); foreach (var coords in currentCoords) { try { var x = coords.X; var y = coords.Y; matrix.Items[x, y] = true; } catch (IndexOutOfRangeException) { // Do nothing. The solution by using matrix is code smell. // There is the catch block just for debug. } } // Закрываем проверяемый узел matrix.Items[targetCoords.X, targetCoords.Y] = false; // Не выбираем првоеряемую координату, как стартовую, потому что // она уже закрыта. Заливка от неё не пройдёт. var availableStartPoints = currentCoords.Where(x => x != targetCoords).ToArray(); if (!availableStartPoints.Any()) { // Если нет доступных координат для старта, // значит стартовая координата была единственной. // Её нельзя закрывать препятсвием. return(false); } var startPoint = availableStartPoints.First(x => MapFactoryHelper.IsAvailableFor(matrix, x)); var floodPoints = HexBinaryFiller.FloodFill(matrix, startPoint); foreach (var point in floodPoints) { matrix.Items[point.X, point.Y] = false; } foreach (var node in currentCoords) { var x = node.X; var y = node.Y; if (matrix.Items[x, y]) { return(false); } } return(true); }
public void FloodFill7_OneSize7Area_ReturnsOneCentralPoint() { // ARRANGE var matrix = new Matrix <bool>(10, 10); PlaceArea(4, 4, matrix); // ACT var regions = HexBinaryFiller.FloodFill7(matrix, new OffsetCoords(4, 4)); // ASSERT regions.Should().BeEquivalentTo(new[] { new OffsetCoords(4, 4) }); }
private static IEnumerable <OffsetCoords> FloodFillRegions(Matrix <bool> matrix, OffsetCoords point) { var regionPoints = HexBinaryFiller.FloodFill( matrix, point); // В регионе должна быть хоть одна точка - стартовая. // Потому что заливка начинается с выбора незалитых точек. // Если этот метод не будет возращать точки, то будет бесконечный цикл. // Это критично, поэтому выбрасываем исключение. if (!regionPoints.Any()) { throw new InvalidOperationException("Должна быть залита хотя бы одна точка."); } return(regionPoints); }
public Task Validate(ISector sector, IServiceProvider scopeContainer) { // Проверяем проходимость карты. // Для этого убеждаемся, что из любого узла есть путь до любого другого. // При поиске пути: // - Считаем непроходимыме все статические объекты. Это декоратиные препятствия и сундуки. // - Игнорируем все перемещаемые. Например, монстров. return(Task.Run(() => { var staticObjectManager = sector.StaticObjectManager; var containerNodes = staticObjectManager.Items.Select(x => x.Node); var allNonObstacleNodes = sector.Map.Nodes.OfType <HexNode>().ToArray(); var allNonContainerNodes = allNonObstacleNodes.Where(x => !containerNodes.Contains(x)); var allNodes = allNonContainerNodes.ToArray(); var matrix = new Matrix <bool>(1000, 1000); foreach (var node in allNodes) { var x = node.OffsetCoords.X; var y = node.OffsetCoords.Y; matrix.Items[x, y] = true; } var startNode = allNodes.First(); var startPoint = startNode.OffsetCoords; var floodPoints = HexBinaryFiller.FloodFill(matrix, startPoint); foreach (var point in floodPoints) { matrix.Items[point.X, point.Y] = false; } foreach (var node in allNodes) { var x = node.OffsetCoords.X; var y = node.OffsetCoords.Y; if (matrix.Items[x, y]) { throw new SectorValidationException($"Точка ({x}, {y}) недоступна для прохода."); } } })); }
private static bool CheckMap(ISector sector, HexNode containerNode) { var map = sector.Map; var currentStaticObjectsNodes = sector.StaticObjectManager.Items.Select(x => x.Node).OfType <HexNode>(); var allNonObstacleNodes = map.Nodes.OfType <HexNode>().ToArray(); var allNonContainerNodes = allNonObstacleNodes.Where(x => !currentStaticObjectsNodes.Contains(x)); var allNodes = allNonContainerNodes.ToArray(); var matrix = new Matrix <bool>(1000, 1000); foreach (var node in allNodes) { var x = node.OffsetCoords.X; var y = node.OffsetCoords.Y; matrix.Items[x, y] = true; } // Закрываем проверяемый узел matrix.Items[containerNode.OffsetCoords.X, containerNode.OffsetCoords.Y] = false; var startNode = allNodes.First(); var startPoint = startNode.OffsetCoords; var floodPoints = HexBinaryFiller.FloodFill(matrix, startPoint); foreach (var point in floodPoints) { matrix.Items[point.X, point.Y] = false; } foreach (var node in allNodes) { var x = node.OffsetCoords.X; var y = node.OffsetCoords.Y; if (matrix.Items[x, y]) { return(false); } } return(true); }
private bool CheckMap(ISectorMap map, HexNode containerNode) { var containerNodes = _propContainerManager.Items.Select(x => x.Node); var allNonObstacleNodes = map.Nodes.OfType <HexNode>().Where(x => !x.IsObstacle).ToArray(); var allNonContainerNodes = allNonObstacleNodes.Where(x => !containerNodes.Contains(x)); var allNodes = allNonContainerNodes.ToArray(); var matrix = new Matrix <bool>(1000, 1000); foreach (var node in allNodes) { var x = node.OffsetX; var y = node.OffsetY; matrix.Items[x, y] = true; } // Закрываем проверяемый узел matrix.Items[containerNode.OffsetX, containerNode.OffsetY] = false; var startNode = allNodes.First(); var startPoint = new OffsetCoords(startNode.OffsetX, startNode.OffsetY); var floodPoints = HexBinaryFiller.FloodFill(matrix, startPoint); foreach (var point in floodPoints) { matrix.Items[point.X, point.Y] = false; } foreach (var node in allNodes) { var x = node.OffsetX; var y = node.OffsetY; if (matrix.Items[x, y]) { return(false); } } return(true); }