/// <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()); } }