public static HashSet <GridPoint3D> GetNextState3D(HashSet <GridPoint3D> initialState) { var result = new HashSet <GridPoint3D>(); // Collect all the points to consider: // All currently active points, plus all points adjacent to those var pointsToConsider = new HashSet <GridPoint3D>(); foreach (var point in initialState) { if (!pointsToConsider.Contains(point)) { pointsToConsider.Add(point); } var adjacentPoints = GridHelper3D.GetAdjacentPoints(point); foreach (var adjacentPoint in adjacentPoints) { if (!pointsToConsider.Contains(adjacentPoint)) { pointsToConsider.Add(adjacentPoint); } } } // Process each point, add it to the next state if it should be active foreach (var point in pointsToConsider) { var isCurrentlyActive = initialState.Contains(point); // Count # of adjacent active points int numberOfActiveAdjacentPoints = GridHelper3D.GetAdjacentPoints(point) .Where(a => initialState.Contains(a)) .Count(); var isNextCubeStateActive = GetIsNextCubeStateActive(isCurrentlyActive, numberOfActiveAdjacentPoints); if (isNextCubeStateActive) { result.Add(point); } } return(result); }
public IList <GridPoint3D> GetNeighbors(GridPoint3D point) { var result = new List <GridPoint3D>(); var directions = new List <MovementDirection>() { MovementDirection.Left, MovementDirection.Right, MovementDirection.Up, MovementDirection.Down }; foreach (var direction in directions) { var neighbor = point.Move(direction, 1); if (!IsRecursive) { result.Add(neighbor); } else // Recursive map { // Check if the neighbor is the middle point if (neighbor.XYPoint.Equals(CenterPointXY)) { // Get the outer cells adjacent to this one in the // inner layer // Handle y is inverted (up actually decreases y), // the inner layer side is actually the same as the // vertical movement direction var innerLayerSide = direction; if (MovementDirection.Left.Equals(direction) || MovementDirection.Right.Equals(direction)) { innerLayerSide = MovementDirectionHelper.GetOppositeDirection(direction); } int[] edgeValues; var coordinateOrder = string.Empty; switch (innerLayerSide) { case MovementDirection.Left: edgeValues = new int[4] { 0, point.Z + 1, 0, Height - 1 }; coordinateOrder = "XZY"; break; case MovementDirection.Right: edgeValues = new int[4] { Width - 1, point.Z + 1, 0, Height - 1 }; coordinateOrder = "XZY"; break; case MovementDirection.Up: edgeValues = new int[4] { 0, point.Z + 1, 0, Width - 1 }; coordinateOrder = "YZX"; break; case MovementDirection.Down: edgeValues = new int[4] { Height - 1, point.Z + 1, 0, Width - 1 }; coordinateOrder = "YZX"; break; default: throw new Exception($"Invalid side {direction}"); } var neighborsOnInnerLayer = GridHelper3D.GetPointsAlongEdge( edgeValues: edgeValues, coordinateOrder: coordinateOrder); result.AddRange(neighborsOnInnerLayer); } // Check if the neighbor is off the map else if (GetIsPointOffMap(neighbor)) { // Get the adjacent cell to the center in the outer layer var outerLayerCenterCell = new GridPoint3D(CenterPointXY, point.Z - 1); neighbor = outerLayerCenterCell.Move(direction, 1); result.Add(neighbor); } else { result.Add(neighbor); } } } return(result); }