Ejemplo n.º 1
0
        private static IEnumerable <GraphNode> GenerateChildren(GraphNode state, Node[,] nodes, int maxAvail, X_Y endTargetNodePos)
        {
            var children = new X_Y[]
            {
                new X_Y()
                {
                    X = state.EmptyNodePos.X - 1, Y = state.EmptyNodePos.Y
                },
                new X_Y()
                {
                    X = state.EmptyNodePos.X + 1, Y = state.EmptyNodePos.Y
                },
                new X_Y()
                {
                    X = state.EmptyNodePos.X, Y = state.EmptyNodePos.Y + 1
                },
                new X_Y()
                {
                    X = state.EmptyNodePos.X, Y = state.EmptyNodePos.Y - 1
                },
            };

            foreach (var childPos in children)
            {
                if (!(nodes.InBound(childPos) && CanMove(childPos, nodes, maxAvail)))
                {
                    continue;
                }

                var targetPos = state.TargetNodePos.Equals(childPos) ? new X_Y()
                {
                    X = state.EmptyNodePos.X, Y = state.EmptyNodePos.Y
                } : new X_Y()
                {
                    X = state.TargetNodePos.X, Y = state.TargetNodePos.Y
                };

                var child = new GraphNode
                {
                    EmptyNodePos  = childPos,
                    TargetNodePos = targetPos,
                    F             = CalcF(targetPos, childPos, endTargetNodePos),
                    H             = state.H + 1,
                    Parent        = state,
                };

                yield return(child);
            }
        }
        private static string PrintState(string[,] output, X_Y emptyNodePos, string title)
        {
            var outStr = new StringBuilder();

            outStr.AppendLine(title);
            for (int i = 0; i < output.GetLength(0); ++i)
            {
                if (emptyNodePos.X == i && emptyNodePos.Y == 0)
                {
                    outStr.Append("[");
                }
                else if (i == 0)
                {
                    outStr.Append("(");
                }
                else
                {
                    outStr.Append(" ");
                }

                for (int j = 0; j < output.GetLength(1); ++j)
                {
                    outStr.Append(output[i, j].ToString());
                    if (i == emptyNodePos.X && j == emptyNodePos.Y - 1)
                    {
                        outStr.Append("[");
                    }
                    else if (i == emptyNodePos.X && j == emptyNodePos.Y)
                    {
                        outStr.Append("]");
                    }
                    else if (i == 0 && j == 0)
                    {
                        outStr.Append(")");
                    }
                    else
                    {
                        outStr.Append(" ");
                    }
                }

                outStr.AppendLine();
            }

            return(outStr.ToString());
        }
        private MapNode[,] InitMap(Node[,] nodes, X_Y posOfEmptyNode)
        {
            var maxAvail = nodes[posOfEmptyNode.X, posOfEmptyNode.Y].Available;

            MapNode[,] output = new MapNode[nodes.GetLength(0), nodes.GetLength(1)];
            for (int i = 0; i < output.GetLength(0); ++i)
            {
                for (int j = 0; j < output.GetLength(1); ++j)
                {
                    output[i, j] = new MapNode
                    {
                        CanMove = nodes[i, j].Used <= maxAvail,
                    };
                }
            }

            return(output);
        }
