Пример #1
0
 public abstract bool ApplyReverseMoveForLoop(
     IGameBlockDestination destinationBlock,
     MovementDirection directionInReverse,
     int numberOfBlocksToMove,
     out BlockMovement move,
     IGameBlock previousBlock,
     IGameBlockDestination previousDestination,
     Queue <IGameBlock> blockHistory);
Пример #2
0
        public BlockMovement(IGameBlockParent sourceBlock, MovementDirection direction)
        {
            this.sourceBlock        = sourceBlock;
            this.destinationBlock   = null;
            this.direction          = direction;
            this.intermediateBlocks = new List <IGameBlockDestination>();

            this.originalAvailableMoves = sourceBlock == null ? 0 : sourceBlock.AvailableMoves;
        }
Пример #3
0
        public BlockMovement(IGameBlockParent sourceBlock, MovementDirection direction)
        {
            this.sourceBlock = sourceBlock;
            this.destinationBlock = null;
            this.direction = direction;
            this.intermediateBlocks = new List<IGameBlockDestination>();

            this.originalAvailableMoves = sourceBlock == null ? 0 : sourceBlock.AvailableMoves;
        }
Пример #4
0
        public void InsertDestinationBlock(IGameBlockDestination destination)
        {
            // Move the destinationBlock into the intermediateBlocks
            if (this.destinationBlock != null)
            {
                this.intermediateBlocks.Add(this.destinationBlock);
            }

            this.destinationBlock = destination;
        }
Пример #5
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestination,
            Queue <IGameBlock> blockHistory)
        {
            move = null;

            return(false);
        }
Пример #6
0
        private static void Shuffle(List <IGameBlockDestination> numbers, int timesToShuffle)
        {
            int maxIndex = numbers.Count - 1;

            for (int i = 0; i < timesToShuffle; i++)
            {
                int index1 = RandomGenerator.Next(0, maxIndex);
                int index2 = RandomGenerator.Next(0, maxIndex);

                IGameBlockDestination temp = numbers[index1];
                numbers[index1] = numbers[index2];
                numbers[index2] = temp;
            }
        }
Пример #7
0
        public bool HasOrphan()
        {
            bool hasOrphan = false;

            foreach (IGameBlock gameBlock in this.gameBlocks)
            {
                IGameBlockDestination gameBlockNormal = gameBlock as IGameBlockDestination;

                if (gameBlockNormal != null && gameBlockNormal.IsOrphaned())
                {
                    hasOrphan = true;
                    break;
                }
            }

            return(hasOrphan);
        }
