/// <summary> /// Used by Query Builder nested class. /// See that class for more details on parameters. /// </summary> public BreadthFirstSearch( Func <IGraph <BreadthFirstSearchNode <T> >, int, int, List <BreadthFirstSearchNode <T> > > adjacencyMethod, Predicate <IGraphSearchNode <T> > failCondition, Predicate <IGraphSearchNode <T> > matchCondition, BreadthFirstSearchNode <T>[,] searchGraph, IGraph <T> sourceGraph) { this.adjacencyMethod = adjacencyMethod; this.failCondition = failCondition; this.matchCondition = matchCondition; this.searchGraph = searchGraph; this.sourceGraph = sourceGraph; }
/// <summary> /// Do a Breadth-First search of the source graph to find a node matching /// the provided criteria. /// </summary> /// <param name="rootX">X position to start the search at.</param> /// <param name="rootY">Y position to start the search at.</param> /// <returns></returns> public BreadthFirstSearchNode <T> SearchAt(int rootX, int rootY) { if (this.matchCondition == null) { return(null); } Queue <BreadthFirstSearchNode <T> > queue = new Queue <BreadthFirstSearchNode <T> >(); queue.Enqueue(this.searchGraph[rootX, rootY]); while (queue.Count > 0) { BreadthFirstSearchNode <T> currentNode = queue.Dequeue(); // Found it! Return the node containing successful search path. if (this.matchCondition(currentNode)) { return(currentNode); } // Still searching. List <BreadthFirstSearchNode <T> > adjacentNodes = GetNeighborElements(currentNode.X, currentNode.Y); foreach (BreadthFirstSearchNode <T> adjacentNode in adjacentNodes) { if (this.failCondition != null && this.failCondition(adjacentNode)) { adjacentNode.SearchStatus = BreadthFirstSearchNode.SearchState.Checked; continue; } if (adjacentNode.SearchStatus == BreadthFirstSearchNode.SearchState.Unchecked) { adjacentNode.SearchStatus = BreadthFirstSearchNode.SearchState.Queued; adjacentNode.PreviousNode = currentNode; queue.Enqueue(adjacentNode); } } // Finished checking this node. currentNode.SearchStatus = BreadthFirstSearchNode.SearchState.Checked; } // No match found. return(null); }
/// <summary> /// Creates a mirror of an existing graph, but decorated with search markers. /// </summary> /// <param name="sourceGraph">Graph to duplicate.</param> /// <returns></returns> private static BreadthFirstSearchNode <T>[,] AssembleSearchArray(IGraph <T> sourceGraph) { int width = sourceGraph.Width; int height = sourceGraph.Height; BreadthFirstSearchNode <T>[,] searchArray = new BreadthFirstSearchNode <T> [width, height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { searchArray[x, y] = new BreadthFirstSearchNode <T>(sourceGraph.GetElement(x, y), x, y); } } return(searchArray); }
/// <summary> /// Create a new query for a graph object. /// </summary> /// <param name="sourceGraph">Graph to search.</param> public Query(IGraph <T> sourceGraph) { this.sourceGraph = sourceGraph; this.searchGraph = AssembleSearchArray(sourceGraph); }