Ejemplo n.º 4
0
        private static X_Y GetEmptyNode(Node[,] nodes)
        {
            var posOfEmptyNode = new X_Y();
            var maxAvail       = 0;

            for (int i = 0; i < nodes.GetLength(0); ++i)
            {
                for (int j = 0; j < nodes.GetLength(1); ++j)
                {
                    if (maxAvail < nodes[i, j].Available)
                    {
                        maxAvail         = nodes[i, j].Available;
                        posOfEmptyNode.X = i;
                        posOfEmptyNode.Y = j;
                    }
                }
            }

            return(posOfEmptyNode);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Calculates heuristic distance to target node.
        /// </summary>
        /// <param name="dataPos">The data node position.</param>
        /// <param name="emptyPos">The empty node.</param>
        /// <param name="targetNodePos">The target node.</param>
        /// <returns>The heuristic distance to target node.</returns>
        public static int CalcF(X_Y dataPos, X_Y emptyPos, X_Y targetNodePos)
        {
            var adjustedTargets = new X_Y[]
            {
                new X_Y()
                {
                    X = dataPos.X - 1, Y = dataPos.Y
                },
                new X_Y()
                {
                    X = dataPos.X + 1, Y = dataPos.Y
                },
                new X_Y()
                {
                    X = dataPos.X, Y = dataPos.Y + 1
                },
                new X_Y()
                {
                    X = dataPos.X, Y = dataPos.Y - 1
                },
            };

            var fs = adjustedTargets.Select(t =>
            {
                var distanceTargetY = Math.Abs(dataPos.Y - targetNodePos.Y);
                var distanceEmptyY  = Math.Abs(t.Y - targetNodePos.Y);

                var distanceTargetX = Math.Abs(dataPos.X - targetNodePos.X);
                var distanceEmptyX  = Math.Abs(t.X - targetNodePos.X);

                var f = CalcFAdjusted(distanceTargetX, distanceTargetY, distanceEmptyX, distanceEmptyY);

                return(new { h = emptyPos.CalcManhattanDistance(t), f });
            })
                     .OrderBy(x => x.h)
                     .ThenBy(x => x.f);
            var target = fs.First();

            return(target.h + target.f);
        }
Ejemplo n.º 6
0
        private IEnumerable <State> FillGraphForLocation(Dictionary <char, Dictionary <char, GraphNode> > graph, MapNode[,] map, Dictionary <char, X_Y> locations, char location)
        {
            var visited = new bool[map.GetLength(0), map.GetLength(1)];
            var paths   = new Dictionary <char, GraphNode>();
            var open    = new HashSet <GraphNode>
            {
                new GraphNode
                {
                    CurrentPos       = locations[location],
                    LocationsToVisit = string.Empty,
                    LastLocation     = location,
                },
            };

            while (open.Any())
            {
                var nextOpen = new HashSet <GraphNode>();
                foreach (var node in open)
                {
                    var childrenPos = new X_Y[]
                    {
                        new X_Y()
                        {
                            X = node.CurrentPos.X - 1, Y = node.CurrentPos.Y
                        },
                        new X_Y()
                        {
                            X = node.CurrentPos.X + 1, Y = node.CurrentPos.Y
                        },
                        new X_Y()
                        {
                            X = node.CurrentPos.X, Y = node.CurrentPos.Y + 1
                        },
                        new X_Y()
                        {
                            X = node.CurrentPos.X, Y = node.CurrentPos.Y - 1
                        },
                    };

                    foreach (var childPos in childrenPos)
                    {
                        var childNode = new GraphNode
                        {
                            CurrentPos       = childPos,
                            LocationsToVisit = node.LocationsToVisit,
                            H            = node.H + 1,
                            Parent       = node,
                            LastLocation = node.LastLocation,
                        };

                        if (!map.InBound(childPos) ||
                            !map[childPos.X, childPos.Y].CanMove ||
                            visited[childPos.X, childPos.Y] ||
                            nextOpen.Contains(childNode))
                        {
                            continue;
                        }

                        nextOpen.Add(childNode);

                        if (map[childPos.X, childPos.Y].Location.HasValue)
                        {
                            paths.Add(map[childPos.X, childPos.Y].Location.Value, childNode);

                            yield return(new State
                            {
                                Path = childNode,
                            });
                        }
                    }

                    visited[node.CurrentPos.X, node.CurrentPos.Y] = true;
                }

                open = nextOpen;
            }

            graph.Add(location, paths);
        }
Ejemplo n.º 7
0
 private static bool CanMove(X_Y childPos, Node[,] nodes, int maxAvail)
 {
     return(nodes[childPos.X, childPos.Y].Used <= maxAvail);
 }
Ejemplo n.º 8
0
        private static IEnumerable <State> FindPath(Node[,] nodes, X_Y emptyNodePos)
        {
            var targetNodePos = new X_Y {
                X = nodes.GetLength(0) - 1, Y = 0
            };
            var maxAvail  = nodes[emptyNodePos.X, emptyNodePos.Y].Available;
            var initState = new GraphNode
            {
                TargetNodePos = targetNodePos,
                EmptyNodePos  = emptyNodePos,
                H             = 0,
                F             = 0,
            };
            var endTargetNodePos = new X_Y {
                X = 0, Y = 0
            };

            var open  = new HashSetOrderedBy <GraphNode, int>((state) => state.G);
            var close = new HashSet <GraphNode>();

            open.Add(initState);
            var       count = 0;
            GraphNode path  = null;

            while (open.Any() && path == null)
            {
                count++;
                var currentNode = open.ValueWithMinSelector();

                var children = GenerateChildren(currentNode, nodes, maxAvail, endTargetNodePos);

                foreach (var child in children)
                {
                    if (open.TryGetValue(child, out GraphNode existingNode) || close.TryGetValue(child, out existingNode))
                    {
                        if (existingNode.H <= child.H)
                        {
                            continue;
                        }

                        open.Remove(existingNode);
                    }

                    open.Add(child);
                    if (child.TargetNodePos.Equals(endTargetNodePos))
                    {
                        path = child;
                        break;
                    }
                }

                open.Remove(currentNode);
                close.Add(currentNode);
                yield return(new State
                {
                    Closed = close,
                    Open = open,
                    LastClosed = currentNode,
                    Path = path,
                });
            }
        }