/// <summary> /// Scans all maze's nodes and converts into an internal solver's Node. /// </summary> private void InitializeSolver(IWalledMaze maze) { _bfsNodes = new BFSNode[maze.height, maze.width]; IEnumerator <IWalledMazeNode> mazeNodes = maze.getNodes(); while (mazeNodes.MoveNext()) { IWalledMazeNode mazeNode = mazeNodes.Current; if (mazeNode.State == WalledMazeNodeState.Blocked) { _bfsNodes[mazeNode.RowPosition, mazeNode.ColPosition] = new BFSNode(mazeNode.RowPosition, mazeNode.ColPosition) { State = BFSNodeState.Visited, Distance = int.MaxValue } } ; else if (mazeNode.State == WalledMazeNodeState.Gap) { _bfsNodes[mazeNode.RowPosition, mazeNode.ColPosition] = new BFSNode(mazeNode.RowPosition, mazeNode.ColPosition) { State = BFSNodeState.NotVisited, Distance = int.MaxValue } } ; } }
/// <summary> /// Gets adjacents for a node, any node can have at most 8 adjacents. /// </summary> public IEnumerable <IWalledMazeNode> getAdjacentNodes(IWalledMazeNode currentNode) { int rowPosition = currentNode.RowPosition; int colPosition = currentNode.ColPosition; if (rowPosition < 0 || rowPosition >= _height || colPosition < 0 || colPosition >= _width) { //if given node is out of bounds return a empty list as adjacents. return(new List <WalledMazeNode>(0)); } List <WalledMazeNode> adjacents = new List <WalledMazeNode>(8); for (i = rowPosition - 1; i <= rowPosition + 1; i++) { for (j = colPosition - 1; j <= colPosition + 1; j++) { if (i < 0 || i >= _height || j < 0 || j >= _width || (i == rowPosition && j == colPosition)) { continue; } adjacents.Add(_maze[i, j]); } } return(adjacents); }
//Determine if it has arrived at the end point. public bool IsEndPoint(IWalledMazeNode currentNode) { if (currentNode == null) { return(false); } return(currentNode.Equals(_destination)); }
/// <summary> /// Implementatin of the Solve() method. Uses the Breadth Fist Search Algorithm that tracks predecessors and distance from source. /// </summary> public void Solve(IWalledMaze maze, Action <IEnumerable <IWalledMazeNode> > solvedResultCallback) { InitializeSolver(maze); Queue <BFSNode> bfsNodesQueue = new Queue <BFSNode>(); BFSNode startNode = GetBFSNode(maze.start); startNode.Distance = 0; startNode.Predecessor = null; startNode.State = BFSNodeState.Queued; bfsNodesQueue.Enqueue(startNode); while (bfsNodesQueue.Count > 0) { BFSNode curBFSNode = bfsNodesQueue.Dequeue(); IWalledMazeNode curMazeNode = GetMazeNode(maze, curBFSNode); if (maze.IsEndPoint(curMazeNode)) { IEnumerable <IWalledMazeNode> solvedPath = TraceSolvedPath(maze, curBFSNode); solvedResultCallback(solvedPath); return; } foreach (IWalledMazeNode adjMazeNode in maze.getAdjacentNodes(curMazeNode)) { BFSNode adjBFSNode = GetBFSNode(adjMazeNode); if (adjBFSNode.State == BFSNodeState.NotVisited) { adjBFSNode.State = BFSNodeState.Queued; adjBFSNode.Predecessor = curBFSNode; adjBFSNode.Distance = curBFSNode.Distance + 1; bfsNodesQueue.Enqueue(adjBFSNode); } } curBFSNode.State = BFSNodeState.Visited; } //No solution found solvedResultCallback(null); }
/// <summary> /// Conversion function. Converts a maze node to a internal BFS node. /// </summary> private BFSNode GetBFSNode(IWalledMazeNode mazeNode) { return(_bfsNodes[mazeNode.RowPosition, mazeNode.ColPosition]); }