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();
                }
            }
        }
Beispiel #2
0
        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);
            }
        }