private void Recursive(Node prev) { //Don't attempt to find any paths that are longer than the fastest path discovered so far. if (_fastestWin != -1 && prev.Depth >= _fastestWin || prev.Depth > 30) { return; } Direction prevDirection = Direction.Up; if (prev.Data.Move != null) { prevDirection = prev.Data.Move.Direction; } foreach (int i in _robotsByPriority) { foreach (Direction d in _allDirections) { _numberOfNodesEvaluated++; RobotMove move = _model.MoveRobot(i, d).FirstOrDefault(); if (move == null) { continue; //an Invalid move not worth saving } NodeData nodeData = new NodeData(move, new Dictionary <int, Cell>(_model.RobotCurrentLocations)); Node next = new Node(nodeData, prev.Depth + 1, prev); prev.Next.Add(next); //Check for a repeating position in the tree. Repeated positions do not need to do any more recursive calls. //If the current depth is quicker than the repeated positions depth, // we should use this path to the position. Rebalance the tree + update depths. Node repeatedNode = null; bool shouldRecurse = false; if (_tree.ContainsKey(next.GetIndex())) { repeatedNode = _tree[next.GetIndex()]; } if (repeatedNode != null) { if (repeatedNode.Depth > next.Depth) { SwapRepeatingNode(repeatedNode, next); } } else { //Eww refactor this shouldRecurse = true; _tree.Add(next.GetIndex(), next); } //This move found a solution if (_model.CurrentWinningDestination.X != _winningDestination.X || _model.CurrentWinningDestination.Y != _winningDestination.Y) { if (_fastestWin == -1) { _fastestWin = next.Depth; } if (_fastestWin > next.Depth) { _fastestWin = next.Depth; } _winningNodes.Add(next); _model.UndoMove(); return; } if (shouldRecurse) { Recursive(next); } //Before trying other paths from this node, Undo the current move. _model.UndoMove(); } } }
private void Recursive(int depth) { Console.WriteLine(String.Format("Beginning Depth: {0}", depth)); Dictionary <int, Node> nodesToAdd = new Dictionary <int, Node>(); //Process all nodes at this depth foreach (Node prev in _tree.Where(t => t.Value.Depth == depth).Select(t => t.Value)) { //Console.WriteLine(String.Format("Starting Node: {0}", prev.ToString())); SetRobotCurrentLocations(prev); foreach (int i in _robotsByPriority) { foreach (Direction d in _allDirections) { _numberOfNodesEvaluated++; RobotMove move = _model.MoveRobot(i, d).FirstOrDefault(); if (move == null) { continue; //an Invalid move not worth saving } Console.WriteLine(move.ToString()); NodeData nodeData = new NodeData(move, new Dictionary <int, Cell>(_model.RobotCurrentLocations)); Node next = new Node(nodeData, depth + 1, prev); prev.Next.Add(next); //This move found a solution, we're done processing. if (_model.CurrentWinningDestination.X != _winningDestination.X || _model.CurrentWinningDestination.Y != _winningDestination.Y) { Console.WriteLine("Solution Found with this move."); _winningNode = next; _model.UndoMove(); return; } //Check for a repeating position in the tree. Any repeated position does not need to be evaluated. //It either occurs in the same number of moves, or fewer, since this is a breadth first algorithm. if (!_tree.ContainsKey(next.GetIndex()) && !nodesToAdd.ContainsKey(next.GetIndex())) { nodesToAdd.Add(next.GetIndex(), next); } _model.UndoMove(); } } } //If we didn't add any new nodes, we've searched everything. if (nodesToAdd.Count == 0) { return; } _tree = _tree.Concat(nodesToAdd).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); if (_winningNode == null && depth < 12) //depths >13 will not be explored by BreadthFirst. { Recursive(depth + 1); } }