{"id":21175796,"url":"https://github.com/m3y54m/a-star-algorithm-in-php","last_synced_at":"2026-05-19T18:31:49.229Z","repository":{"id":156140005,"uuid":"384066596","full_name":"m3y54m/a-star-algorithm-in-php","owner":"m3y54m","description":"A* Algorithm Implementation in PHP","archived":false,"fork":false,"pushed_at":"2021-07-08T12:26:52.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-31T07:00:06.946Z","etag":null,"topics":["a-star-algorithm","pathfinding-algorithm","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m3y54m.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-08T09:10:59.000Z","updated_at":"2021-07-19T20:30:18.000Z","dependencies_parsed_at":"2024-04-06T12:45:07.759Z","dependency_job_id":null,"html_url":"https://github.com/m3y54m/a-star-algorithm-in-php","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/m3y54m/a-star-algorithm-in-php","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3y54m%2Fa-star-algorithm-in-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3y54m%2Fa-star-algorithm-in-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3y54m%2Fa-star-algorithm-in-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3y54m%2Fa-star-algorithm-in-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m3y54m","download_url":"https://codeload.github.com/m3y54m/a-star-algorithm-in-php/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3y54m%2Fa-star-algorithm-in-php/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33227390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-19T15:49:41.270Z","status":"ssl_error","status_checked_at":"2026-05-19T15:49:22.917Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a-star-algorithm","pathfinding-algorithm","php"],"created_at":"2024-11-20T17:00:32.588Z","updated_at":"2026-05-19T18:31:49.212Z","avatar_url":"https://github.com/m3y54m.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"A* Algorithm Implementation in PHP\n=================================\n\nThis is translation of the C implementation of A* (https://github.com/m3y54m/a-star-algorithm-in-c) into PHP. Just for fun :)\n\n.. image:: https://github.com/m3y54m/a-star-algorithm-in-php/blob/main/output.png?raw=true\n    :alt: Output of this code in web browser\n\nA very basic and easy to understand implementation of A* algorithm in C that was part of my \"Fundamentals of Programming\" course at the University of Zanjan, Fall 2012.\n\nThe code is written based on this tutorial: https://www.raywenderlich.com/3016-introduction-to-a-pathfinding\n\nI (Meysam Parvizi) translated this tutorial into Persian/فارسی and published it my website (http://tabin.ir).\nNow I decided to publish that article here as the README file of this repository:\n\n.. raw:: html\n\n    \u003cdiv dir=\"rtl\"\u003e\n    \u003ch1\u003eآشنایی با الگوریتم مسیریابی *A\u003c/h1\u003e\n    \u003ch2\u003eمقدمه\u003c/h2\u003e\n    \u003cp\u003eاین مقاله سعی دارد تا الگوریتم *A را که از این پس برای راحتی کار، آن را الگوریتم «آ-ستاره» می نامیم، گام به گام و بر اساس مفاهیم بسیار ابتدایی شرح دهد. ضمناً سعی کرده‌‌‌‌ایم که تنها به حروف و کلمات بسنده نکنیم و از تصاویر و نمودارها نیز برای انتقال مفاهیم کمک بگیریم.\u003c/p\u003e\n    \u003cp\u003eمهم نیست که شما می‌‌‌‌خواهید از کدام زبان برنامه‌‌‌‌نویسی برای پیاده‌‌‌‌سازی این الگوریتم استفاده کنید، کافی است گام به گام با ما پیش بیایید و فقط سعی کنید که الگوریتم «آ-ستاره» را کاملاً دقیق بفهمید.\u003c/p\u003e\n    \u003ch2\u003eگربه‌‌‌‌ی مسیریاب\u003c/h2\u003e\n    \u003cp\u003eتصور کنید که ما یک بازی داریم که در آن گربه‌‌‌‌ای می‌‌‌‌خواهد مسیری را برای رسیدن به یک تکه استخوان پیدا کند.\u003c/p\u003e\n    \u003cp\u003eشاید از خود بپرسید که یک گربه چرا باید به دنبال یک تکه استخوان باشد؟!\u003c/p\u003e\n    \u003cp\u003eخوب! گربه‌‌‌‌ی بازیِ ما بسیار زیرک است و می‌‌‌‌خواهد با جمع کردن استخوان‌‌‌‌ها و دادن آن‌‌‌‌ها به سگ‌‌‌‌ها، از چنگال آن‌‌‌‌ها در امان بماند!\u003c/p\u003e\n    \u003cp\u003eفرض کنید گربه‌‌‌‌ی موجود در شکل زیر می‌‌‌‌خواهد کوتاه‌‌‌‌ترین مسیر برای رسیدن به استخوان را پیدا کند:\u003c/p\u003e\n    \u003cimg class=\"wp-image-295 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A1.png?raw=true\" alt=\"گربه‌‌‌‌ای در جستجوی استخوان\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eمتأسفانه گربه نمی‌‌‌‌تواند مستقیماً از مکان فعلی خود به طرف استخوان حرکت کند، چون در مقابلش یک دیوار قرار دارد و گربه‌‌‌‌ی ما هم برخلاف ارواح نمی‏‌تواند از دیوار عبور کند!\u003c/p\u003e\n    \u003cp\u003eاز طرف دیگر، گربه‌‌‌‌ی ما خیلی تنبل است و دوست دارد که کوتاه‌‌‌‌ترین راه را پیدا کند.\u003c/p\u003e\n    \u003cp\u003eاما چگونه می‌‌‌‌توانیم الگوریتمی بنویسیم که کوتاه‌‌‌‌ترین مسیر بین گربه و استخوان را پیدا کند؟ اینجاست که از «آ-ستاره» کمک می‌‌‌‌گیریم!\u003c/p\u003e\n    \u003ch2\u003eساده کردن حوزه‌‌‌‌ی جستجو\u003c/h2\u003e\n    \u003cp\u003eدر گام نخست باید حوزه‌‌‌‌ی جستجو را به چیزی که مدلسازی ریاضی آن آسان باشد نزدیک کنیم.\u003c/p\u003e\n    \u003cp\u003eمثلاً می‌‌‌‌توانیم حوزه‌‌‌‌ی جستجو را پیکسل‌‌‌‌بندی کنیم؛ اما در شرایط فعلی این کاملاً غیرضروری است و فقط کار ما را سخت می‌‌‌‌کند پس بهتر است به چیز ساده‌‌‌‌تری فکر کنیم مثلاً تقسیم‌‌‌‌بندی صفحه به مربع‌‌‌‌های هم اندازه و تا حد ممکن بزرگ. البته می‌‌‌‌توان واحدهای مختلفی برای تقسیم‌‌‌‌بندی صفحه (مثل مثلث یا شش‌‌‌‌‏ضلعی) به کار برد اما مربع آسان‌‌‌‌ترین و بهترین گزینه‌‌‌‌ای است که می‌‌‌‌توان برای این مسئله انتخاب کرد.\u003c/p\u003e\n    \u003cp\u003eبا این تقسیم‌‌‌‌بندی می‌‌‌‌توانیم حوزه‌‌‌‌ی جستجو را تبدیل به یک آرایه‌‌‌‌ی دو بعدی کنیم که مانند یک نقشه از حوزه‌‌‌‌ی جستجو، همه چیز را در اختیار ما می‌‌‌‌گذارد. مثلاً اگر سطح یک مربع کاشی شده‌‌‌‌ی 25 در 25 را در نظر بگیریم، حوزه‌‌‌‌ی جستجوی ما یک آرایه‌‌‌‌ی دوبعدی متشکل از 625 کاشی مربعی‌‌‌‌شکل خواهد بود. حالا اگر در همین نقشه، بخواهیم از واحد پیکسل استفاده کنیم، حوزه‌‌‌‌ی جستجوی ما تبدیل به یک آرایه‌‌‌‌ی دوبعدی متشکل از 640000 مربع خواهد شد (با این فرض که ابعاد هر کاشی 32×32 پیکسل باشد)!\u003c/p\u003e\n    \u003cp\u003eبهتر است پس از تقسیم‌‌‌‌بندیِ مربعیِ حوزه‌‌‌‌ی جستجو نگاهی به آن بیندازیم که حالا به یک صفحه با (6×7 کاشی =) 42 کاشی مربعی‌‌‌‌شکل تبدیل شده است:\u003c/p\u003e\n    \u003cimg class=\"wp-image-296 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A2.png?raw=true\" alt=\"تقسیم‌‌‌‌بندی مربعی حوزه‌‌‌‌ی جستجو\" width=\"480\" height=\"432\" /\u003e\n    \u003ch2\u003eلیست‌‌‌‌های باز و بسته\u003c/h2\u003e\n    \u003cp\u003eحالاً که حوزه‌‌‌‌ی جستجو را به شکل ساده‌‌‌‌تری درآوردیم، زمان بحث در مورد الگوریتم آ-ستاره رسیده است.\u003c/p\u003e\n    \u003cp\u003eگربه‌‌‌‌ی ما علاوه بر این که تنبل است، حافظه‌‌‌‌ی چندان خوبی هم ندارد، بنابر این ما به دو لیست نیاز داریم:\u003c/p\u003e\n    \u003cp\u003eیکی برای فهرست کردن تمام مربع‌‌‌‌هایی که تصور می‌‌‌‌شود کوتاه‌‌‌‌ترین مسیر را به دست دهند؛ که آن را \u003cstrong\u003eلیست باز (\u003c/strong\u003e\u003cstrong\u003eOpen List\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e می‌‌‌‌نامیم.\u003c/p\u003e\n    \u003cp\u003eدیگری برای فهرست کردن مربع‌‌‌‌هایی که دیگر لازم نیست مورد ارزیابی قرار گیرند که آن را \u003cstrong\u003eلیست بسته (\u003c/strong\u003e\u003cstrong\u003eClosed List\u003c/strong\u003e\u003cstrong\u003e) \u003c/strong\u003eمی‌‌‌‌نامیم.\u003c/p\u003e\n    \u003cp\u003eگربه با اضافه کردن موقعیت فعلی‌‌‌‌اش به لیست بسته، کارش را شروع می‌‌‌‌کند. (ما نقطه‌‌‌‌ی شروع را A می‏‌نامیم.) سپس از میان مربع‌‌‌‌های همسایه‌‌‌‌اش (Adjucent Squares) ، آن‌‌‌‌هایی را که قابل تردد هستند به لیست باز اضافه می‌‌‌‌کند.\u003c/p\u003e\n    \u003cp\u003eاین تصویر نمونه‌‌‌‌ای از چیزی است در بالا بیان شد، البته با این فرض که گربه در محیطی باز و بدون مانع قرار داشته باشد. (مربع‌‌‌‌های با حاشیه‌‌‌‌ی سبزرنگ همان لیستِ باز هستند):\u003c/p\u003e\n    \u003cimg class=\"wp-image-297 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A3.png?raw=true\" alt=\"تمام انتخاب‌های ممکن برای گربه در مکان فعلی\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eحالا گربه باید مشخص کند که کدام یک از این مربع‌‌‌‌ها در کوتاه‌‌‌‌ترین مسیر قرار دارند. اما چگونه؟\u003c/p\u003e\n    \u003cp\u003eخوب، در الگوریتم آ-ستاره این کار با اختصاص دادن امتیاز به هر مربع انجام می‌‌‌‌پذیرد که به آن \u003cstrong\u003eامتیازدهی مسیر (\u003c/strong\u003e\u003cstrong\u003ePath Scoring\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e گفته می‏شود.\u003c/p\u003e\n    \u003ch2\u003eامتیازدهی به مسیر\u003c/h2\u003e\n    \u003cp\u003eما به هر مربع یک امتیاز که حاصل جمع G+H است، اختصاص می‌‌‌‌دهیم:\u003c/p\u003e\n    \u003ch3\u003eG\u003c/h3\u003e\n    \u003cp\u003e‌هزینه‌‌‌‌‌ی حرکت از نقطه‌‌‌‌ی شروع مسیر تا مکان فعلی است. با این حساب برای مربع همسایه‌‌‌‌ی نقطه‌‌‌‌ی A ، این مقدار برابر 1 خواهد بود و هرچقدر که از نقطه‌‌‌‌ی آغازِ حرکت دورتر شویم، مقدار G افزایش خواهد یافت.\u003c/p\u003e\n    \u003ch3\u003eH\u003c/h3\u003e\n    \u003cp\u003eتخمین ما از فاصله‌‌‌‌ی مربعی که اکنون در آن قرار داریم تا نقطه‌‌‌‌ی پایان مسیر (که از این پس آن را نقطه‌ی B می‏‌نامیم) است. این عدد لزوماً مقدار واقعی نیست چون ما هنوز مسیر را نپیموده‌‌‌‌ایم تا مقداد دقیق آن را بفهمیم بلکه فقط یک حدس است.\u003c/p\u003e\n    \u003cp\u003eشاید بپرسید که منظور از ‌\u003cstrong\u003eهزینه\u003c/strong\u003e\u003cstrong\u003e‌\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eی حرکت (\u003c/strong\u003e\u003cstrong\u003eMovement Cost\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e چیست؟ خوب، در این بازی ما بسیار ساده است – صرفاً تعداد مربع‌‌‌‌هایی است که از روی آن‌‌‌‌ها عبور کرده‌‏ایم.\u003c/p\u003e\n    \u003cp\u003eبه هر حال باید به یاد داشته باشید که نحوه‌‌‌‌ی محاسبه‌‌‌‌ی G و H متناسب با شرایط بازی می‌‌‌‌تواند تغییر کند. مثلاً:\u003c/p\u003e\n    \u003cul\u003e\n    \u003cli\u003eاگر شما مجاز به حرکت‌‌‌‌های قطری (اُریب) باشید، باید ‌هزینه‌‌‌‌‌ی حرکت مربوط به حرکت‌‌‌‌های قطری را اندکی بیشتر از حرکت‌‌‌‌های مستقیم (بالا، چپ، پایین و راست) در نظر بگیرید.\u003c/li\u003e\n    \u003cli\u003eاگر در بازی شما عوارض و موانع طبیعی مختلفی وجود دارد باید ‌هزینه‌‌‌‌‌ی حرکت را برای عبور از باتلاق، دریاچه و هر مانعی که عبور از آن مشکل‌‌‌‌تر است، بیشتر در نظر بگیرید.\u003c/li\u003e\n    \u003c/ul\u003e\n    \u003cp\u003eاین‌‌‌‌ها همگی مفاهیم کلّی بودند – حالا وقت دقیق شدن در جزئیات محاسبه‌‌‌‌ی G و H است.\u003c/p\u003e\n    \u003ch2\u003eدرباره‌‌‌‌ی G بیشتر بدانید\u003c/h2\u003e\n    \u003cp\u003eبه یاد بیاورید که G ‌هزینه‌‌‌‌‌ی حرکت (و به طور خاص در بازی ما، تعداد مربع‌‌‌‌های پیموده شده) از نقطه‌‌‌‌ی شروع حرکت یعنی A تا موقعیت کنونی است.\u003c/p\u003e\n    \u003cp\u003eبرای محاسبه‌‌‌‌ی G در یک مکان خاص از مسیر، ما باید G مربوط به موقعیتِ \u003cstrong\u003eوالد (\u003c/strong\u003e\u003cstrong\u003eParent\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e آن (یعنی آخرین مربعی که از آن گذشته‌‌‌‌ایم و به اینجا رسیده‌‌‌‌ایم) را در نظر بگیریم و یک واحد به آن اضافه کنیم. با این دستورالعمل، G مربوط به هر مربع، تعداد مربع‌‌‌‌هایی است که از نقطه‌‌‌‌ی شروع یعنی A تا موقعیت کنونی از روی آن‌‌‌‌ها عبور کرده‌‌‌‌ایم.\u003c/p\u003e\n    \u003cp\u003eبه عنوان مثال، نمودار زیرین دو مسیر متفاوت را به سوی دو تکه استخوان متفاوت نشان می‌‌‌‌دهد که مقادیر G مربوط به هر مربع موجود در مسیر روی خود آن مربع نوشته شده است:\u003c/p\u003e\n    \u003cimg class=\"wp-image-298 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A4.png?raw=true\" alt=\"مقادیر متوالی G در دو مسیر مختلف\" width=\"480\" height=\"432\" /\u003e\n    \u003ch2\u003eدرباره‌‌‌‌ی H بیشتر بدانید\u003c/h2\u003e\n    \u003cp\u003eبه یاد بیاورید که H ‌هزینه‌‌‌‌‌ی حرکت تخمینی (یعنی تعداد مربع‌‌‌‌های باقیمانده) از موقعیت فعلی تا نقطه‌‌‌‌ی پایان مسیر یعنی B است.\u003c/p\u003e\n    \u003cp\u003eهر چقدر که ‌هزینه‌‌‌‌‌ی حرکت تخمینی به اندازه‌‌‌‌ی واقعی نزدیک‌‌‌‌تر باشد، مسیر نهایی درست‌‌‌‌تر خواهد بود. اگر این مقدار تخمینی مورد استفاده قرار نگیرد، ممکن است مسیر نهایی کوتاه‌‌‌‌ترین مسیر نباشد (البته شاید نزدیک به آن باشد). این موضوع بسیار پیچیده است و از این رو در این مقاله پوشش داده نخواهد شد.\u003c/p\u003e\n    \u003cp\u003eبرای این که کارمان را ساده کنیم از \u003cstrong\u003eروش فاصله\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eی منهتن (\u003c/strong\u003e\u003cstrong\u003eManhattan distance method\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e که با نام‌‌‌‌های \u003cstrong\u003eطول منهتن (\u003c/strong\u003e\u003cstrong\u003eManhattan Length\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e یا \u003cstrong\u003eفاصله\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eی بلوک شهری (\u003c/strong\u003e\u003cstrong\u003eCity block distance\u003c/strong\u003e\u003cstrong\u003e)\u003c/strong\u003e هم شناخته می‌‌‌‌شود استفاده می‌‌‌‌کنیم. در این روش بدون در نظر گرفتن موانع و عوارض طبیعی موجود در مسیر، فقط فاصله‌‌‌‌ی افقی و عمودی از نقطه‌‌‌‌ی فعلی تا رسیدن به نقطه‌‌‌‌ی نهایی یعنی B را در نظر می‏‌گیریم.\u003c/p\u003e\n    \u003cp\u003eبه عنوان مثال، تصویر زیر چگونگی استفاده از «فاصله‌‌‌‌ی بلوکی» را در محاسبه‌‌‌‌ی H نشان می‌‌‌‌دهد (که مقدار آن با رنگ سیاه در مربع مربوطه نوشته شده است):\u003c/p\u003e\n    \u003cimg class=\"wp-image-299 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A5.png?raw=true\" alt=\"تخمین مقدار H با روش فاصله بلوکی\" width=\"480\" height=\"432\" /\u003e\n    \u003ch2\u003eالگوریتم آ-ستاره\u003c/h2\u003e\n    \u003cp\u003eحالا که متوجه شدید چگونه باید امتیاز هر مربع را محاسبه کنیم (که از این به بعد آن را F می‌‌‌‌نامیم و برابر با G+H است)، وقت آن است که ببینیم الگوریتم آ-ستاره چگونه کار می‌‌‌‌کند.\u003c/p\u003e\n    \u003cp\u003eگربه‌‌‌‌ی ما کوتاه‌‌‌‌ترین مسیر را با تکرار کردن مراحل زیر پیدا خواهد کرد:\u003c/p\u003e\n    \u003col\u003e\n    \u003cli\u003e\u003cstrong\u003e مربعی که کم\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eترین امتیاز را در لیست باز دارد را در نظر می\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eگیریم. از این پس این مربع را \u003c/strong\u003e\u003cstrong\u003eS\u003c/strong\u003e\u003cstrong\u003e می\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eنامیم.\u003c/strong\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cstrong\u003eS\u003c/strong\u003e\u003cstrong\u003e را از لیست باز حذف می\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eکنیم و به لیست بسته اضافه می\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eکنیم.\u003c/strong\u003e\u003c/li\u003e\n    \u003cli\u003e\u003cstrong\u003e به ازای هر مربعِ \u003c/strong\u003e\u003cstrong\u003eT\u003c/strong\u003e\u003cstrong\u003e که در همسایگی \u003c/strong\u003e\u003cstrong\u003eS\u003c/strong\u003e\u003cstrong\u003e قرار دارد:\u003c/strong\u003e\u003c/li\u003e\n    \u003cli\u003eاگر T در لیستِ بسته است: آن را نادیده بگیر. (کاری به کارش نداشته باش.)\u003c/li\u003e\n    \u003cli\u003eاگر T در لیستِ باز نیست: آن را به لیست باز اضافه کن و امتیازش (F) را محاسبه کن.\u003c/li\u003e\n    \u003cli\u003eاگر T در لیستِ باز است: بررسی کن که با در نظر گرفتن S به عنوان موقعیت والد و محاسبه‌‌‌‌ی مجددِ G ، آیا امتیازِ F آن کاهش می‌‌‌‌یابد؟ اگر پاسخ مثبت است، امتیاز آن را به روز کن و موقعیتِ والد آن را نیز به روز کن.\u003c/li\u003e\n    \u003c/ol\u003e\n    \u003cp\u003eاگر هنوز هم کمی سردرگم هستید، نگران نباشید چون از این پس با یک مثال و گام به گام پیش خواهیم رفت تا نحوه‌‌‌‌ی عملکرد این الگوریتم را عیناً مشاهده کنید!\u003c/p\u003e\n    \u003ch2\u003eمسیر گربه\u003c/h2\u003e\n    \u003cp\u003eبگذارید با همان مثالِ گربه‌‌‌‌ی تنبل خودمان و مسیرش به سوی تکه استخوان پیش برویم.\u003c/p\u003e\n    \u003cp\u003eدر نمودارهای زیر، مقادیرِ F = G + H مطابق با نکات زیر داخل هر مربع نوشته شده‌‌‌‌اند:\u003c/p\u003e\n    \u003cp\u003e\u003cstrong\u003eF\u003c/strong\u003e\u003cstrong\u003e (امتیاز مربع مربوطه): گوشه\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eی چپ و بالا\u003c/strong\u003e\u003c/p\u003e\n    \u003cp\u003e\u003cstrong\u003eG\u003c/strong\u003e\u003cstrong\u003e (مسافت پیموده شده از \u003c/strong\u003e\u003cstrong\u003eA\u003c/strong\u003e\u003cstrong\u003e تا مربع مربوطه): گوشه\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eی چپ و پایین\u003c/strong\u003e\u003c/p\u003e\n    \u003cp\u003e\u003cstrong\u003eH\u003c/strong\u003e\u003cstrong\u003e (مسافت تخمینی از مربع مربوطه تا \u003c/strong\u003e\u003cstrong\u003eB\u003c/strong\u003e\u003cstrong\u003e): گوشه\u003c/strong\u003e\u003cstrong\u003e‌‌‌‌\u003c/strong\u003e\u003cstrong\u003eی راست و پایین\u003c/strong\u003e\u003c/p\u003e\n    \u003cp\u003eهمچنین، پیکان‌‌‌‌های موجود در هر مربع، جهت حرکتی که برای رفتن به آن مربع نیاز است را نشان می‌‌‌‌دهد.\u003c/p\u003e\n    \u003cp\u003eدر نهایت، در هر مرحله، مربع‌‌‌‌های سرخ‌‌‌‌رنگ نشان دهنده‌‌‌‌ی موارد موجود در \u003cstrong\u003eلیست بسته\u003c/strong\u003e هستند و مربع‌‌‌‌های سبزرنگ نشان دهنده‌‌‌‌ی موارد موجود در \u003cstrong\u003eلیست باز\u003c/strong\u003e هستند.\u003c/p\u003e\n    \u003cp\u003eبسیار خوب، حالا شروع می‌‌‌‌کنیم:\u003c/p\u003e\n    \u003ch3\u003eگام اوّل\u003c/h3\u003e\n    \u003cp\u003eدر گام اوّل، گربه‌‌‌‌ی ما از میان مربع‌‌‌‌های مجاورِ مکان کنونی یعنی A ، مربع‌‌‌‌هایی را که مسدود نیستند شناسایی کرده و امتیازِ F آن‌‌‌‌ها را محاسبه می‌‌‌‌کند و سپس آن‌‌‌‌ها را به لیست باز اضافه می‌‌‌‌کند:\u003c/p\u003e\n    \u003cimg class=\"wp-image-300 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A6.png?raw=true\" alt=\"گام اول\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eدر شکل بالا می‏‌ببینید که مقدار H برای هر مربع نوشته شده است (دو تا از آن‌‌‌‌ها 6 هستند و یکی 4). من پیشنهاد می‌‌‌‌کنم که از همان روش شمارش مربع‌‌‌‌ها با توجه به «فاصله‌‌‌‌ی بلوکی» استفاده کنید تا متوجه شوید که چگونه H را محاسبه کرده‏ایم.\u003c/p\u003e\n    \u003cp\u003eهمچنین توجه داشته باشید که مقدارِ F (در گوشه‌‌‌‌ی چپ و بالا) صرفاً حاصل جمع G+H است (که در گوشه‌‌‌‌های پایینی نوشته شده‌‌‌‌اند.)\u003c/p\u003e\n    \u003ch3\u003eگام دوم\u003c/h3\u003e\n    \u003cp\u003eدر گام بعدی، گربه‌‌‌‌ی ما مربعی که کم‌‌‌‌ترین مقدار F را دارد، انتخاب کرده و آن را به لیست بسته اضافه می‌‌‌‌کند، از لیست باز حذف می‌‌‌‌کند و مربع‌‌‌‌های مجاور این مربع جدید (که کم‌‌‌‌ترین F را داشته است) را شناسایی می‌‌‌‌کند.\u003c/p\u003e\n    \u003cimg class=\"wp-image-301 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A7.png?raw=true\" alt=\"گام دوم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eمربعی که کمترین امتیاز را دارد همان مربعی است که مقدارِ F آن برابر 5 است. گربه تلاش می‌‌‌‌کند که تمام مربع‌‌‌‌های مجاور را به لیستِ باز اضافه کند (و امتیاز آن‌‌‌‌ها را محاسبه کند)، اما باید توجه داشته باشید که او نمی‌‌‌‌تواند مکان قبلی خودش را (که هم اکنون در لیستِ بسته قرار دارد) یا موانع موجود در مسیر مانند مربع‌‌‌‌های هاشور خورده را (که قابل تردد نیستند) به لیست باز اضافه کند.\u003c/p\u003e\n    \u003cp\u003eتوجه کنید که برای مربع‌‌‌‌های جدیدی که به لیست باز افزوده می‌‌‌‌شوند، مقدارِ G به اندازه‌‌‌‌ی یک واحد افزایش پیدا می‌‌‌‌کند چون این مربع‌‌‌‌ها به اندازه‏ی 2 کاشی با نقطه‌‌‌‌ی شروع فاصله دارند. برای اطمینان از مقدار H هم می‌‌‌‌توانید از شمارش «فاصله‌‌‌‌ی بلوکی» استفاده کنید.\u003c/p\u003e\n    \u003ch3\u003eگام سوم\u003c/h3\u003e\n    \u003cp\u003eدوباره مربعی که کمترین مقدار F (یعنی 5) را داراست انتخاب کرده و روند پیشین را تکرار می‌‌‌‌کنیم:\u003c/p\u003e\n    \u003cimg class=\"wp-image-302 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A8.png?raw=true\" alt=\"گام سوم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eدر این مرحله تنها یک کاشی می‌‌‌‌تواند به لیست باز اضافه شود، چون دوتا از کاشی‌‌‌‌های همسایه مسدود هستند و یکی هم در لیستِ بسته قرار دارد.\u003c/p\u003e\n    \u003ch3\u003eگام چهارم\u003c/h3\u003e\n    \u003cp\u003eحالا با یک وضعیت جالب مواجه شده‌‌‌‌ایم. همان‌‌‌‌گونه که در گام سوم مشاهده کردید، 4 مربع با مقدارِ F یکسان (یعنی 7) موجودند؛ الآن چه باید کرد؟!\u003c/p\u003e\n    \u003cp\u003eراه حل‌‌‌‌های مختلفی برای این وضعیت وجود دارد اما ساده‌‌‌‌ترین و در عین حال سریع‌‌‌‌ترین راه این است که آخرین مربعی که به لیستِ باز اضافه شده است را برای حرکت بعدی انتخاب کنیم:\u003c/p\u003e\n    \u003cimg class=\"wp-image-303 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A9.png?raw=true\" alt=\"گام چهارم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eاین بار دو کاشی قابل تردد در همسایگی وجود دارند که امتیاز آن‌‌‌‌ها را حساب می‌‌‌‌کنیم.\u003c/p\u003e\n    \u003ch3\u003eگام پنجم\u003c/h3\u003e\n    \u003cp\u003eدوباره مربعی که کمترین مقدار F (یعنی 7) را داراست و آخر از همه به لیستِ باز افزوده شده است انتخاب می‌‌‌‌کنیم:\u003c/p\u003e\n    \u003cimg class=\"wp-image-304 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A10.png?raw=true\" alt=\"گام پنجم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eدر این مرحله فقط یک مربعِ قابلِ تردد به لیست باز اضافه می‌‌‌‌شود. کم کم به استخوان نزدیک می‌‌‌‌شویم!\u003c/p\u003e\n    \u003ch3\u003eگام ششم\u003c/h3\u003e\n    \u003cp\u003eدیگر خودتان روند کار را یاد گرفته‌‌‌‌اید! مطمئنم که می‌‌‌‌توانید گام بعدی را حدس بزنید:\u003c/p\u003e\n    \u003cimg class=\"wp-image-305 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A11.png?raw=true\" alt=\"گام ششم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eتقریباً رسیده‌‌‌‌ایم، امّا این بار مشاهده می‌‌‌‌کنید که دو مسیر وجود دارد که هر دو طول یکسانی دارند و کوتاه‌‌‌‌ترین مسیر هستند.  می‌‌‌‌توانیم یکی از آن‌‌‌‌ها را انتخاب کنیم تا به استخوان برسیم:\u003c/p\u003e\n    \u003cimg class=\"wp-image-306 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A12.png?raw=true\" alt=\"دو مسیر متفاوت با طول یکسان\" width=\"479\" height=\"432\" /\u003e\n    \u003cp\u003eدر مثال ما 2 مسیر مختلف به عنوان کوتاه‌‌‌‌ترین مسیر وجود دارند:\u003c/p\u003e\n    \u003cp\u003e6 – 5 – 4 – 3 – 2 – 1\u003c/p\u003e\n    \u003cp\u003e7 – 5 – 4 – 3 – 2 – 1\u003c/p\u003e\n    \u003cp\u003eفرقی نمی‌‌‌‌کند که کدام‌‌‌‌یک از آن‌‌‌‌ها را انتخاب کنیم، این موضوع باید در پیاده‌سازی الگوریتم هنگام کدنویسی در نظر گرفته شود.\u003c/p\u003e\n    \u003ch3\u003eگام هفتم\u003c/h3\u003e\n    \u003cp\u003eبگذارید مسیر را از طریق یکی از این دو مربع ادامه دهیم:\u003c/p\u003e\n    \u003cimg class=\"wp-image-307 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A13.png?raw=true\" alt=\"گام هفتم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eحالا استخوان در لیستِ باز است!\u003c/p\u003e\n    \u003ch3\u003eگام هشتم\u003c/h3\u003e\n    \u003cp\u003eدر وضعیتی که استخوان (نقطه‌‌‌‌ی مقصد) در لیست باز قرار گیرد، الگوریتم آن را به لیستِ بسته اضافه می‌‌‌‌کند:\u003c/p\u003e\n    \u003cimg class=\"wp-image-308 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A14.png?raw=true\" alt=\"گام هشتم\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eسپس تنها کاری که الگوریتم باید انجام دهد این است به عقب برگردد و مسیر نهایی را شناسایی کند.\u003c/p\u003e\n    \u003cimg class=\"wp-image-309 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A15.png?raw=true\" alt=\"مسیر نهایی\" width=\"480\" height=\"432\" /\u003e\n    \u003ch2\u003eیک گربه‌‌‌‌ی معمولی\u003c/h2\u003e\n    \u003cp\u003eدر مثال فوق، ما می‌‌‌‌بینیم که وقتی گربه به دنبال کوتاه‌‌‌‌ترین مسیر می‌‌‌‌گشت، غالباً بهترین مربع را انتخاب می‌‌‌‌کرد (آن مربعی که در راستای کوتاه‌‌‌‌ترین مسیرِ آینده‌‌‌‌اش قرار داشت) – گویا گربه‌‌‌‌ی ما می‏‌توانست آینده را پیش‏بینی کند.\u003c/p\u003e\n    \u003cp\u003eاما چه می‌‌‌‌شد اگر گربه‌‌‌‌ی ما نمی‌‌‌‌توانست آینده را ببیند و همواره اوّلین مربعی را که به لیست اضافه می‌‌‌‌شد انتخاب می‌‌‌‌کرد؟\u003c/p\u003e\n    \u003cp\u003eشکل زیر نشان می‌‌‌‌دهد که اگر چنین فرایندی را طی می‌‌‌‌کردیم باید چه مربع‌‌‌‌هایی را مورد بررسی قرار می‌‌‌‌دادیم. شما مشاهده می‌‌‌‌کنید که در این حالت گربه‌‌‌‌ی ما مربع‌‌‌‌های بیشتری را امتحان می‌‌‌‌کند، امّا باز هم کوتاه‌‌‌‌ترین مسیر را پیدا می‌‌‌‌کند (نه دقیقاً همان مسیری که قبلاً پیدا کرده بود امّا مسیر دیگری با طول یکسان پیدا می‌‌‌‌کند):\u003c/p\u003e\n    \u003cimg class=\"wp-image-310 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A16.png?raw=true\" alt=\"پیدا کردن مسیر بدون انتخاب بهترین مربع‌ها\" width=\"479\" height=\"432\" /\u003e\n    \u003cp\u003eمربع‌‌‌‌های سرخ‌‌‌‌رنگ در نمودار فوق لزوماً کوتاه‌‌‌‌ترین مسیر را نشان نمی‌‌‌‌دهند، آن‌‌‌‌ها فقط مربع‌‌‌‌هایی را نشان می‌‌‌‌دهند که در مراحل مختلف به عنوانِ مربعِ S در نظر گرفته شده‌‌‌‌اند.\u003c/p\u003e\n    \u003cp\u003eمن توصیه می‌‌‌‌کنم که به نمودار بالایی نگاه کنید و سعی کنید که همگام با آن پیش بروید. این بار در هر چندراهی، «بدترین» مسیر را برای رفتن انتخاب کنید. خواهید دید که باز هم با پیمودن کوتاه‌‌‌‌ترین مسیر به انتها می‌‌‌‌رسید!\u003c/p\u003e\n    \u003cp\u003eشما می‌‌‌‌بینید که اگر مربعِ «اشتباه» را دنبال کنید، مشکلی پیش نمی‌‌‌‌آید و شما با کوتاه‌‌‌‌ترین مسیر به انتها می‌‌‌‌رسید هرچند که باید روند الگوریتم را بیشتر تکرار کنید.\u003c/p\u003e\n    \u003cp\u003eدر هنگام اجرای الگوریتم، مربع‌‌‌‌ها را با توجه به الگوریتم زیر به لیستِ باز اضافه می‌‌‌‌کنیم:\u003c/p\u003e\n    \u003cp\u003eمربع‌‌‌‌های همسایه به این ترتیب در نظر گرفته می‌‌‌‌شوند:\u003c/p\u003e\n    \u003cp\u003e\u003cstrong\u003eبالا / چپ / پایین / راست\u003c/strong\u003e (البته شما می‌توانید ترتیب دیگری انتخاب کنید!)\u003c/p\u003e\n    \u003cp\u003eیک مربع پس از تمام مربع‌‌‌‌هایی که امتیاز یکسانی با آن دارند به لیستِ باز افزوده می‌‌‌‌شود (بنابر این اوّلین مربعی که اضافه می‌‌‌‌شود اولّین مربعی است که گربه انتخاب می‌‌‌‌کند).\u003c/p\u003e\n    \u003cp\u003eاین یک نمودار برای عقب‌‌‌‌گرد و بازخوانی مسیر است:\u003c/p\u003e\n    \u003cimg class=\"wp-image-311 size-full\" src=\"https://github.com/m3y54m/a-star-algorithm-in-c/blob/main/images/A17.png?raw=true\" alt=\"بازخوانی مسیر\" width=\"480\" height=\"432\" /\u003e\n    \u003cp\u003eکوتاه‌‌‌‌ترین مسیر با شروع از نقطه‌‌‌‌ی مقصد و عقب رفتن از یک مربع والد به مربع والد دیگر ساخته می‌‌‌‌شود (مثلاً: در مربعِ مقصد می‌‌‌‌بینیم که پیکانِ داخلِ آن به سمت راست است پس مربعِ والد آن در سمت چپ قرار دارد).\u003c/p\u003e\n    \u003cp\u003eبرای نتیجه‌‌‌‌گیری می‌‌‌‌توانیم فرایندی را که گربه طی می‌‌‌‌کند در قالب کد زیر خلاصه کنیم. کدهای زیر به زبان Objective-C هستند، امّا شما می‌‌‌‌توانید آن‌‌‌‌ها را به راحتی به هر زبان دیگری ترجمه کنید:\u003c/p\u003e\n    \u003c/div\u003e\n    \n.. code-block:: objective-c\n \n    [openList add:originalSquare]; // start by adding the original position to the open list\n\n    do {\n        currentSquare = [openList squareWithLowestFScore]; // Get the square with the lowest F score\n        [closedList add:currentSquare]; // add the current square to the closed list\n        [openList remove:currentSquare]; // remove it to the open list\n\n        if ([closedList contains:destinationSquare]) { // if we added the destination to the closed list, we've found a path\n                // PATH FOUND\n                break; // break the loop\n        }\n\n        adjacentSquares = [currentSquare walkableAdjacentSquares]; // Retrieve all its walkable adjacent squares\n\n        foreach (aSquare in adjacentSquares) {\n                if ([closedList contains:aSquare]) { // if this adjacent square is already in the closed list ignore it\n                        continue; // Go to the next adjacent square\n                }\n\n                if (![openList contains:aSquare]) { // if its not in the open list\n                        // compute its score, set the parent\n                        [openList add:aSquare]; // and add it to the open list\n                } else { // if its already in the open list\n                        // test if using the current G score make the aSquare F score lower, if yes update the parent because it means its a better path\n                }\n        }\n    } while(![openList isEmpty]); // Continue until there is no more available square in the open list (which means there is no path)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm3y54m%2Fa-star-algorithm-in-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm3y54m%2Fa-star-algorithm-in-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm3y54m%2Fa-star-algorithm-in-php/lists"}