public void StackTracksCountForSegmentsCorrectly() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); stack.Push("3"); Assert.Equal(3, stack.Count); using (stack.EnterSegment()) { Assert.Equal(0, stack.Count); stack.Push("4"); stack.Push("5"); stack.Push("6"); Assert.Equal(3, stack.Count); stack.Pop(); stack.Pop(); stack.Pop(); Assert.Equal(0, stack.Count); } Assert.Equal(3, stack.Count); }
public void CanCreateStackSegment() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); stack.Push("3"); using (stack.EnterSegment()) { Assert.Equal(stack, Enumerable.Empty <string>()); stack.Push("4"); stack.Push("5"); stack.Push("6"); Assert.Equal(stack, new[] { "6", "5", "4" }); stack.Pop(); stack.Pop(); stack.Pop(); Assert.Equal(stack, Enumerable.Empty <string>()); } Assert.Equal(stack, new[] { "3", "2", "1" }); }
public void CanEnumerateStackItems() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); stack.Push("3"); Assert.Equal(stack, new[] { "3", "2", "1" }); }
public void CannotPopEmptyStack() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); Assert.Equal("2", stack.Pop()); Assert.Equal("1", stack.Pop()); Assert.Throws <InvalidOperationException>(() => stack.Pop()); }
public void CanPushAndPopWithoutSegment() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); stack.Push("3"); Assert.Equal("3", stack.Pop()); Assert.Equal("2", stack.Pop()); Assert.Equal("1", stack.Pop()); }
public void CannotPopEmptySegment() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); stack.Push("3"); using (stack.EnterSegment()) { Assert.Throws <InvalidOperationException>(() => stack.Pop()); } }
public void CannotExitSegmentWithUnpoppedItems() { var stack = new SegmentedStack <string>(); stack.Push("1"); stack.Push("2"); stack.Push("3"); Assert.Equal(3, stack.Count); var segment = stack.EnterSegment(); Assert.Equal(0, stack.Count); stack.Push("4"); stack.Push("5"); stack.Push("6"); Assert.Equal(3, stack.Count); stack.Pop(); Assert.Throws <InvalidOperationException>(() => segment.Dispose()); }
private void VisitAllPulls() { // Recursively visit all predecessors. This // algorithm would be implemented most // naturally as a depth-first recursive // search, but doing so easily exhausts // the call stack. // Create a stack of moves that need to be processed. IStack<Move> moves = new SegmentedStack<Move>(); // For all subsets of boxes on targets of the specified size. foreach (Coordinate2D[] targets in CoordinateUtils.GetCoordinateSets(level.TargetCoordinates, level.Boxes)) { // Check for cancel. if (cancelInfo.Cancel) { return; } // Move the boxes into position. level.MoveBoxes(targets); // Add moves from all possible starting sokoban squares. foreach (Coordinate2D coord in regionFinder.Coordinates) { pathFinder.Find(coord); FindPulls(moves); } // Record position of pulls with no predecessors. int index = moves.Count; // While the stack is not empty. while (!moves.IsEmpty) { // Check for cancel. if (cancelInfo.Cancel) { return; } // Pop the next move off the stack. Move move = moves.Pop(); int row = move.Row; int column = move.Column; Coordinate2D direction = move.Direction; // If the move was previously searched, then undo it. if (row < 0) { row = -row; pathFinder.MoveBox(Operation.Push, row, column, row - direction.Row, column - direction.Column); continue; } // Re-add the move as searched to undo it later. moves.Push(new Move(-row, column, move.Direction)); // Check for move with no predecessor. if (moves.Count <= index) { // Force a full search in preperation for // an incremental search. pathFinder.ForceFullCalculation(); } // Execute the move and put the virtual sokoban on its normalized square. pathFinder.MoveBoxAndIncrementalFind(Operation.Pull, row - direction.Row, column - direction.Column, row, column); Coordinate2D sokobanCoord = pathFinder.GetFirstAccessibleCoordinate(); // If previously visited continue; otherwise add it to the set. if (!visited.Add(sokobanCoord)) { continue; } // Find all possible pulls from the current position and add them to the stack. FindPulls(moves); } } }