Пример #8
0
        public override bool ApplyReverseMove(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue <IGameBlock> blockHistory)
        {
            // Already used
            if (this.AvailableMoves > 0)
            {
                move = null;
                return(false);
            }

            // This block is a valid "starting" point
            move = new BlockMovement(this, directionInReverse);
            return(true);
        }
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue<IGameBlock> blockHistory)
        {
            move = null;

            // This block can't be the destination
            if (destinationBlock == null)
            {
                return false;
            }

            // This block forces the next move to be a certain direction, so depending on what "forceDirection" is,
            // the next move is always going to be the one in that direction.  As a reverse move, previousBlock will
            // need to be the correct block based on this requirement.
            IGameBlock forcedPreviousBlock;
            switch (this.forceDirection)
            {
                default:
                case MovementDirection.Up:
                    forcedPreviousBlock = this.Top;
                    break;

                case MovementDirection.Down:
                    forcedPreviousBlock = this.Bottom;
                    break;

                case MovementDirection.Left:
                    forcedPreviousBlock = this.Left;
                    break;

                case MovementDirection.Right:
                    forcedPreviousBlock = this.Right;
                    break;
            }

            if (!ReferenceEquals(forcedPreviousBlock, previousBlock))
            {
                return false;
            }

            bool isPossibleLoopDirection;

            // This is trying to make a loop, so it has to be the opposite direction
            switch (this.forceDirection)
            {
                case MovementDirection.Up:
                    isPossibleLoopDirection = directionInReverse == MovementDirection.Down;
                    break;

                case MovementDirection.Down:
                    isPossibleLoopDirection = directionInReverse == MovementDirection.Up;
                    break;

                case MovementDirection.Left:
                    isPossibleLoopDirection = directionInReverse == MovementDirection.Right;
                    break;

                case MovementDirection.Right:
                    isPossibleLoopDirection = directionInReverse == MovementDirection.Left;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }

            if (!isPossibleLoopDirection)
            {
                return false;
            }

            blockHistory.Enqueue(this);

            bool moveApplied;

            switch (directionInReverse)
            {
                default:
                case MovementDirection.Up:
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMove(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Down:
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMove(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Left:
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMove(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Right:
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMove(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;
            }

            return moveApplied;
        }
Пример #10
0
        public override bool ApplyReverseMove(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue<IGameBlock> blockHistory)
        {
            move = null;

            // This block can't be the destination
            if (destinationBlock == null)
            {
                return false;
            }

            // This block forces the next move to be a certain direction, so depending on what "forceDirection" is,
            // the next move is always going to be the one in that direction.  As a reverse move, previousBlock will
            // need to be the correct block based on this requirement.
            IGameBlock forcedPreviousBlock;
            switch (this.forceDirection)
            {
                default:
                case MovementDirection.Up:
                    forcedPreviousBlock = this.Top;
                    break;

                case MovementDirection.Down:
                    forcedPreviousBlock = this.Bottom;
                    break;

                case MovementDirection.Left:
                    forcedPreviousBlock = this.Left;
                    break;

                case MovementDirection.Right:
                    forcedPreviousBlock = this.Right;
                    break;
            }

            if (!ReferenceEquals(forcedPreviousBlock, previousBlock))
            {
                return false;
            }

            blockHistory.Enqueue(this);

            // It can be any direction except for the forced direction, so try any one of the three others
            // until one of them works (at random)
            List<MovementDirection> directions = new List<MovementDirection>
                                                     {
                                                         MovementDirection.Down,
                                                         MovementDirection.Up,
                                                         MovementDirection.Left,
                                                         MovementDirection.Right
                                                     };

            switch (this.forceDirection)
            {
                case MovementDirection.Up:
                    directions.Remove(MovementDirection.Down);
                    break;
                case MovementDirection.Down:
                    directions.Remove(MovementDirection.Up);
                    break;
                case MovementDirection.Left:
                    directions.Remove(MovementDirection.Right);
                    break;
                case MovementDirection.Right:
                    directions.Remove(MovementDirection.Left);
                    break;
            }

            // Shuffle
            Random random = new Random();
            for (int i = 0; i < 3; i++)
            {
                MovementDirection remove = directions[random.Next(0, 2)];
                directions.Remove(remove);
                directions.Add(remove);
            }

            bool moveApplied = false;

            foreach (MovementDirection movementDirectionInReverse in directions)
            {
                switch (movementDirectionInReverse)
                {
                    default:
                    case MovementDirection.Up:
                        if (this.Bottom == null)
                        {
                            moveApplied = false;
                        }
                        else
                        {
                            moveApplied = this.Bottom.ApplyReverseMove(
                                destinationBlock,
                                movementDirectionInReverse,
                                numberOfBlocksToMove,
                                out move,
                                this,
                                previousDestinationBlock,
                                blockHistory);
                        }
                        break;

                    case MovementDirection.Down:
                        if (this.Top == null)
                        {
                            moveApplied = false;
                        }
                        else
                        {
                            moveApplied = this.Top.ApplyReverseMove(
                                destinationBlock,
                                movementDirectionInReverse,
                                numberOfBlocksToMove,
                                out move,
                                this,
                                previousDestinationBlock,
                                blockHistory);
                        }
                        break;

                    case MovementDirection.Left:
                        if (this.Right == null)
                        {
                            moveApplied = false;
                        }
                        else
                        {
                            moveApplied = this.Right.ApplyReverseMove(
                                destinationBlock,
                                movementDirectionInReverse,
                                numberOfBlocksToMove,
                                out move,
                                this,
                                previousDestinationBlock,
                                blockHistory);
                        }
                        break;

                    case MovementDirection.Right:
                        if (this.Left == null)
                        {
                            moveApplied = false;
                        }
                        else
                        {
                            moveApplied = this.Left.ApplyReverseMove(
                                destinationBlock,
                                movementDirectionInReverse,
                                numberOfBlocksToMove,
                                out move,
                                this,
                                previousDestinationBlock,
                                blockHistory);
                        }
                        break;
                }

                // One of the moves worked, so break out
                if (moveApplied)
                {
                    break;
                }
            }

            return moveApplied;
        }
Пример #11
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue <IGameBlock> blockHistory)
        {
            move = null;

            // This block can't be the destination
            if (destinationBlock == null)
            {
                return(false);
            }

            // This block forces the next move to be a certain direction, so depending on what "forceDirection" is,
            // the next move is always going to be the one in that direction.  As a reverse move, previousBlock will
            // need to be the correct block based on this requirement.
            IGameBlock forcedPreviousBlock;

            switch (this.forceDirection)
            {
            default:
            case MovementDirection.Up:
                forcedPreviousBlock = this.Top;
                break;

            case MovementDirection.Down:
                forcedPreviousBlock = this.Bottom;
                break;

            case MovementDirection.Left:
                forcedPreviousBlock = this.Left;
                break;

            case MovementDirection.Right:
                forcedPreviousBlock = this.Right;
                break;
            }

            if (!ReferenceEquals(forcedPreviousBlock, previousBlock))
            {
                return(false);
            }

            bool isPossibleLoopDirection;

            // This is trying to make a loop, so it has to be the opposite direction
            switch (this.forceDirection)
            {
            case MovementDirection.Up:
                isPossibleLoopDirection = directionInReverse == MovementDirection.Down;
                break;

            case MovementDirection.Down:
                isPossibleLoopDirection = directionInReverse == MovementDirection.Up;
                break;

            case MovementDirection.Left:
                isPossibleLoopDirection = directionInReverse == MovementDirection.Right;
                break;

            case MovementDirection.Right:
                isPossibleLoopDirection = directionInReverse == MovementDirection.Left;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (!isPossibleLoopDirection)
            {
                return(false);
            }

            blockHistory.Enqueue(this);

            bool moveApplied;

            switch (directionInReverse)
            {
            default:
            case MovementDirection.Up:
                if (this.Bottom == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Bottom.ApplyReverseMove(
                        destinationBlock,
                        directionInReverse,
                        numberOfBlocksToMove,
                        out move,
                        this,
                        previousDestinationBlock,
                        blockHistory);
                }
                break;

            case MovementDirection.Down:
                if (this.Top == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Top.ApplyReverseMove(
                        destinationBlock,
                        directionInReverse,
                        numberOfBlocksToMove,
                        out move,
                        this,
                        previousDestinationBlock,
                        blockHistory);
                }
                break;

            case MovementDirection.Left:
                if (this.Right == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Right.ApplyReverseMove(
                        destinationBlock,
                        directionInReverse,
                        numberOfBlocksToMove,
                        out move,
                        this,
                        previousDestinationBlock,
                        blockHistory);
                }
                break;

            case MovementDirection.Right:
                if (this.Left == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Left.ApplyReverseMove(
                        destinationBlock,
                        directionInReverse,
                        numberOfBlocksToMove,
                        out move,
                        this,
                        previousDestinationBlock,
                        blockHistory);
                }
                break;
            }

            return(moveApplied);
        }
Пример #12
0
        public override bool ApplyReverseMove(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue <IGameBlock> blockHistory)
        {
            move = null;

            // This block can't be the destination
            if (destinationBlock == null)
            {
                return(false);
            }

            // This block forces the next move to be a certain direction, so depending on what "forceDirection" is,
            // the next move is always going to be the one in that direction.  As a reverse move, previousBlock will
            // need to be the correct block based on this requirement.
            IGameBlock forcedPreviousBlock;

            switch (this.forceDirection)
            {
            default:
            case MovementDirection.Up:
                forcedPreviousBlock = this.Top;
                break;

            case MovementDirection.Down:
                forcedPreviousBlock = this.Bottom;
                break;

            case MovementDirection.Left:
                forcedPreviousBlock = this.Left;
                break;

            case MovementDirection.Right:
                forcedPreviousBlock = this.Right;
                break;
            }

            if (!ReferenceEquals(forcedPreviousBlock, previousBlock))
            {
                return(false);
            }

            blockHistory.Enqueue(this);

            // It can be any direction except for the forced direction, so try any one of the three others
            // until one of them works (at random)
            List <MovementDirection> directions = new List <MovementDirection>
            {
                MovementDirection.Down,
                MovementDirection.Up,
                MovementDirection.Left,
                MovementDirection.Right
            };

            switch (this.forceDirection)
            {
            case MovementDirection.Up:
                directions.Remove(MovementDirection.Down);
                break;

            case MovementDirection.Down:
                directions.Remove(MovementDirection.Up);
                break;

            case MovementDirection.Left:
                directions.Remove(MovementDirection.Right);
                break;

            case MovementDirection.Right:
                directions.Remove(MovementDirection.Left);
                break;
            }

            // Shuffle
            Random random = new Random();

            for (int i = 0; i < 3; i++)
            {
                MovementDirection remove = directions[random.Next(0, 2)];
                directions.Remove(remove);
                directions.Add(remove);
            }

            bool moveApplied = false;

            foreach (MovementDirection movementDirectionInReverse in directions)
            {
                switch (movementDirectionInReverse)
                {
                default:
                case MovementDirection.Up:
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMove(
                            destinationBlock,
                            movementDirectionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Down:
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMove(
                            destinationBlock,
                            movementDirectionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Left:
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMove(
                            destinationBlock,
                            movementDirectionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Right:
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMove(
                            destinationBlock,
                            movementDirectionInReverse,
                            numberOfBlocksToMove,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;
                }

                // One of the moves worked, so break out
                if (moveApplied)
                {
                    break;
                }
            }

            return(moveApplied);
        }
Пример #13
0
        /// <summary>
        /// Reverses the solve.
        /// </summary>
        /// <param name="gameBoard">The game board.</param>
        /// <param name="maxCountAtPlayer">The max count at player.</param>
        /// <param name="maxNumberOfSolutions">The max number of solutions.</param>
        /// <param name="variability">The variability.</param>
        /// <param name="milliSecondsTimeout">The milli seconds timeout.</param>
        /// <param name="aborted">if set to <c>true</c> [aborted].</param>
        /// <returns></returns>
        public static List <GameBoard> ReverseSolve(
            GameBoard gameBoard, int maxCountAtPlayer, int maxNumberOfSolutions, int variability, int milliSecondsTimeout, out bool aborted)
        {
            RequestAbort        = false;
            AlreadyTestedBoards = new HashSet <string>();
            Dictionary <string, GameBoard> solutionGameBoards = new Dictionary <string, GameBoard>();
            List <Thread> threads = new List <Thread>();
            List <IGameBlockDestination> destinations = new List <IGameBlockDestination>();

            foreach (IGameBlock gameBlock in gameBoard.GameBlocks)
            {
                IGameBlockDestination nextDestination = gameBlock as IGameBlockDestination;

                if (nextDestination != null)
                {
                    destinations.Add(gameBlock as IGameBlockDestination);
                }
            }

            Shuffle(destinations, destinations.Count);

            foreach (IGameBlockDestination gameBlock in destinations)
            {
                GameBoard             gameBoardClone = (GameBoard)gameBoard.Clone();
                IGameBlockDestination gameBlockClone =
                    gameBoardClone.GameBlocks[gameBlock.IndexRow, gameBlock.IndexColumn] as IGameBlockDestination;

                // Parallel process the solutions
                ThreadStart threadStart = () =>
                {
                    int stepsBack = 0;

                    ReverseSolveMovements(
                        gameBoardClone,
                        gameBlockClone,
                        null,
                        maxCountAtPlayer,
                        maxNumberOfSolutions,
                        variability,
                        ref stepsBack,
                        null,
                        solutionGameBoards);
                };

                Thread threadFunction = new Thread(threadStart);
                threads.Add(threadFunction);
                threadFunction.Start();
            }

            // Wait for the threads to finish
            foreach (Thread thread in threads)
            {
                thread.Join(milliSecondsTimeout);

                // Took too long so abort it
                if (thread.IsAlive)
                {
                    thread.Abort();
                }
            }

            NotifySolveSolutionStartedEvent();

            // Clear it to take back memory
            AlreadyTestedBoards = new HashSet <string>();

            GC.Collect();

            if (AnalyzeImmediately)
            {
                foreach (KeyValuePair <string, GameBoard> solutionGameBoard in solutionGameBoards)
                {
                    int fails;
                    int successes;

                    GameBoardSolver.Solve(solutionGameBoard.Value, milliSecondsTimeout * 4, out fails, out successes);
                    solutionGameBoard.Value.Failures  = fails;
                    solutionGameBoard.Value.Successes = successes;

                    NotifyAnalyzedSolutionEvent();
                }
            }

            NotifySolveSolutionEndedEvent();

            aborted      = RequestAbort;
            RequestAbort = false;

            return(solutionGameBoards.Values.ToList());
        }
Пример #14
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue<IGameBlock> blockHistory)
        {
            move = null;

            // This can't be the final destination block
            if (destinationBlock == null)
            {
                return false;
            }

            // It needs at least 2 previous blocks
            if (previousDestinationBlock == null)
            {
                return false;
            }

            if (destinationBlock == previousDestinationBlock)
            {
                return false;
            }

            bool moveApplied;
            switch (directionInReverse)
            {
                default:
                case MovementDirection.Down:
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Up:
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Right:
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Left:
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;
            }

            if (moveApplied)
            {
                // It requires 1 less move if this block is used
                move.SourceBlock.AvailableMoves--;
            }

            return moveApplied;
        }
Пример #15
0
        private static void ReverseSolveMovements(
            GameBoard gameBoard,
            IGameBlockDestination gameBlock,
            IGameBlockDestination destinationBlock,
            int maxCountAtPlayer,
            int maxNumberOfSolutions,
            int variability,
            ref int stepsBack,
            BlockMovement nextMove,
            Dictionary <string, GameBoard> solutionGameBoards)
        {
            List <MovementDirection> movementDirections = GetRandomDirections();

            if (!gameBlock.IsFullyAvailable && !RequestAbort)
            {
                int    oldNumSolutions = solutionGameBoards.Count;
                string key             = gameBoard.GetBoardStringFull() + "_" + gameBlock.IndexRow + "_" + gameBlock.IndexColumn;

                lock (AlreadyTestedBoards)
                {
                    // Already tested this, so don't need to try it again
                    if (AlreadyTestedBoards.Contains(key))
                    {
                        return;
                    }

                    AlreadyTestedBoards.Add(key);
                }

                foreach (MovementDirection direction in movementDirections)
                {
                    ReverseSolveDirection(
                        gameBoard,
                        gameBlock,
                        destinationBlock,
                        direction,
                        maxCountAtPlayer,
                        maxNumberOfSolutions,
                        variability,
                        ref stepsBack,
                        nextMove,
                        solutionGameBoards);

                    // New solutions found so step back up the stack to get more variability in the solutions
                    if (oldNumSolutions != solutionGameBoards.Count)
                    {
                        if (variability > stepsBack)
                        {
                            stepsBack++;
                            break;
                        }
                        else
                        {
                            stepsBack = 0;
                        }
                    }

                    if (RequestAbort)
                    {
                        break;
                    }
                }
            }
        }
Пример #16
0
        private static void ReverseSolveDirection(
            GameBoard gameBoard,
            IGameBlockDestination gameBlock,
            IGameBlockDestination destinationBlock,
            MovementDirection direction,
            int maxCountAtPlayer,
            int maxNumberOfSolutions,
            int variability,
            ref int stepsBack,
            BlockMovement nextMove,
            Dictionary <string, GameBoard> solutionGameBoards)
        {
            // Test the board to see if a reverse solve is even possible.  If it's not, return early so it doesn't
            // waste time trying to solve something that can't be solved.
            if (CanTestReverseSolve && !gameBoard.TestCanReverseSolve())
            {
                return;
            }

            // So it doesn't always choose the max
            List <int> counts = Enumerable.Range(1, maxCountAtPlayer).ToList();

            for (int i = 0; i < counts.Count; i++)
            {
                int next  = RandomGenerator.Next(0, counts.Count - 1);
                int index = counts[next];
                counts.Remove(index);
                counts.Add(index);
            }

            for (int i = 0; i < counts.Count && solutionGameBoards.Count < maxNumberOfSolutions && !RequestAbort; i++)
            {
                BlockMovement temp;

                if (gameBlock.ApplyReverseMove(destinationBlock, direction, counts[i], out temp, null, null, new Queue <IGameBlock>()))
                {
                    bool allMovesUsed           = true;
                    int  originalAvailableMoves = temp.SourceBlock.AvailableMoves;

                    List <List <IGameBlockDestination> > removedCombinations;

                    if (nextMove != null)
                    {
                        temp.NextMove         = nextMove;
                        nextMove.PreviousMove = temp;
                    }

                    // Got more moves that we wanted, so take out a few randomly
                    int max = counts[i];

                    if (temp.SourceBlock.PreferredMaxMoves != 0 && temp.SourceBlock.AvailableMoves > temp.SourceBlock.PreferredMaxMoves)
                    {
                        max = Math.Min(max, temp.SourceBlock.PreferredMaxMoves);
                    }

                    // More moves than can be used
                    if (temp.SourceBlock.AvailableMoves > max)
                    {
                        int numberOfMovedNeedRemoving = temp.SourceBlock.AvailableMoves - max;

                        int numberAvailableForRemoving = temp.IntermediateBlocks.Count(ib => ib.CanBeRemovedIntermediate());

                        // Not possible because it needs to remove more items than it could
                        if (numberAvailableForRemoving < numberOfMovedNeedRemoving)
                        {
                            BlockMovement move = new BlockMovement(temp.SourceBlock, temp.Direction);
                            temp.SourceBlock.ApplyMove(null, temp.Direction, move);

                            continue;
                        }

                        allMovesUsed = false;

                        List <IGameBlockDestination> removeableIntermediates =
                            temp.IntermediateBlocks.Where(ib => ib.CanBeRemovedIntermediate()).ToList();

                        removedCombinations = new List <List <IGameBlockDestination> >();
                        IEnumerable <IEnumerable <IGameBlockDestination> > combos =
                            removeableIntermediates.Combinations(numberOfMovedNeedRemoving).ToList();

                        int count = 0;
                        foreach (IEnumerable <IGameBlockDestination> gameBlockDestinations in combos)
                        {
                            removedCombinations.Add(gameBlockDestinations.ToList());

                            if (MaxCombinations > 0 && ++count >= MaxCombinations)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        removedCombinations = new List <List <IGameBlockDestination> > {
                            new List <IGameBlockDestination>()
                        };
                    }

                    List <IGameBlockDestination> originalIntermediateBlocks = new List <IGameBlockDestination>();

                    foreach (IGameBlockDestination gameBlockDestination in temp.IntermediateBlocks)
                    {
                        originalIntermediateBlocks.Add(gameBlockDestination.Clone() as IGameBlockDestination);
                    }

                    foreach (List <IGameBlockDestination> removedCombination in removedCombinations)
                    {
                        List <IGameBlockDestination>         unusedBlocks          = new List <IGameBlockDestination>();
                        List <List <IGameBlockDestination> > intermediateBlockSets = new List <List <IGameBlockDestination> >();

                        foreach (IGameBlockDestination gameBlockDestination in removedCombination)
                        {
                            temp.IntermediateBlocks.Remove(gameBlockDestination);

                            temp.SourceBlock.AvailableMoves--;
                            gameBlockDestination.SetAvailability(false);
                            unusedBlocks.Add(gameBlockDestination);
                        }

                        foreach (IGameBlockDestination unusedBlock in unusedBlocks)
                        {
                            for (int j = 0; j < temp.IntermediateBlocks.Count; j++)
                            {
                                List <IGameBlockDestination> sets = new List <IGameBlockDestination>(temp.IntermediateBlocks);

                                sets.RemoveAt(j);
                                sets.Add(unusedBlock);
                                intermediateBlockSets.Add(sets);
                            }
                        }

                        do
                        {
                            if (gameBoard.IsUntouchedPuzzle())
                            {
                                lock (solutionGameBoards)
                                {
                                    // HACK: Test the solution in case it comes up with an invalid solution
                                    GameBoard testSolution = (GameBoard)gameBoard.Clone();
                                    testSolution.SolutionStartMove = temp.CloneFromGameBoard(testSolution, null);
                                    testSolution.NullZeroPlayers();

                                    string key = testSolution.ToString();

                                    if (!solutionGameBoards.ContainsKey(key))
                                    {
                                        if (testSolution.PlaySolution())
                                        {
                                            GameBoard solution = (GameBoard)gameBoard.Clone();
                                            solution.SolutionStartMove = temp.CloneFromGameBoard(solution, null);
                                            solution.NullZeroPlayers();
                                            solutionGameBoards.Add(key, solution);
                                            NotifySolutionFoundEvent();
                                        }
                                    }
                                }
                            }
                            else if (!gameBoard.HasOrphan())
                            {
                                List <IGameBlockDestination> destinations = new List <IGameBlockDestination>();

                                foreach (IGameBlock nextBlock in gameBoard.GameBlocks)
                                {
                                    IGameBlockDestination nextDestination = nextBlock as IGameBlockDestination;

                                    if (nextDestination != null && !nextDestination.IsFullyAvailable)
                                    {
                                        for (int j = 0; j < nextDestination.NumberUsed; j++)
                                        {
                                            destinations.Add(nextDestination);
                                        }
                                    }
                                }

                                Shuffle(destinations, destinations.Count);

                                foreach (IGameBlockDestination nextBlock in destinations)
                                {
                                    ReverseSolveMovements(
                                        gameBoard,
                                        nextBlock,
                                        null,
                                        maxCountAtPlayer,
                                        maxNumberOfSolutions,
                                        variability,
                                        ref stepsBack,
                                        temp,
                                        solutionGameBoards);

                                    if (solutionGameBoards.Count >= maxNumberOfSolutions)
                                    {
                                        allMovesUsed = true;
                                        break;
                                    }

                                    if (RequestAbort)
                                    {
                                        break;
                                    }
                                }
                            }

                            // Not all the moves were used, but no solution was found, so let's use one of the ones we took out
                            if (!allMovesUsed)
                            {
                                if (intermediateBlockSets.Count == 0)
                                {
                                    allMovesUsed = true;
                                }
                                else
                                {
                                    // Replace the block with one of the unused ones
                                    temp.IntermediateBlocks.ForEach(g => g.SetAvailability(true));

                                    List <IGameBlockDestination> intermediateBlockSet = intermediateBlockSets[0];
                                    intermediateBlockSets.RemoveAt(0);
                                    intermediateBlockSet.ForEach(g => g.SetAvailability(false));

                                    temp.IntermediateBlocks = intermediateBlockSet;
                                }
                            }
                            else
                            {
                                allMovesUsed = true;
                                NotifySolutionFailedEvent();
                            }
                        }while (!allMovesUsed && !RequestAbort);

                        if (removedCombination.Count > 0)
                        {
                            allMovesUsed = false;
                            temp.IntermediateBlocks.Clear();

                            foreach (IGameBlockDestination gameBlockDestination in originalIntermediateBlocks)
                            {
                                IGameBlockDestination blockDestination =
                                    gameBoard.GameBlocks[gameBlockDestination.IndexRow, gameBlockDestination.IndexColumn] as
                                    IGameBlockDestination;
                                blockDestination.Copy(gameBlockDestination);
                                temp.IntermediateBlocks.Add(blockDestination);
                            }

                            temp.SourceBlock.AvailableMoves = originalAvailableMoves;
                        }
                    }

                    BlockMovement blockMove = new BlockMovement(temp.SourceBlock, temp.Direction);
                    temp.SourceBlock.ApplyMove(null, temp.Direction, blockMove);
                }
            }
        }
Пример #17
0
 public abstract bool ApplyReverseMoveForLoop(
     IGameBlockDestination destinationBlock,
     MovementDirection directionInReverse,
     int numberOfBlocksToMove,
     out BlockMovement move,
     IGameBlock previousBlock,
     IGameBlockDestination previousDestination,
     Queue<IGameBlock> blockHistory);
Пример #18
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue<IGameBlock> blockHistory)
        {
            move = null;

            // This can't be the final destination block
            if (destinationBlock == null)
            {
                return false;
            }

            // It needs at least 2 previous blocks
            if (previousDestinationBlock == null)
            {
                return false;
            }

            if (destinationBlock == previousDestinationBlock)
            {
                return false;
            }

            bool moveApplied;
            switch (directionInReverse)
            {
                default:
                case MovementDirection.Down:
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Up:
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Right:
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;

                case MovementDirection.Left:
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMoveForLoop(
                            destinationBlock,
                            directionInReverse,
                            numberOfBlocksToMove - 1,
                            out move,
                            this,
                            previousDestinationBlock,
                            blockHistory);
                    }
                    break;
            }

            if (moveApplied)
            {
                // It requires 1 less move if this block is used
                move.SourceBlock.AvailableMoves--;
            }

            return moveApplied;
        }
Пример #19
0
        public override bool ApplyReverseMove(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue <IGameBlock> blockHistory)
        {
            move = null;

            // Starting with a non-filled block isn't valid
            if (destinationBlock != null && this.isAvailable)
            {
                return(false);
            }

            // If this is the destination
            bool thisIsFinalMove      = destinationBlock == null;
            int  availableBlocksToUse = this.CountUsedBlocks(directionInReverse, new Dictionary <IGameBlock, IGameBlock>());

            // See if there are enough blocks to do this move
            if (thisIsFinalMove && availableBlocksToUse < numberOfBlocksToMove)
            {
                return(false);
            }
            else if (destinationBlock == this)
            {
                // If it came back around to this block again, then it's in a loop.  It needs to break out.
                return(false);
            }
            else if (blockHistory.Contains(this))
            {
                // If it came back around to this block again, then it's in a loop.  It needs to break out.
                return(false);
            }

            blockHistory.Enqueue(this);

            // Use this block as the destination block if destinationBlock is null
            IGameBlockDestination destination = destinationBlock ?? this;

            bool moveApplied;

            switch (directionInReverse)
            {
            default:
            case MovementDirection.Up:
                if (this.Bottom == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Bottom.ApplyReverseMove(
                        destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;

            case MovementDirection.Down:
                if (this.Top == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Top.ApplyReverseMove(
                        destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;

            case MovementDirection.Left:
                if (this.Right == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Right.ApplyReverseMove(
                        destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;

            case MovementDirection.Right:
                if (this.Left == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Left.ApplyReverseMove(
                        destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;
            }

            if (moveApplied && !this.isAvailable && move != null)
            {
                this.IsAvailable = true;
                move.InsertDestinationBlock(this);
                move.SourceBlock.AvailableMoves++;
            }

            return(moveApplied);
        }
Пример #20
0
        public void InsertDestinationBlock(IGameBlockDestination destination)
        {
            // Move the destinationBlock into the intermediateBlocks
            if (this.destinationBlock != null)
            {
                this.intermediateBlocks.Add(this.destinationBlock);
            }

            this.destinationBlock = destination;
        }
Пример #21
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestination,
            Queue<IGameBlock> blockHistory)
        {
            move = null;

            // There should already be a destination block
            if (destinationBlock == null)
            {
                return false;
            }

            blockHistory.Enqueue(this);

            bool moveApplied;
            switch (directionInReverse)
            {
                default:
                case MovementDirection.Down:
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMoveForLoop(
                            destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;

                case MovementDirection.Up:
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMoveForLoop(
                            destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;

                case MovementDirection.Right:
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMoveForLoop(
                            destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;

                case MovementDirection.Left:
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMoveForLoop(
                            destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;
            }

            if (moveApplied && !this.isAvailable && move != null)
            {
                this.IsAvailable = true;
                move.InsertDestinationBlock(this);
                move.SourceBlock.AvailableMoves++;
            }

            return moveApplied;
        }
Пример #22
0
        public override bool ApplyReverseMove(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue <IGameBlock> blockHistory)
        {
            move = null;

            // Starting with a non-filled block isn't valid
            if (destinationBlock != null && this.numberOfMovesApplied == 0)
            {
                return(false);
            }

            // If this is the destination
            bool thisIsFinalMove      = destinationBlock == null;
            int  availableBlocksToUse = this.CountUsedBlocks(directionInReverse, new Dictionary <IGameBlock, IGameBlock>());

            // See if there are enough blocks to do this move
            if (thisIsFinalMove && availableBlocksToUse < numberOfBlocksToMove - 1)
            {
                return(false);
            }

            bool isThisBlockUsedInLoop = ReferenceEquals(destinationBlock, this) || blockHistory.Contains(this);

            blockHistory.Enqueue(this);

            // Use this block as the destination block if destinationBlock is null
            IGameBlockDestination destination = destinationBlock ?? this;

            bool moveApplied;

            switch (directionInReverse)
            {
            default:
            case MovementDirection.Up:
                if (this.numberOfMovesApplied == numberOfMovesNeeded && !isThisBlockUsedInLoop)
                {
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }

                    // Loop failed, so try non-looped
                    if (!moveApplied && this.Bottom != null)
                    {
                        moveApplied = this.Bottom.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }
                else
                {
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }

                break;

            case MovementDirection.Down:
                if (this.numberOfMovesApplied == numberOfMovesNeeded && !isThisBlockUsedInLoop)
                {
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }

                    // Loop failed, so try non-looped
                    if (!moveApplied && this.Top != null)
                    {
                        moveApplied = this.Top.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }
                else
                {
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }

                break;

            case MovementDirection.Left:
                if (this.numberOfMovesApplied == numberOfMovesNeeded && !isThisBlockUsedInLoop)
                {
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }

                    // Loop failed, so try non-looped
                    if (!moveApplied && this.Right != null)
                    {
                        moveApplied = this.Right.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }
                else
                {
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }

                break;

            case MovementDirection.Right:
                if (this.numberOfMovesApplied == numberOfMovesNeeded && !isThisBlockUsedInLoop)
                {
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }

                    // Loop failed, so try non-looped
                    if (!moveApplied && this.Left != null)
                    {
                        moveApplied = this.Left.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }
                else
                {
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMove(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                }

                break;
            }

            if (moveApplied && !this.IsFullyAvailable && move != null)
            {
                this.SetAvailability(true);
                move.InsertDestinationBlock(this);
                move.SourceBlock.AvailableMoves++;
            }

            return(moveApplied);
        }
Пример #23
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestination,
            Queue <IGameBlock> blockHistory)
        {
            move = null;

            // There should already be a destination block
            if (destinationBlock == null)
            {
                return(false);
            }

            blockHistory.Enqueue(this);

            bool moveApplied;

            switch (directionInReverse)
            {
            default:
            case MovementDirection.Down:
                if (this.Bottom == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Bottom.ApplyReverseMoveForLoop(
                        destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;

            case MovementDirection.Up:
                if (this.Top == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Top.ApplyReverseMoveForLoop(
                        destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;

            case MovementDirection.Right:
                if (this.Right == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Right.ApplyReverseMoveForLoop(
                        destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;

            case MovementDirection.Left:
                if (this.Left == null)
                {
                    moveApplied = false;
                }
                else
                {
                    moveApplied = this.Left.ApplyReverseMoveForLoop(
                        destinationBlock, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                }
                break;
            }

            if (moveApplied && !this.isAvailable && move != null)
            {
                this.IsAvailable = true;
                move.InsertDestinationBlock(this);
                move.SourceBlock.AvailableMoves++;
            }

            return(moveApplied);
        }
Пример #24
0
        public override bool ApplyReverseMove(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestinationBlock,
            Queue<IGameBlock> blockHistory)
        {
            // Already used
            if (this.AvailableMoves > 0)
            {
                move = null;
                return false;
            }

            // This block is a valid "starting" point
            move = new BlockMovement(this, directionInReverse);
            return true;
        }
Пример #25
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestination,
            Queue<IGameBlock> blockHistory)
        {
            move = null;

            // Starting with a non-filled block isn't valid
            if (destinationBlock != null && this.numberOfMovesApplied == 0)
            {
                return false;
            }

            // If this is the destination
            bool thisIsFinalMove = destinationBlock == null;
            int availableBlocksToUse = this.CountUsedBlocks(directionInReverse, new Dictionary<IGameBlock, IGameBlock>());

            // See if there are enough blocks to do this move
            if (thisIsFinalMove && availableBlocksToUse < numberOfBlocksToMove)
            {
                return false;
            }

            // Use this block as the destination block if destinationBlock is null
            IGameBlockDestination destination = destinationBlock ?? this;

            blockHistory.Enqueue(this);

            bool moveApplied;
            switch (directionInReverse)
            {
                default:
                case MovementDirection.Up:
                    if (this.Top == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Top.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;

                case MovementDirection.Down:
                    if (this.Bottom == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Bottom.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;

                case MovementDirection.Left:
                    if (this.Left == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Left.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;

                case MovementDirection.Right:
                    if (this.Right == null)
                    {
                        moveApplied = false;
                    }
                    else
                    {
                        moveApplied = this.Right.ApplyReverseMoveForLoop(
                            destination, directionInReverse, numberOfBlocksToMove, out move, this, this, blockHistory);
                    }
                    break;
            }

            if (moveApplied && !this.IsFullyAvailable && move != null)
            {
                this.SetAvailability(true);
                move.InsertDestinationBlock(this);
                move.SourceBlock.AvailableMoves++;
            }

            return moveApplied;
        }
Пример #26
0
        public override bool ApplyReverseMoveForLoop(
            IGameBlockDestination destinationBlock,
            MovementDirection directionInReverse,
            int numberOfBlocksToMove,
            out BlockMovement move,
            IGameBlock previousBlock,
            IGameBlockDestination previousDestination,
            Queue<IGameBlock> blockHistory)
        {
            // Failed to find a looped reverse move
            move = null;

            return false;
        }