/// <summary>
        /// Crawls this instance.
        /// </summary>
        /// <returns>The solution if found</returns>
        /// <remarks>We have to override this so we can synchonize the forward and reverse crawlers</remarks>
        public override BaseNode Crawl()
        {
            if (!this.reversed)
            {
                BaseNode solution = null;

                while ((!this.IsQueueEmpty() || !reverseCrawler.IsQueueEmpty()) && solution == null)
                {
                    this.EvaluateAndExpandNode(this.PopQueue());
                    reverseCrawler.Crawl();

                    // If there exists a node that both crawlers have found where, combined, a solution is found; that is our winner.
                    List <BaseNode> similarNodes = this.ExploredSet.Where(en => reverseCrawler.ExploredSet.Any(rcEn => rcEn.Key == en.Key)).ToList();
                    foreach (BaseNode similarNode in similarNodes)
                    {
                        foreach (BaseNode possibleSolution in this.reverseCrawler.ExploredSet.Where(en => en.Key == similarNode.Key))
                        {
                            List <Move> movesToGoal = TreeHelpers.ActionTracker(possibleSolution);
                            movesToGoal.Reverse();
                            movesToGoal = TreeHelpers.ReflectMoves(movesToGoal);

                            int          x             = similarNode.X;
                            int          y             = similarNode.Y;
                            List <int[]> newChildState = new List <int[]>();
                            similarNode.CrateLocations.ForEach(state => newChildState.Add(new int[] { state[0], state[1] }));

                            this.MoveToCurrentNode(movesToGoal, ref x, ref y, ref newChildState);

                            if (IsWinningState(newChildState))
                            {
                                return(InvertNodeHeritage(similarNode, possibleSolution.Parent));
                            }
                        }
                    }
                }

                return(solution);
            }
            else
            {
                // If we are the reversed solution, we just need to take the normal steps and return if we found a solution.
                // all the Bi-Directional stuff is done in the non-reversed loop.
                BaseNode reverseSolution;
                reverseSolution = this.EvaluateAndExpandNode(this.PopQueue());
                return(reverseSolution);
            }
        }
        /// <summary>
        /// Calculates the results.
        /// </summary>
        /// <param name="solution">The solution.</param>
        /// <returns>The results of the exploration</returns>
        private string[] CalculateResults(BaseNode solution)
        {
            if (solution == null)
            {
                return new[] { "Failure. No solution found." }
            }
            ;

            List <string> compiledFinalState = new List <string>();

            string elapsedTime = this.ElapsedTime.ToString();

            List <Move> movesToSolution = TreeHelpers.ActionTracker(solution);

            string numberOfMoves = movesToSolution.Count.ToString();
            string moveBreakdown = movesToSolution.Aggregate(string.Empty, (current, move) => current + move.ToString());
            string prettyDims    = this.mapDims[0] + " " + this.mapDims[1];

            compiledFinalState.Add(elapsedTime);
            compiledFinalState.Add(numberOfMoves);
            compiledFinalState.Add(moveBreakdown);
            compiledFinalState.Add(prettyDims);
            compiledFinalState.Add(solution.Key);

            // Put the crates in the map for display
            foreach (int[] crate in solution.CrateLocations)
            {
                this.map[crate[0], crate[1]] = AlgorithmConstants.crate;
            }

            for (int row = 0; row < this.mapDims[1]; row++)
            {
                string temp = string.Empty;
                for (int column = 0; column < this.mapDims[0]; column++)
                {
                    temp += this.map[column, row];
                }

                compiledFinalState.Add(temp);
            }

            return(compiledFinalState.ToArray());
        }
    }