Exemple #1
0
        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);
        }
Exemple #2
0
        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" });
        }
Exemple #3
0
        public void CanEnumerateStackItems()
        {
            var stack = new SegmentedStack <string>();

            stack.Push("1");
            stack.Push("2");
            stack.Push("3");

            Assert.Equal(stack, new[] { "3", "2", "1" });
        }
Exemple #4
0
        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());
        }
Exemple #5
0
        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());
        }
Exemple #6
0
        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());
            }
        }
Exemple #7
0
        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);
                }
            }
        }