{"id":307737,"date":"2020-07-30T15:00:36","date_gmt":"2020-07-30T15:00:36","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=307737"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2020-07-30T15:00:36","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=307737","title":{"rendered":"A* pathfinding \u043d\u0430 C#: \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u043a\u0443\u0447\u0438 \u0438 \u0431\u043e\u0440\u044c\u0431\u0430 \u0441 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u044f\u043c\u0438"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/513158\/\">\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c <a href=\"https:\/\/en.wikipedia.org\/wiki\/A*_search_algorithm\" rel=\"nofollow\">\u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0435\u0439\u0448\u0438\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438<\/a>. \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0441 \u0434\u0432\u0443\u043c\u0435\u0440\u043d\u044b\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442.<\/p>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u0440\u0430\u0442\u043a\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u043e\u0431\u0445\u043e\u0434\u0430 \u0433\u0440\u0430\u0444\u043e\u0432, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u0438\u0441\u043a \u043f\u0443\u0442\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0432\u043a\u0443\u0441\u043d\u043e\u043c\u0443: \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438 \u0437\u0430\u0442\u0440\u0430\u0442 \u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438. \u0412 \u0438\u0434\u0435\u0430\u043b\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0443\u044e \u043c\u0443\u0441\u043e\u0440 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438. <\/p>\n<p>  \u042f \u0431\u044b\u043b \u0438\u0437\u0443\u043c\u043b\u0435\u043d, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043d\u0435 \u0432\u044b\u0434\u0430\u043b \u043c\u043d\u0435 \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 A* \u043d\u0430 C# \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a (\u044d\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0438\u0445 \u043d\u0435\u0442). \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u043c\u044f\u0442\u044c \u043f\u0430\u043b\u044c\u0446\u044b!<\/p>\n<p>  \u0416\u0434\u0443 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0447\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438, \u043a\u0430\u043a \u0438 \u0437\u043d\u0430\u0442\u043e\u043a\u043e\u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u0435\u0451 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c!<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2>\u042d\u043a\u0441\u043a\u0443\u0440\u0441 \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u044e<\/h2>\n<p>  \u0414\u0432\u0443\u043c\u0435\u0440\u043d\u0443\u044e \u0441\u0435\u0442\u043a\u0443 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u0433\u0440\u0430\u0444\u0430, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d \u0438\u043c\u0435\u0435\u0442 8 \u0440\u0451\u0431\u0435\u0440:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/yc\/is\/f-\/ycisf-mooaxs7mup9q49av7d-go.png\"><\/p>\n<p>  \u0421 \u0433\u0440\u0430\u0444\u0430\u043c\u0438 \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u041a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u2014 \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430. \u041a\u0430\u0436\u0434\u043e\u0435 \u0440\u0435\u0431\u0440\u043e \u2014 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u043c\u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 \u043f\u043e \u043f\u0440\u044f\u043c\u043e\u0439 \u0438\u043b\u0438 \u043f\u043e \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u0438. \u0421\u0430\u043c\u0443 \u0441\u0435\u0442\u043a\u0443 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0438 \u0440\u0430\u0441\u0447\u0435\u0442 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0438 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u0439 \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u2014 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u043c \u043d\u0430 \u0432\u0445\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0442\u043e\u0447\u0435\u043a \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043f\u0443\u0442\u0438:<\/p>\n<pre><code class=\"cs\">public interface IPath {     IReadOnlyCollection&lt;Vector2Int&gt; Calculate(Vector2Int start, Vector2Int target,          IReadOnlyCollection&lt;Vector2Int&gt; obstacles); }<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u0445\u043e\u0434\u0430 \u0433\u0440\u0430\u0444\u0430.<\/p>\n<h3>\u041f\u043e\u0438\u0441\u043a \u0432 \u0433\u043b\u0443\u0431\u0438\u043d\u0443<\/h3>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/vt\/ew\/ys\/vtewys5_wfju_g7jv1cloygx2ak.png\"><\/p>\n<p>  \u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u0437 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432:<\/p>\n<ol>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u0442\u043e\u043f\u043a\u0443 \u0432\u0441\u0435 \u043d\u0435\u043f\u043e\u0441\u0435\u0449\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0440\u044f\u0434\u043e\u043c \u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439.<\/li>\n<li>\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0438\u0437 \u0441\u0442\u043e\u043f\u043a\u0438.<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0438\u0441\u043a\u043e\u043c\u0430\u044f \u2014 \u0432\u044b\u0445\u043e\u0434\u0438\u043c \u0438\u0437 \u0446\u0438\u043a\u043b\u0430. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u0448\u043b\u0438 \u0432 \u0442\u0443\u043f\u0438\u043a \u2014 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430\u0437\u0430\u0434.<\/li>\n<li>GOTO 1.<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u0432\u043e\u0442 \u0442\u0430\u043a:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">private Node DFS(Node first, Node target) {     List&lt;Node&gt; visited = new List&lt;Node&gt;();     Stack&lt;Node&gt; frontier = new Stack&lt;Node&gt;();     frontier.Push(first);                  while (frontier.Count &gt; 0)     {         var current = frontier.Pop();         visited.Add(current);                         if (current == target)             return Node;          var neighbours = current.GenerateNeighbours();         foreach(var neighbour in neighbours)             if (!visited.Contains(neighbour))                 frontier.Push(neighbour);     }      return default; }<\/code><\/pre>\n<p>  \u041f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e <i>Node<\/i> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0441\u0432\u044f\u0437\u0438, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c.  <\/div>\n<\/p><\/div>\n<p>  \u041e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 LIFO (<i>Last in \u2014 First out<\/i>), \u0433\u0434\u0435 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0441\u0432\u0435\u0436\u0435\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c\u0438 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043f\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0443\u0442\u044c.<\/p>\n<p>  \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 (\u043d\u0443, \u043f\u043e\u0447\u0442\u0438) \u043d\u0435 \u0432\u0435\u0440\u043d\u0435\u0442 <i>\u043a\u0440\u0430\u0442\u0447\u0430\u0439\u0448\u0438\u0439<\/i> \u043f\u0443\u0442\u044c, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0433\u0440\u0430\u0444 \u0432 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438. \u041e\u043d \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0433\u0440\u0430\u0444\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0431\u0435\u0437 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 <i>\u0445\u043e\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e<\/i> \u043f\u0443\u0442\u044c \u0434\u043e \u0438\u0441\u043a\u043e\u043c\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u043d\u0443\u0436\u043d\u043e\u0435 \u0437\u0432\u0435\u043d\u043e \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439).<\/p>\n<p>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0436\u0435 \u0441 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u043a\u043e\u0439 \u0438 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c\u0438 \u0433\u0440\u0430\u0444\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0431\u0443\u0434\u0435\u0442 \u0431\u0435\u0437 \u043a\u043e\u043d\u0446\u0430 \u0438\u0434\u0442\u0438 \u0432 \u043e\u0434\u043d\u0443 \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u0438 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b, \u0442\u0430\u043a \u0438 \u043d\u0435 \u0434\u043e\u0439\u0434\u044f \u0434\u043e \u043d\u0443\u0436\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u0420\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c. \u0417\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0447\u043a\u0438, \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u043d\u0435 \u0434\u0430\u043b\u044c\u0448\u0435, \u0447\u0435\u043c N \u0448\u0430\u0433\u043e\u0432 \u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0434\u043e\u0445\u043e\u0434\u0438\u0442 \u0434\u043e \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043e\u0431\u043b\u0430\u0441\u0442\u0438, \u043e\u043d \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0434\u0438\u0443\u0441\u0430.<\/p>\n<p>  \u0418\u043d\u043e\u0433\u0434\u0430 \u0442\u043e\u0447\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0430 \u043d\u0430\u0443\u0433\u0430\u0434 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 <b>\u0438\u0442\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0432 \u0433\u043b\u0443\u0431\u0438\u043d\u0443<\/b>:<\/p>\n<ol>\n<li>\u0417\u0430\u0434\u0430\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 \u0433\u043b\u0443\u0431\u0438\u043d\u0443.<\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a.<\/li>\n<li>\u0415\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d, \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0430 1.<\/li>\n<li>GOTO 2.<\/li>\n<\/ol>\n<p>  \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0441\u043d\u043e\u0432\u0430 \u0438 \u0441\u043d\u043e\u0432\u0430, \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u044f \u0432\u0441\u0451 \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u043f\u043e\u043a\u0430 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u0442 \u0438\u0441\u043a\u043e\u043c\u0443\u044e \u0442\u043e\u0447\u043a\u0443.<\/p>\n<p>  \u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0440\u0430\u0441\u043d\u043e\u0439 \u0442\u0440\u0430\u0442\u043e\u0439 \u0441\u0438\u043b \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043d\u0430 \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435\u043c \u0440\u0430\u0434\u0438\u0443\u0441\u0435 (\u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438!), \u043d\u043e \u043d\u0435\u0442: \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c\u0438 \u0440\u0430\u0441\u0442\u0435\u0442 \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0434\u0438\u0443\u0441\u0430. \u0413\u043e\u0440\u0430\u0437\u0434\u043e \u0434\u043e\u0440\u043e\u0436\u0435 \u043e\u0431\u043e\u0439\u0434\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c \u0440\u0430\u0434\u0438\u0443\u0441 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0443\u0436\u043d\u043e\u0433\u043e, \u0447\u0435\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u0440\u043e\u0439\u0442\u0438\u0441\u044c \u043f\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u0440\u0430\u0434\u0438\u0443\u0441\u0430\u043c.<\/p>\n<p>  \u0422\u0430\u043a\u043e\u043c\u0443 \u043f\u043e\u0438\u0441\u043a\u0443 \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0443: \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u043c\u0441\u044f \u0440\u0430\u0434\u0438\u0443\u0441\u043e\u043c \u0440\u043e\u0432\u043d\u043e \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043a\u043e\u043d\u0447\u0438\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<h3>\u041f\u043e\u0438\u0441\u043a \u0432 \u0448\u0438\u0440\u0438\u043d\u0443<\/h3>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/fm\/b0\/dr\/fmb0dr8sjwq_4yxkdaxuta3ks3m.png\"><\/p>\n<p>  \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u043e\u0438\u0441\u043a\u0430 \u0432 \u0433\u043b\u0443\u0431\u0438\u043d\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u0442\u043e\u043f\u043a\u0443 (LIFO), \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u044c (FIFO) \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0440\u0448\u0438\u043d:<\/p>\n<ol>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435\u0445 \u043d\u0435\u043f\u043e\u0441\u0435\u0449\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c.<\/li>\n<li>\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438.<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0438\u0441\u043a\u043e\u043c\u0430\u044f \u2014 \u0432\u044b\u0445\u043e\u0434\u0438\u043c \u0438\u0437 \u0446\u0438\u043a\u043b\u0430, \u0438\u043d\u0430\u0447\u0435 GOTO 1.<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u044d\u0442\u043e \u0432\u043e\u0442 \u0442\u0430\u043a:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">private Node BFS(Node first, Node target) {     List&lt;Node&gt; visited = new List&lt;Node&gt;();     Queue&lt;Node&gt; frontier = new Queue&lt;Node&gt;();     frontier.Enqueue(first);                  while (frontier.Count &gt; 0)     {         var current = frontier.Dequeue();         visited.Add(current);                          if (current == target)             return Node;          var neighbours = current.GenerateNeighbours();         foreach(var neighbour in neighbours)             if (!visited.Contains(neighbour))                 frontier.Enqueue(neighbour);     }      return default; }<\/code><\/pre>\n<p>  \u041f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e <i>Node<\/i> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0441\u0432\u044f\u0437\u0438, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c.  <\/div>\n<\/p><\/div>\n<p>  \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u0430\u0451\u0442 <i>\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439<\/i> \u043f\u0443\u0442\u044c, \u043d\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0432\u043e\u0445: \u0442\u0430\u043a \u043a\u0430\u043a \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432\u043e \u0432\u0441\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043e\u043d \u043e\u0447\u0435\u043d\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u044f\u0445 \u0438 \u0433\u0440\u0430\u0444\u0430\u0445 \u0441 \u0441\u0438\u043b\u044c\u043d\u044b\u043c \u0432\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435\u043c. \u041a\u0430\u043a \u0440\u0430\u0437 \u043d\u0430\u0448 \u0441\u043b\u0443\u0447\u0430\u0439.<\/p>\n<p>  \u0422\u0443\u0442 \u0443\u0436\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0448\u044c, \u0438\u0431\u043e \u043e\u043d \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0443\u0439\u0434\u0435\u0442 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0440\u0430\u0434\u0438\u0443\u0441\u0430 \u0434\u043e \u0438\u0441\u043a\u043e\u043c\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u041d\u0443\u0436\u043d\u044b \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<h2>A*<\/h2>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7r\/qi\/fn\/7rqifnsfpygympjj8r43slpso8g.png\"><\/p>\n<p>  \u041c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0432 \u0448\u0438\u0440\u0438\u043d\u0443: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u0448\u0438\u043d, \u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 <i>\u044d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0438<\/i> \u2014 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e\u0439 \u043e\u0446\u0435\u043d\u043a\u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u0443\u0442\u0438. <\/p>\n<p>  \u041a\u0430\u043a \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u043f\u0443\u0442\u044c? \u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u2014 \u0434\u043b\u0438\u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0438\u0437 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0434\u043e \u0438\u0441\u043a\u043e\u043c\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u0427\u0435\u043c \u0432\u0435\u043a\u0442\u043e\u0440 \u043c\u0435\u043d\u044c\u0448\u0435 \u2014 \u0442\u0435\u043c \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u0435\u0435 \u0442\u043e\u0447\u043a\u0430 \u0438 \u0442\u0435\u043c \u0431\u043b\u0438\u0436\u0435 \u043a \u043d\u0430\u0447\u0430\u043b\u0443 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043e\u043d\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f. \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u0442\u0435\u043c \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043b\u0435\u0436\u0430\u0442 \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043a \u0446\u0435\u043b\u0438.<\/p>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0447\u0443\u0442\u044c \u0434\u043e\u043b\u044c\u0448\u0435 \u0438\u0437-\u0437\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439, \u043d\u043e \u0437\u0430 \u0441\u0447\u0435\u0442 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0431\u0443\u0434\u0443\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435) \u043c\u044b \u0434\u043e\u0431\u0438\u0432\u0430\u0435\u043c\u0441\u044f \u043f\u043e\u0442\u0440\u044f\u0441\u0430\u044e\u0449\u0435\u0433\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430.<\/p>\n<p>  \u041d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0432\u0435\u0440\u0448\u0438\u043d \u0432\u0441\u0435 \u0435\u0449\u0451 \u043c\u043d\u043e\u0433\u043e. \u041d\u0430\u0439\u0442\u0438 \u0434\u043b\u0438\u043d\u0443 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u2014 \u0434\u043e\u0440\u043e\u0433\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u0440\u043d\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0441\u0447\u0435\u0442 \u0434\u043b\u044f \u044d\u0432\u0440\u0438\u0441\u0442\u0438\u043a\u0438.<\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u043a\u0442\u043e\u0440:<\/p>\n<pre><code class=\"cs\">public readonly struct Vector2Int : IEquatable&lt;Vector2Int&gt; {     private static readonly double Sqr = Math.Sqrt(2);      public Vector2Int(int x, int y)     {         X = x;         Y = y;     }      public int X { get; }     public int Y { get; }              \/\/\/ &lt;summary&gt;     \/\/\/ Estimated path distance without obstacles.     \/\/\/ &lt;\/summary&gt;     public double DistanceEstimate()     {         int linearSteps = Math.Abs(Y - X);         int diagonalSteps = Math.Max(Math.Abs(Y), Math.Abs(X)) - linearSteps;         return linearSteps + Sqr * diagonalSteps;     }              public static Vector2Int operator +(Vector2Int a, Vector2Int b)          =&gt; new Vector2Int(a.X + b.X, a.Y + b.Y);     public static Vector2Int operator -(Vector2Int a, Vector2Int b)          =&gt; new Vector2Int(a.X - b.X, a.Y - b.Y);     public static bool operator ==(Vector2Int a, Vector2Int b)          =&gt; a.X == b.X &amp;&amp; a.Y == b.Y;     public static bool operator !=(Vector2Int a, Vector2Int b)          =&gt; !(a == b);      public bool Equals(Vector2Int other)         =&gt; X == other.X &amp;&amp; Y == other.Y;      public override bool Equals(object obj)     {         if (!(obj is Vector2Int))             return false;          var other = (Vector2Int) obj;         return X == other.X &amp;&amp; Y == other.Y;     }      public override int GetHashCode()         =&gt; HashCode.Combine(X, Y);      public override string ToString()         =&gt; $&quot;({X}, {Y})&quot;; }<\/code><\/pre>\n<p>  \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u044b \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043e\u0440\u043d\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0440\u0430\u0437. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IEquatable \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 Vector2Int \u0432 object \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u042d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u0438\u0442 \u043d\u0430\u0448 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0438 \u0438\u0437\u0431\u0430\u0432\u0438\u0442 \u043e\u0442 \u043b\u0438\u0448\u043d\u0438\u0445 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439.<\/p>\n<p>  DistanceEstimate() \u0441\u043b\u0443\u0436\u0438\u0442 \u0434\u043b\u044f \u043e\u0446\u0435\u043d\u043a\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e\u0439 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u0434\u043e \u0446\u0435\u043b\u0438 \u043f\u0443\u0442\u0435\u043c \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0440\u044f\u043c\u044b\u0445 \u0438 \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432. \u0420\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: <\/p>\n<pre><code class=\"cs\">return Math.Max(Math.Abs(X), Math.Abs(Y))<\/code><\/pre>\n<p>  \u0422\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0449\u0451 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043d\u043e \u044d\u0442\u043e \u043a\u043e\u043c\u043f\u0435\u043d\u0441\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0438\u0437\u043a\u043e\u0439 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0446\u0435\u043d\u043a\u0438 \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u0439.<\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0438\u0437 \u0441\u0435\u0431\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0433\u0440\u0430\u0444\u0430:<\/p>\n<pre><code class=\"cs\">internal class PathNode {     public PathNode(Vector2Int position, double traverseDist, double heuristicDist, PathNode parent)     {         Position = position;         TraverseDistance = traverseDist;         Parent = parent;         EstimatedTotalCost = TraverseDistance + heuristicDist;     }      public Vector2Int Position { get; }     public double TraverseDistance { get; }     public double EstimatedTotalCost { get; }     public PathNode Parent { get; } }<\/code><\/pre>\n<p>  \u0412 Parent \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u043e\u0432\u043e\u0439: \u044d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u043f\u043e \u0442\u043e\u0447\u043a\u0430\u043c. \u041f\u043e\u043c\u0438\u043c\u043e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u0443\u044e \u043e\u0446\u0435\u043d\u043a\u0443 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0443\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<p>  \u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043d\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f, \u043d\u043e \u043c\u044b \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u043f\u043e\u0437\u0436\u0435. \u041f\u043e\u043a\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b:<\/p>\n<pre><code class=\"cs\">internal static class NodeExtensions {     private static readonly (Vector2Int position, double cost)[] NeighboursTemplate = {         (new Vector2Int(1, 0), 1),         (new Vector2Int(0, 1), 1),         (new Vector2Int(-1, 0), 1),         (new Vector2Int(0, -1), 1),         (new Vector2Int(1, 1), Math.Sqrt(2)),         (new Vector2Int(1, -1), Math.Sqrt(2)),         (new Vector2Int(-1, 1), Math.Sqrt(2)),         (new Vector2Int(-1, -1), Math.Sqrt(2))     };              public static IEnumerable&lt;PathNode&gt; GenerateNeighbours(this PathNode parent, Vector2Int target)     {         foreach ((Vector2Int position, double cost) in NeighboursTemplate)         {             Vector2Int nodePosition = position + parent.Position;             double traverseDistance = parent.TraverseDistance + cost;             double heuristicDistance = (position - target).DistanceEstimate();             yield return new PathNode(nodePosition, traverseDistance, heuristicDistance, parent);         }     } }<\/code><\/pre>\n<p>  NeighboursTemplate \u2014 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0445 \u0438 \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u0438\u0441\u043a\u043e\u043c\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u0412 \u043d\u0435\u043c \u0442\u0430\u043a\u0436\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u043d\u0430\u044f \u0446\u0435\u043d\u0430 \u0434\u0438\u0430\u0433\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432.<\/p>\n<p>  GenerateNeighbours \u2014 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e NeighboursTemplate \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u043e\u0441\u044c\u043c\u0438 \u043f\u0440\u0438\u043b\u0435\u0433\u0430\u044e\u0449\u0438\u0445 \u0441\u0442\u043e\u0440\u043e\u043d.<\/p>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u0438\u0445\u043d\u0443\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0432\u043d\u0443\u0442\u0440\u044c PathNode, \u043d\u043e \u044d\u0442\u043e \u043e\u0449\u0443\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435\u043c SRP. \u0410 \u0437\u0430\u043d\u043e\u0441\u0438\u0442\u044c \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0432\u043d\u0443\u0442\u0440\u044c \u0441\u0430\u043c\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0442\u043e\u0436\u0435 \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f: \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u043c\u0438.<\/p>\n<p>  \u041f\u043e\u0440\u0430 \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438!<\/p>\n<pre><code class=\"cs\">public class Path {     private readonly List&lt;PathNode&gt; frontier = new List&lt;PathNode&gt;();     private readonly List&lt;Vector2Int&gt; ignoredPositions = new List&lt;Vector2Int&gt;();      public IReadOnlyCollection&lt;Vector2Int&gt; Calculate(Vector2Int start, Vector2Int target,          IReadOnlyCollection&lt;Vector2Int&gt; obstacles) {...} \t\t     private bool GenerateNodes(Vector2Int start, Vector2Int target,          IEnumerable&lt;Vector2Int&gt; obstacles, out PathNode node)     {         frontier.Clear();         ignoredPositions.Clear();         ignoredPositions.AddRange(obstacles);          \/\/ Add starting point.         frontier.Add(new PathNode(start, 0, 0, null));          while (frontier.Any())         {             \/\/ Find node with lowest estimated cost.             var lowest = frontier.Min(a =&gt; a.EstimatedTotalCost);             PathNode current = frontier.First(a =&gt; a.EstimatedTotalCost == lowest);             ignoredPositions.Add(current.Position);              if (current.Position.Equals(target))             {                 node = current;                 return true;             }              GenerateFrontierNodes(current, target);         }          \/\/ All nodes analyzed - no path detected.         node = null;         return false;     }      private void GenerateFrontierNodes(PathNode parent, Vector2Int target)     {         foreach (PathNode newNode in parent.GenerateNeighbours(target))         {             \/\/ Position is already checked or occupied by an obstacle.             if (ignoredPositions.Contains(newNode.Position)) continue;              \/\/ Node is not present in queue.             var node = frontier.FirstOrDefault(a =&gt; a.Position == newNode.Position);             if (node == null)                 frontier.Add(newNode);              \/\/ Node is present in queue and new optimal path is detected.             else if (newNode.TraverseDistance &lt; node.TraverseDistance)             {                 frontier.Remove(node);                 frontier.Add(newNode);             }         }     } }<\/code><\/pre>\n<p>  GenerateNodes \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0434\u0432\u0443\u043c\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u043c\u0438: frontier, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430, \u0438 ignoredPositions, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0443\u0436\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b.<\/p>\n<p>  \u0426\u0438\u043a\u043b \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u0438 \u043b\u0438 \u043c\u044b \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443, \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u0441\u0435\u0434\u0435\u0439 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b. <\/p>\n<p>  \u0418 \u0432\u0441\u044f \u044d\u0442\u0430 \u043a\u0440\u0430\u0441\u043e\u0442\u0430 \u0443\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 50 \u0441\u0442\u0440\u043e\u043a.<\/p>\n<p>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"cs\">public IReadOnlyCollection&lt;Vector2Int&gt; Calculate(Vector2Int start, Vector2Int target,      IReadOnlyCollection&lt;Vector2Int&gt; obstacles) {     if (!GenerateNodes(start, target, obstacles, out PathNode node))          return Array.Empty&lt;Vector2Int&gt;();      var output = new List&lt;Vector2Int&gt;();      while (node.Parent != null)     {         output.Add(node.Position);         node = node.Parent;     }      output.Add(start);     return output.AsReadOnly(); }<\/code><\/pre>\n<p>  GenerateNodes \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u043c \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0432\u0435\u0440\u0448\u0438\u043d\u0443, \u0430 \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0432 \u043a\u0430\u0436\u0434\u0443\u044e \u0438\u0437 \u043d\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0441\u043e\u0441\u0435\u0434\u044f-\u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0439\u0442\u0438\u0441\u044c \u043f\u043e \u0432\u0441\u0435\u043c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f\u043c \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u2014 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043a\u0440\u0430\u0442\u0447\u0430\u0439\u0448\u0438\u0439 \u043f\u0443\u0442\u044c. \u0412\u0441\u0451 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e!<\/p>\n<p>  \u0418\u043b\u0438 \u043d\u0435\u0442?<\/p>\n<h2>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430<\/h2>\n<p>  <\/p>\n<h3>1. PathNode<\/h3>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e. \u0423\u043f\u0440\u043e\u0441\u0442\u0438\u043c PathNode:<\/p>\n<pre><code class=\"cs\">internal readonly struct PathNode {     public PathNode(Vector2Int position, Vector2Int target, double traverseDistance)     {         Position = position;         TraverseDistance = traverseDistance;         double heuristicDistance = (position - target).DistanceEstimate();         EstimatedTotalCost = traverseDistance + heuristicDistance;     }      public Vector2Int Position { get; }     public double TraverseDistance { get; }     public double EstimatedTotalCost { get; } }<\/code><\/pre>\n<p>  \u042d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043a \u0442\u043e\u043c\u0443 \u0436\u0435 \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f. \u041d\u0435\u0442 \u043f\u0440\u0438\u0447\u0438\u043d \u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0451 \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0438 \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0438\u0448\u0435\u043c <i>new<\/i>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c struct.<\/p>\n<p>  \u041d\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430: \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0446\u0438\u043a\u043b\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u0441\u0432\u043e\u0439 \u0436\u0435 \u0442\u0438\u043f. \u0417\u043d\u0430\u0447\u0438\u0442, \u0432\u043c\u0435\u0441\u0442\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f Parent \u0432\u043d\u0443\u0442\u0440\u0438 PathNode, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0443\u0442\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0448\u0438\u043d\u0430\u043c\u0438. \u042d\u0442\u043e \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0432 \u043a\u043b\u0430\u0441\u0441 Path:<\/p>\n<pre><code class=\"cs\">private readonly Dictionary&lt;Vector2Int, Vector2Int&gt; links;<\/code><\/pre>\n<p>  \u0418 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u0441\u043e\u0441\u0435\u0434\u0435\u0439:<\/p>\n<pre><code class=\"cs\">private void GenerateFrontierNodes(PathNode parent, Vector2Int target) {     foreach (PathNode newNode in parent.GenerateNeighbours(target))     {         \/\/ Position is already checked or occupied by an obstacle.         if (ignoredPositions.Contains(newNode.Position)) continue;          \/\/ Node is not present in queue.         if (!frontier.TryGet(newNode.Position, out PathNode existingNode))         {             frontier.Enqueue(newNode);             links[newNode.Position] = parent.Position; \/\/ Add link to dictionary.         }          \/\/ Node is present in queue and new optimal path is detected.         else if (newNode.TraverseDistance &lt; existingNode.TraverseDistance)         {             frontier.Modify(newNode);             links[newNode.Position] = parent.Position; \/\/ Add link to dictionary.         }     } }<\/code><\/pre>\n<p>  \u0412\u043c\u0435\u0441\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u0432 \u0441\u0430\u043c\u0443 \u0432\u0435\u0440\u0448\u0438\u043d\u0443, \u043c\u044b \u0437\u0430\u043d\u043e\u0441\u0438\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c. \u041a\u0430\u043a \u0431\u043e\u043d\u0443\u0441 \u2014 \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441 Vector2Int, \u0430 \u043d\u0435 \u0441 PathNode, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0443\u0436\u043d\u044b \u043d\u0430\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435.<\/p>\n<p>  \u0422\u0430\u043a\u0436\u0435 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442\u0441\u044f \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 Calculate:<\/p>\n<pre><code class=\"cs\">public IReadOnlyCollection&lt;Vector2Int&gt; Calculate(Vector2Int start, Vector2Int target,      IReadOnlyCollection&lt;Vector2Int&gt; obstacles) {     if (!GenerateNodes(start, target, obstacles))          return Array.Empty&lt;Vector2Int&gt;();      var output = new List&lt;Vector2Int&gt; {target};     while (links.TryGetValue(target, out target))          output.Add(target);     return output.AsReadOnly(); }<\/code><\/pre>\n<p>  <\/p>\n<h3>2. NodeExtensions<\/h3>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u0441 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0441\u043e\u0441\u0435\u0434\u0435\u0439. IEnumerable, \u043f\u0440\u0438 \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u0445, \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0435\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0443\u0441\u043e\u0440\u0430 \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445. \u0411\u0443\u0434\u0435\u043c \u043e\u0442 \u043d\u0435\u0433\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f:<\/p>\n<pre><code class=\"cs\">internal static class NodeExtensions {     private static readonly (Vector2Int position, double cost)[] NeighboursTemplate = {         (new Vector2Int(1, 0), 1),         (new Vector2Int(0, 1), 1),         (new Vector2Int(-1, 0), 1),         (new Vector2Int(0, -1), 1),         (new Vector2Int(1, 1), Math.Sqrt(2)),         (new Vector2Int(1, -1), Math.Sqrt(2)),         (new Vector2Int(-1, 1), Math.Sqrt(2)),         (new Vector2Int(-1, -1), Math.Sqrt(2))     };              public static void Fill(this PathNode[] buffer, PathNode parent, Vector2Int target)     {         int i = 0;         foreach ((Vector2Int position, double cost) in NeighboursTemplate)         {             Vector2Int nodePosition = position + parent.Position;             double traverseDistance = parent.TraverseDistance + cost;             buffer[i++] = new PathNode(nodePosition, target, traverseDistance);         }     } }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u043c\u0435\u0442\u043e\u0434 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c: \u043e\u043d \u043b\u0438\u0448\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0431\u0443\u0444\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u043c\u0443 \u043f\u043e\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430. \u0411\u0443\u0444\u0435\u0440 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u043a\u0430\u043a \u0435\u0449\u0451 \u043e\u0434\u043d\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 Path:<\/p>\n<pre><code class=\"cs\">private const int MaxNeighbours = 8; private readonly PathNode[] neighbours = new PathNode[MaxNeighbours];<\/code><\/pre>\n<p>  \u0418 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">neighbours.Fill(parent, target); foreach(var neighbour in neighbours) {    \/\/ ...<\/code><\/pre>\n<p>  <\/p>\n<h3>3. HashSet<\/h3>\n<p>  \u0412\u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f List \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f HashSet:<\/p>\n<pre><code class=\"cs\">private readonly HashSet&lt;Vector2Int&gt; ignoredPositions;<\/code><\/pre>\n<p>  \u041e\u043d \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0435\u0435 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u043c\u0438, \u043c\u0435\u0442\u043e\u0434 ignoredPositions.Contains() \u2014 \u043e\u0447\u0435\u043d\u044c \u0437\u0430\u0442\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c \u0438\u0437-\u0437\u0430 \u0447\u0430\u0441\u0442\u043e\u0442\u044b \u0432\u044b\u0437\u043e\u0432\u0430. \u041f\u0440\u043e\u0441\u0442\u0430\u044f \u0441\u043c\u0435\u043d\u0430 \u0442\u0438\u043f\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0434\u0430\u0441\u0442 \u0437\u0430\u043c\u0435\u0442\u043d\u044b\u0439 \u0431\u0443\u0441\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<h3>4. BinaryHeap<\/h3>\n<p>  \u0415\u0441\u0442\u044c \u043e\u0434\u043d\u043e \u043c\u0435\u0441\u0442\u043e \u0432 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 \u0432 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437:<\/p>\n<pre><code class=\"cs\">\/\/ Find node with lowest estimated cost. var lowest = frontier.Min(a =&gt; a.EstimatedTotalCost); PathNode current = frontier.First(a =&gt; a.EstimatedTotalCost == lowest);<\/code><\/pre>\n<p>  List \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Linq \u0443\u0441\u0443\u0433\u0443\u0431\u043b\u044f\u0435\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e. <br \/>  \u0412 \u0438\u0434\u0435\u0430\u043b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0441:<\/p>\n<ul>\n<li>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043e\u0439.<\/li>\n<li>\u041d\u0438\u0437\u043a\u0438\u043c \u0440\u043e\u0441\u0442\u043e\u043c \u0430\u0441\u0438\u043c\u043f\u0442\u043e\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/li>\n<li>\u0411\u044b\u0441\u0442\u0440\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0432\u0441\u0442\u0430\u0432\u043a\u0438.<\/li>\n<li>\u0411\u044b\u0441\u0442\u0440\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f.<\/li>\n<li>\u041b\u0435\u0433\u043a\u043e\u0439 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0435\u0439 \u043f\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c.<\/li>\n<\/ul>\n<p>  \u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e SortedSet \u2014 \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043d\u043e \u043e\u043d \u043d\u0435 \u0443\u043c\u0435\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b. \u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e EstimatedTotalCost, \u0442\u043e \u0432\u0441\u0435 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0439 \u0446\u0435\u043d\u043e\u0439 (\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438!) \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0441\u0435\u044f\u043d\u044b. \u0412 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u0445 \u0441 \u043c\u0430\u043b\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u0439 \u044d\u0442\u043e \u043d\u0435 \u0441\u0442\u0440\u0430\u0448\u043d\u043e, \u043f\u043b\u044e\u0441 \u0443\u0441\u043a\u043e\u0440\u0438\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430, \u043d\u043e \u0432 \u0443\u0437\u043a\u0438\u0445 \u043b\u0430\u0431\u0438\u0440\u0438\u043d\u0442\u0430\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0443\u0442 \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0438 \u043b\u043e\u0436\u043d\u043e-\u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b.<\/p>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u2014 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Binary_heap\" rel=\"nofollow\">\u0434\u0432\u043e\u0438\u0447\u043d\u0443\u044e \u043a\u0443\u0447\u0443<\/a>! \u041a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u043c 4 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0438\u0437 5, \u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u044d\u0442\u0443 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f.<\/p>\n<p>  \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e, \u0441\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0432\u043d\u043e\u0439 <i>log(n)<\/i>.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sc\/68\/om\/sc68om2l7rmytzhgwc6emv3nbxs.png\"><br \/>  <i>\u0414\u0432\u043e\u0438\u0447\u043d\u0430\u044f \u043a\u0443\u0447\u0430 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043f\u043e \u0443\u0431\u044b\u0432\u0430\u043d\u0438\u044e<\/i><\/p>\n<pre><code class=\"cs\">internal interface IBinaryHeap&lt;in TKey, T&gt; {     void Enqueue(T item);     T Dequeue();     void Clear();     bool TryGet(TKey key, out T value);     void Modify(T value);     int Count { get; } }<\/code><\/pre>\n<p>  \u041f\u0438\u0448\u0435\u043c \u043b\u0435\u0433\u043a\u0443\u044e \u0447\u0430\u0441\u0442\u044c:<\/p>\n<pre><code class=\"cs\">internal class BinaryHeap : IBinaryHeap&lt;Vector2Int, PathNode&gt; {     private readonly IDictionary&lt;Vector2Int, int&gt; map;     private readonly IList&lt;PathNode&gt; collection;     private readonly IComparer&lt;PathNode&gt; comparer;              public BinaryHeap(IComparer&lt;PathNode&gt; comparer)     {         this.comparer = comparer;         collection = new List&lt;PathNode&gt;();         map = new Dictionary&lt;Vector2Int, int&gt;();     }      public int Count =&gt; collection.Count;      public void Clear()     {     collection.Clear();     map.Clear();     }\t\t      \/\/ ... }<\/code><\/pre>\n<p>  IComparer \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0432\u0435\u0440\u0448\u0438\u043d. IList \u2014 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0432\u0435\u0440\u0448\u0438\u043d, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. IDictionary \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432 \u0432\u0435\u0440\u0448\u0438\u043d \u0434\u043b\u044f \u0438\u0445 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f (\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0432\u043e\u0438\u0447\u043d\u043e\u0439 \u043a\u0443\u0447\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0432\u0435\u0440\u0445\u043d\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c).<\/p>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"cs\">public void Enqueue(PathNode item) {     collection.Add(item);     int i = collection.Count - 1;     map[item.Position] = i;      \/\/ Sort nodes from bottom to top.     while(i &gt; 0)     {         int j = (i - 1) \/ 2;                          if (comparer.Compare(collection[i], collection[j]) &lt;= 0)             break;          Swap(i, j);         i = j;     } } \t private void Swap(int i, int j) {     PathNode temp = collection[i];     collection[i] = collection[j];     collection[j] = temp;     map[collection[i].Position] = i;     map[collection[j].Position] = j; }<\/code><\/pre>\n<p>  \u041a\u0430\u0436\u0434\u044b\u0439 \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u044f\u0447\u0435\u0439\u043a\u0443 \u0434\u0435\u0440\u0435\u0432\u0430, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u043d\u0438\u0437\u0443 \u0432\u0432\u0435\u0440\u0445: \u043f\u043e \u0443\u0437\u043b\u0430\u043c \u043e\u0442 \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0434\u043e \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e, \u043f\u043e\u043a\u0430 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0435 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0448\u0435. \u0422\u0430\u043a \u043a\u0430\u043a \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0435 \u0432\u0441\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f, \u0430 \u043b\u0438\u0448\u044c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0443\u0437\u043b\u044b \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0440\u0445\u043d\u0438\u043c \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c, \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c <i>log(n)<\/i>.<\/p>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"cs\">public PathNode Dequeue() {     if (collection.Count == 0) return default;                PathNode result = collection.First();     RemoveRoot();     map.Remove(result.Position);     return result; } \t private void RemoveRoot() {     collection[0] = collection.Last();     map[collection[0].Position] = 0;     collection.RemoveAt(collection.Count - 1);      \/\/ Sort nodes from top to bottom.     var i = 0;     while(true)     {         int largest = LargestIndex(i);         if (largest == i)             return;          Swap(i, largest);         i = largest;     } } \t private int LargestIndex(int i) {     int leftInd = 2 * i + 1;     int rightInd = 2 * i + 2;     int largest = i;      if (leftInd &lt; collection.Count          &amp;&amp; comparer.Compare(collection[leftInd], collection[largest]) &gt; 0)          largest = leftInd;      if (rightInd &lt; collection.Count          &amp;&amp; comparer.Compare(collection[rightInd], collection[largest]) &gt; 0)          largest = rightInd;                  return largest; }<\/code><\/pre>\n<p>  \u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c: \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f, \u0430 \u043d\u0430 \u0435\u0433\u043e \u043c\u0435\u0441\u0442\u043e \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u043d\u0438\u0437 \u043c\u0435\u043d\u044f\u0435\u0442 \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0432\u0435\u0440\u0445\u0443 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0438\u0439.<\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u043e\u0438\u0441\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438 \u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"cs\">public bool TryGet(Vector2Int key, out PathNode value) {     if (!map.TryGetValue(key, out int index))     {         value = default;         return false;     }                  value = collection[index];     return true; }  public void Modify(PathNode value) {     if (!map.TryGetValue(value.Position, out int index))         throw new KeyNotFoundException(nameof(value));                  collection[index] = value; }<\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e: \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u043f\u043e\u0438\u0441\u043a \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u0441\u043b\u043e\u0432\u0430\u0440\u044c, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e.<\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043a\u0443\u0447\u0438:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">internal class BinaryHeap&lt;TKey, T&gt; : IBinaryHeap&lt;TKey, T&gt; where TKey : IEquatable&lt;TKey&gt; {     private readonly IDictionary&lt;TKey, int&gt; map;     private readonly IList&lt;T&gt; collection;     private readonly IComparer&lt;T&gt; comparer;     private readonly Func&lt;T, TKey&gt; lookupFunc;              public BinaryHeap(IComparer&lt;T&gt; comparer, Func&lt;T, TKey&gt; lookupFunc, int capacity)     {         this.comparer = comparer;         this.lookupFunc = lookupFunc;         collection = new List&lt;T&gt;(capacity);         map = new Dictionary&lt;TKey, int&gt;(capacity);     }      public int Count =&gt; collection.Count;      public void Enqueue(T item)     {         collection.Add(item);         int i = collection.Count - 1;         map[lookupFunc(item)] = i;         while(i &gt; 0)         {             int j = (i - 1) \/ 2;                              if (comparer.Compare(collection[i], collection[j]) &lt;= 0)                 break;              Swap(i, j);             i = j;         }     }      public T Dequeue()     {         if (collection.Count == 0) return default;                      T result = collection.First();         RemoveRoot();         map.Remove(lookupFunc(result));         return result;     }      public void Clear()     {         collection.Clear();         map.Clear();     }      public bool TryGet(TKey key, out T value)     {         if (!map.TryGetValue(key, out int index))         {             value = default;             return false;         }                      value = collection[index];         return true;     }      public void Modify(T value)     {         if (!map.TryGetValue(lookupFunc(value), out int index))             throw new KeyNotFoundException(nameof(value));                      collection[index] = value;     }              private void RemoveRoot()     {         collection[0] = collection.Last();         map[lookupFunc(collection[0])] = 0;         collection.RemoveAt(collection.Count - 1);          var i = 0;         while(true)         {             int largest = LargestIndex(i);             if (largest == i)                 return;              Swap(i, largest);             i = largest;         }     }      private void Swap(int i, int j)     {         T temp = collection[i];         collection[i] = collection[j];         collection[j] = temp;         map[lookupFunc(collection[i])] = i;         map[lookupFunc(collection[j])] = j;     }      private int LargestIndex(int i)     {         int leftInd = 2 * i + 1;         int rightInd = 2 * i + 2;         int largest = i;          if (leftInd &lt; collection.Count &amp;&amp; comparer.Compare(collection[leftInd], collection[largest]) &gt; 0) largest = leftInd;          if (rightInd &lt; collection.Count &amp;&amp; comparer.Compare(collection[rightInd], collection[largest]) &gt; 0) largest = rightInd;                      return largest;     } }<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u043f\u043e\u0438\u0441\u043a \u043f\u0443\u0442\u0438 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0438\u043b\u0438\u0447\u043d\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u0443\u0441\u043e\u0440\u0430 \u043f\u043e\u0447\u0442\u0438 \u043d\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c. \u0424\u0438\u043d\u0438\u0448 \u0431\u043b\u0438\u0437\u043e\u043a!<\/p>\n<h3>5. \u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438<\/h3>\n<p>  \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043e\u0433\u043b\u044f\u0434\u043a\u043e\u0439 \u043d\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u043c\u0443\u0441\u043e\u0440\u0430 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u0430: \u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 (\u0438 \u0431\u0443\u0434\u0435\u0442!) \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0441\u0430\u0434\u043a\u0438 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  \u0412\u0441\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u043a\u0440\u043e\u043c\u0435 output, \u0443\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u0430, \u0442\u0443\u0434\u0430 \u0436\u0435 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e:<\/p>\n<pre><code class=\"cs\">private const int MaxNeighbours = 8; private readonly PathNode[] neighbours = new PathNode[MaxNeighbours];  private readonly IBinaryHeap&lt;Vector2Int, PathNode&gt; frontier; private readonly HashSet&lt;Vector2Int&gt; ignoredPositions; private readonly IList&lt;Vector2Int&gt; output; private readonly IDictionary&lt;Vector2Int, Vector2Int&gt; links;  public Path() {     var comparer = Comparer&lt;PathNode&gt;.Create((a, b) =&gt; b.EstimatedTotalCost.CompareTo(a.EstimatedTotalCost));     frontier = new BinaryHeap(comparer);     ignoredPositions = new HashSet&lt;Vector2Int&gt;();     output = new List&lt;Vector2Int&gt;();     links = new Dictionary&lt;Vector2Int, Vector2Int&gt;(); }<\/code><\/pre>\n<p>  \u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0434:<\/p>\n<pre><code class=\"cs\">public IReadOnlyCollection&lt;Vector2Int&gt; Calculate(Vector2Int start, Vector2Int target,      IReadOnlyCollection&lt;Vector2Int&gt; obstacles) {         if (!GenerateNodes(start, target, obstacles))                  return Array.Empty&lt;Vector2Int&gt;();          output.Clear();         output.Add(target);          while (links.TryGetValue(target, out target))              output.Add(target);         return output.AsReadOnly(); }<\/code><\/pre>\n<p>  \u0418 \u0434\u0435\u043b\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439! \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u0435\u043d\u044f\u044e\u0442 \u0441\u0432\u043e\u044e \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438, \u0435\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u0434\u043b\u0438\u043d\u043d\u044b\u0439 \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437. \u042d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0430\u043c\u044f\u0442\u044c. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438\u0445 \u0431\u0435\u0437 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445, \u043e\u043d\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442 \u0441\u0432\u043e\u044e \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c. \u041f\u0435\u0440\u0432\u043e\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0443\u0442\u0438 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043c\u0443\u0441\u043e\u0440\u0430 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u0437\u0430\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0439 (\u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0447\u0442\u043e \u0434\u043b\u0438\u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u043f\u043b\u044e\u0441-\u043c\u0438\u043d\u0443\u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430 \u0431\u0435\u0437 \u0440\u0435\u0437\u043a\u0438\u0445 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u043e\u0432). \u041e\u0442\u0441\u044e\u0434\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043f\u0443\u043d\u043a\u0442:<\/p>\n<h3>6. (\u0411\u043e\u043d\u0443\u0441) \u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439<\/h3>\n<p>  \u0421\u0440\u0430\u0437\u0443 \u0432\u0441\u0442\u0430\u0435\u0442 \u0440\u044f\u0434 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\u041b\u0443\u0447\u0448\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 Path \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438?<\/li>\n<li>\u041a\u0430\u043a\u0443\u044e \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0441\u043a\u0430\u0440\u043c\u043b\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u043c?<\/li>\n<li>\u0414\u0435\u0448\u0435\u0432\u043b\u0435 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0438\u043b\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c\u0441\u044f \u0441\u0430\u043c\u043e\u0439?<\/li>\n<\/ul>\n<p>  \u041d\u0430 \u0442\u0440\u0435\u0442\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443: \u0435\u0441\u043b\u0438 \u0443 \u043d\u0430\u0441 \u0441\u043e\u0442\u043d\u0438 \u0438 \u0442\u044b\u0441\u044f\u0447\u0438 \u044f\u0447\u0435\u0435\u043a \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438, \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0434\u0435\u0448\u0435\u0432\u043b\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u043d\u0430\u0448\u0438\u043c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u043c.<\/p>\n<p>  \u041d\u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0432\u0430 \u0432\u043e\u043f\u0440\u043e\u0441\u0430 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435. \u041e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043d\u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u044d\u043c\u043f\u0438\u0440\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043b\u0443\u0447\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u043c\u044b \u0432\u0441\u0451 \u0436\u0435 \u0440\u0435\u0448\u0430\u0435\u043c \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0442\u043e \u043f\u043e\u0440\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043d\u0430\u0448 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0448\u0430\u0433\u043e\u0432:<\/p>\n<pre><code class=\"cs\">public Path(int maxSteps) {     this.maxSteps = maxSteps;     var comparer = Comparer&lt;PathNode&gt;.Create((a, b) =&gt; b.EstimatedTotalCost.CompareTo(a.EstimatedTotalCost));     frontier = new BinaryHeap(comparer, maxSteps);     ignoredPositions = new HashSet&lt;Vector2Int&gt;(maxSteps);     output = new List&lt;Vector2Int&gt;(maxSteps);     links = new Dictionary&lt;Vector2Int, Vector2Int&gt;(maxSteps); }<\/code><\/pre>\n<p>  \u0412\u043d\u0443\u0442\u0440\u0438 GenerateNodes \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0446\u0438\u043a\u043b:<\/p>\n<pre><code class=\"cs\">var step = 0; while (frontier.Count &gt; 0 &amp;&amp; step++ &lt;= maxSteps)  {    \/\/ ... }<\/code><\/pre>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u043c \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0432\u043d\u0430\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432\u043c\u0435\u0449\u0430\u044e\u0442 \u0432 \u0441\u0435\u0431\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u0443\u0437\u043b\u044b, \u043d\u043e \u0438 \u0438\u0445 \u0441\u043e\u0441\u0435\u0434\u0435\u0439: \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u0432 4-5 \u0440\u0430\u0437 \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439. <\/p>\n<p>  \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437\u0447\u0443\u0440, \u043d\u043e \u0434\u043b\u044f \u043f\u0443\u0442\u0435\u0439, \u0431\u043b\u0438\u0437\u043a\u0438\u0445 \u043a \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u043c\u0443, \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u0442\u0440\u0430\u0442\u0438\u0442 \u0432\u0434\u0432\u043e\u0435-\u0432\u0442\u0440\u043e\u0435 \u043c\u0435\u043d\u044c\u0448\u0435 \u043f\u0430\u043c\u044f\u0442\u0438, \u0447\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435. \u0415\u0441\u043b\u0438 \u0436\u0435, \u043d\u0430\u043f\u0440\u043e\u0442\u0438\u0432, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e maxSteps \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u043f\u0443\u0442\u0438, \u0442\u0430\u043a\u043e\u0435 \u043d\u043e\u0432\u043e\u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u0434\u0438\u0442\u044c. \u041e, \u0438 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c int.MaxValue!<\/p>\n<p>  \u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432, \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0437\u0430\u0434\u0430\u0435\u0442 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439. \u0422\u043e\u0433\u0434\u0430 \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0431\u0435\u0437 \u0435\u0433\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<h3>\u0427\u0442\u043e \u0435\u0449\u0451 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c?<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/li>\n<li>\u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c XML-\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e.<\/li>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0445\u0435\u0448 \u0434\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u0430 GetHashCode \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 Vector2Int. \u0412\u0435\u043a\u0442\u043e\u0440 \u0438\u043c\u043c\u0443\u0442\u0430\u0431\u0435\u043b\u0435\u043d, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435\u0442 \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438, \u0447\u0442\u043e \u0445\u0435\u0448 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430.<\/li>\n<li>\u041f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u0439 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b. \u041d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430 \u0441 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0441\u043a\u0430\u0440\u043c\u043b\u0438\u0432\u0430\u0442\u044c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0443 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u0439.<\/li>\n<li>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IComparable \u0434\u043b\u044f PathNode \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e EqualityComparer. \u042d\u0442\u043e \u0434\u0430\u0441\u0442 \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u043e\u0441\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b \u0447\u0443\u0442\u044c \u043f\u043e\u0447\u0438\u0449\u0435.<\/li>\n<li>\u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445: \u043f\u0435\u0440\u0435\u0434 \u043e\u0447\u0438\u0441\u0442\u043a\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c \u043b\u0438 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438. \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043e \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u043f\u0443\u0442\u044c \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u044b\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u043c, \u0430 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u0441\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043d\u0443\u043b\u044f.<\/li>\n<li>\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0443 \u043c\u0435\u0442\u043e\u0434\u0430 \u0432 \u043d\u0430\u0448\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u0447\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043e\u0442\u0440\u0430\u0436\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0443\u0442\u044c:\n<pre><code class=\"cs\">bool Calculate(Vector2Int start, Vector2Int target,      IReadOnlyCollection&lt;Vector2Int&gt; obstacles,      out IReadOnlyCollection&lt;Vector2Int&gt; path);<\/code><\/pre>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u043e \u043c\u0435\u0442\u043e\u0434\u0443 \u043a\u0440\u0438\u0441\u0441\u0442\u0430\u043b\u044c\u043d\u043e \u0432\u0438\u0434\u043d\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u043e \u0431\u044b \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0442\u0430\u043a: <i>CalculateOrReturnEmpty<\/i>.<\/li>\n<\/ul>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0418\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 Path:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cs\">\/\/\/ &lt;summary&gt; \/\/\/ Reusable A* path finder. \/\/\/ &lt;\/summary&gt; public class Path : IPath {     private const int MaxNeighbours = 8;     private readonly PathNode[] neighbours = new PathNode[MaxNeighbours];      private readonly int maxSteps;     private readonly IBinaryHeap&lt;Vector2Int, PathNode&gt; frontier;     private readonly HashSet&lt;Vector2Int&gt; ignoredPositions;     private readonly List&lt;Vector2Int&gt; output;     private readonly IDictionary&lt;Vector2Int, Vector2Int&gt; links;      \/\/\/ &lt;summary&gt;     \/\/\/ Creation of new path finder.     \/\/\/ &lt;\/summary&gt;     \/\/\/ &lt;exception cref=&quot;ArgumentOutOfRangeException&quot;&gt;&lt;\/exception&gt;     public Path(int maxSteps = int.MaxValue, int initialCapacity = 0)     {         if (maxSteps &lt;= 0)              throw new ArgumentOutOfRangeException(nameof(maxSteps));         if (initialCapacity &lt; 0)              throw new ArgumentOutOfRangeException(nameof(initialCapacity));          this.maxSteps = maxSteps;         var comparer = Comparer&lt;PathNode&gt;.Create((a, b) =&gt; b.EstimatedTotalCost.CompareTo(a.EstimatedTotalCost));         frontier = new BinaryHeap&lt;Vector2Int, PathNode&gt;(comparer, a =&gt; a.Position, initialCapacity);         ignoredPositions = new HashSet&lt;Vector2Int&gt;(initialCapacity);         output = new List&lt;Vector2Int&gt;(initialCapacity);         links = new Dictionary&lt;Vector2Int, Vector2Int&gt;(initialCapacity);     }      \/\/\/ &lt;summary&gt;     \/\/\/ Calculate a new path between two points.     \/\/\/ &lt;\/summary&gt;     \/\/\/ &lt;exception cref=&quot;ArgumentNullException&quot;&gt;&lt;\/exception&gt;     public bool Calculate(Vector2Int start, Vector2Int target,          IReadOnlyCollection&lt;Vector2Int&gt; obstacles,          out IReadOnlyCollection&lt;Vector2Int&gt; path)     {         if (obstacles == null)              throw new ArgumentNullException(nameof(obstacles));          if (!GenerateNodes(start, target, obstacles))         {             path = Array.Empty&lt;Vector2Int&gt;();             return false;         }          output.Clear();         output.Add(target);          while (links.TryGetValue(target, out target)) output.Add(target);         path = output;         return true;     }      private bool GenerateNodes(Vector2Int start, Vector2Int target, IReadOnlyCollection&lt;Vector2Int&gt; obstacles)     {         frontier.Clear();         ignoredPositions.Clear();         links.Clear();          frontier.Enqueue(new PathNode(start, target, 0));         ignoredPositions.UnionWith(obstacles);         var step = 0;         while (frontier.Count &gt; 0 &amp;&amp; step++ &lt;= maxSteps)         {             PathNode current = frontier.Dequeue();             ignoredPositions.Add(current.Position);              if (current.Position.Equals(target)) return true;              GenerateFrontierNodes(current, target);         }          \/\/ All nodes analyzed - no path detected.         return false;     }      private void GenerateFrontierNodes(PathNode parent, Vector2Int target)     {         neighbours.Fill(parent, target);         foreach (PathNode newNode in neighbours)         {             \/\/ Position is already checked or occupied by an obstacle.             if (ignoredPositions.Contains(newNode.Position)) continue;              \/\/ Node is not present in queue.             if (!frontier.TryGet(newNode.Position, out PathNode existingNode))             {                 frontier.Enqueue(newNode);                 links[newNode.Position] = parent.Position;             }              \/\/ Node is present in queue and new optimal path is detected.             else if (newNode.TraverseDistance &lt; existingNode.TraverseDistance)             {                 frontier.Modify(newNode);                 links[newNode.Position] = parent.Position;             }         }     } }<\/code><\/pre>\n<p>  <\/div>\n<\/p><\/div>\n<p>  <a href=\"https:\/\/bitbucket.org\/Xamtos\/randomstuff\/src\/master\/Projects\/AI\/A_Star\/\" rel=\"nofollow\">\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434<\/a><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/513158\/\"> https:\/\/habr.com\/ru\/post\/513158\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/513158\/\">\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c <a href=\"https:\/\/en.wikipedia.org\/wiki\/A*_search_algorithm\" rel=\"nofollow\">\u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0435\u0439\u0448\u0438\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438<\/a>. \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0441 \u0434\u0432\u0443\u043c\u0435\u0440\u043d\u044b\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u043c \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442.<\/p>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u0440\u0430\u0442\u043a\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u043e\u0431\u0445\u043e\u0434\u0430 \u0433\u0440\u0430\u0444\u043e\u0432, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u0438\u0441\u043a \u043f\u0443\u0442\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0432\u043a\u0443\u0441\u043d\u043e\u043c\u0443: \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438 \u0437\u0430\u0442\u0440\u0430\u0442 \u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438. \u0412 \u0438\u0434\u0435\u0430\u043b\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0443\u044e \u043c\u0443\u0441\u043e\u0440 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438. <\/p>\n<p>  \u042f \u0431\u044b\u043b \u0438\u0437\u0443\u043c\u043b\u0435\u043d, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043d\u0435 \u0432\u044b\u0434\u0430\u043b \u043c\u043d\u0435 \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 A* \u043d\u0430 C# \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a (\u044d\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0438\u0445 \u043d\u0435\u0442). \u0410 \u0437\u043d\u0430\u0447\u0438\u0442 \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u043c\u044f\u0442\u044c \u043f\u0430\u043b\u044c\u0446\u044b!<\/p>\n<p>  \u0416\u0434\u0443 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0447\u0435\u0442 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0443\u0442\u0438, \u043a\u0430\u043a \u0438 \u0437\u043d\u0430\u0442\u043e\u043a\u043e\u0432 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u0435\u0451 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c!  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-307737","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/307737","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=307737"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/307737\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=307737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=307737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=307737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}