ฉันต้องการที่จะเข้าใจในระดับพื้นฐานว่า A * pathfinding ทำงานอย่างไร การใช้รหัสหรือรหัส psuedo ใด ๆ รวมถึงการสร้างภาพข้อมูลจะเป็นประโยชน์
ฉันต้องการที่จะเข้าใจในระดับพื้นฐานว่า A * pathfinding ทำงานอย่างไร การใช้รหัสหรือรหัส psuedo ใด ๆ รวมถึงการสร้างภาพข้อมูลจะเป็นประโยชน์
คำตอบ:
มีตัวอย่างโค้ดจำนวนมากและคำอธิบายของ A * ที่สามารถพบได้ทางออนไลน์ คำถามนี้ยังได้รับคำตอบที่ยอดเยี่ยมพร้อมลิงก์ที่มีประโยชน์มากมาย ในคำตอบของฉันฉันจะพยายามแสดงตัวอย่างของอัลกอริทึมซึ่งอาจเข้าใจง่ายกว่าโค้ดหรือคำอธิบาย
เพื่อทำความเข้าใจ A * ฉันขอแนะนำให้คุณดูขั้นตอนวิธีของ Dijkstraก่อน ให้ฉันแนะนำคุณผ่านขั้นตอนวิธีอัลกอริทึมของ Dijkstra จะทำการค้นหา
เริ่มต้นโหนดของเราเป็นและเราต้องการที่จะหาเส้นทางที่สั้นที่สุดA
F
ขอบของกราฟแต่ละอันมีค่าใช้จ่ายในการเคลื่อนที่ (แสดงเป็นตัวเลขสีดำถัดจากขอบ) เป้าหมายของเราคือการประเมินค่าใช้จ่ายการเดินทางน้อยที่สุดสำหรับกราฟแต่ละจุด (หรือโหนด) ของกราฟจนกว่าเราจะไปถึงโหนดเป้าหมายของเรา
นี่คือจุดเริ่มต้นของเรา เรามีลิสต์ของโหนดเพื่อตรวจสอบรายการนี้คือ:
{ A(0) }
A
มีค่าใช้จ่าย0
โหนดอื่น ๆ ทั้งหมดถูกตั้งค่าเป็นอนันต์ (ในการนำไปใช้โดยทั่วไปสิ่งนี้จะคล้ายint.MAX_VALUE
หรือคล้ายกัน)
เรารับโหนดด้วยราคาที่ต่ำที่สุดจากรายการโหนดของเรา (เนื่องจากรายการของเรามีเฉพาะA
นี่คือผู้สมัครของเรา) และเยี่ยมชมเพื่อนบ้านทั้งหมด เรากำหนดค่าใช้จ่ายของแต่ละเพื่อนบ้านเป็น:
Cost_of_Edge + Cost_of_previous_Node
และติดตามโหนดก่อนหน้า (แสดงเป็นตัวอักษรสีชมพูเล็ก ๆ ด้านล่างโหนด) A
สามารถทำเครื่องหมายว่าแก้ไขแล้ว (สีแดง) ได้ในขณะนี้เพื่อที่เราจะไม่ไปดูอีก รายชื่อผู้สมัครของเราตอนนี้มีลักษณะดังนี้:
{ B(2), D(3), C(4) }
อีกครั้งเรานำโหนดที่มีต้นทุนต่ำที่สุดจากรายการของเรา ( B
) และประเมินเพื่อนบ้าน เส้นทางที่จะD
มีราคาแพงกว่าค่าใช้จ่ายในปัจจุบันของD
ดังนั้นเส้นทางนี้สามารถทิ้ง E
จะถูกเพิ่มในรายชื่อผู้สมัครของเราซึ่งตอนนี้มีลักษณะดังนี้:
{ D(3), C(4), E(4) }
D
โหนดต่อไปเพื่อตรวจสอบอยู่ในขณะนี้ การเชื่อมต่อที่C
สามารถยกเลิกได้เนื่องจากเส้นทางไม่สั้นกว่าค่าใช้จ่ายที่มีอยู่ เราพบเส้นทางที่สั้นกว่าE
แต่ค่าใช้จ่ายE
และโหนดก่อนหน้านี้จะได้รับการอัปเดต รายการของเราตอนนี้ดูเหมือนว่านี้:
{ E(3), C(4) }
E
ดังนั้นในขณะที่เราทำมาก่อนเราตรวจสอบโหนดที่มีต้นทุนต่ำจากรายการของเราซึ่งอยู่ในขณะนี้ E
มีหนึ่งเพื่อนบ้านที่ไม่ได้แก้ซึ่งเป็นโหนดเป้าหมายเช่นกัน ค่าใช้จ่ายในการเข้าถึงโหนดเป้าหมายมีการตั้งค่าและโหนดก่อนหน้านี้ในการ10
E
รายชื่อผู้สมัครของเราตอนนี้มีลักษณะดังนี้:
{ C(4), F(10) }
C
ต่อไปเราจะตรวจสอบ F
เราสามารถปรับปรุงค่าใช้จ่ายและโหนดก่อนหน้านี้สำหรับ เนื่องจากรายการของเราตอนนี้มีF
โหนดเป็นค่าใช้จ่ายต่ำสุดที่เราทำ เส้นทางของเราสามารถสร้างได้โดยการย้อนรอยโหนดที่สั้นที่สุดก่อนหน้า
ดังนั้นคุณอาจสงสัยว่าทำไมฉันอธิบาย Dijkstra ให้คุณแทนอัลกอริทึม A * ? ความแตกต่างเพียงอย่างเดียวคือวิธีที่คุณชั่งน้ำหนัก (หรือเรียงลำดับ) ผู้สมัครของคุณ ด้วย Dijkstra มัน:
Cost_of_Edge + Cost_of_previous_Node
ด้วย A * มันคือ:
Cost_of_Edge + Cost_of_previous_Node + Estimated_Cost_to_reach_Target_from(Node)
ที่ไหนEstimated_Cost_to_reach_Target_from
กันทั่วไปจะเรียกว่าHeuristicฟังก์ชั่น นี่คือฟังก์ชั่นที่จะพยายามประมาณการค่าใช้จ่ายเพื่อให้ถึงเป้าหมายโหนด ฟังก์ชั่นการแก้ปัญหาที่ดีจะประสบความสำเร็จได้ว่าจะต้องมีการเยี่ยมชมโหนดน้อยกว่าเพื่อค้นหาเป้าหมาย ในขณะที่อัลกอริธึมของ Dijkstra จะขยายออกไปทุกด้าน A * จะค้นหาด้วยวิธีฮิวริสติกในทิศทางของเป้าหมาย
หน้า Amit เกี่ยวกับการวิเคราะห์พฤติกรรมมีภาพรวมที่ดีเกี่ยวกับการวิเคราะห์พฤติกรรมทั่วไป
การค้นหาเส้นทาง * เป็นการค้นหาประเภทที่ดีที่สุดซึ่งใช้การวิเคราะห์พฤติกรรมเพิ่มเติม
สิ่งแรกที่คุณต้องทำคือแบ่งพื้นที่การค้นหาของคุณ สำหรับคำอธิบายนี้แผนที่เป็นรูปสี่เหลี่ยมจัตุรัสของไทล์เพราะเกม 2D ส่วนใหญ่ใช้กริดของไทล์และเพราะมันง่ายต่อการมองเห็น อย่างไรก็ตามโปรดทราบว่าพื้นที่การค้นหาสามารถแยกย่อยได้ทุกอย่างที่คุณต้องการไม่ว่าจะเป็นกริดฐานสิบหกหรือแม้กระทั่งรูปร่างตามอำเภอใจเช่นความเสี่ยง ตำแหน่งแผนที่ต่างๆเรียกว่า "nodes" และอัลกอริทึมนี้จะทำงานเมื่อใดก็ตามที่คุณมีโหนดจำนวนมากเพื่อสำรวจและกำหนดการเชื่อมต่อระหว่างโหนด
อย่างไรก็ตามเริ่มต้นที่ไทล์เริ่มต้นที่ระบุ:
ไพ่ 8 ใบรอบ ๆ ไพ่เริ่มต้นคือ "คะแนน" ตาม) ค่าใช้จ่ายในการเคลื่อนย้ายจากไทล์ปัจจุบันไปยังไทล์ถัดไป (โดยทั่วไป 1 สำหรับการเคลื่อนไหวในแนวนอนหรือแนวตั้ง
แต่ละไทล์จะได้รับคะแนน "ฮิวริสติก" เพิ่มเติม - การประมาณมูลค่าสัมพัทธ์ของการย้ายไปยังไทล์แต่ละอัน ฮิวริสติกที่แตกต่างกันจะใช้วิธีที่ง่ายที่สุดคือระยะทางเส้นตรงระหว่างจุดกึ่งกลางของไทล์ที่กำหนดและไทล์เอนด์
ไทล์ปัจจุบันคือ "ปิด" และเอเจนต์ย้ายไปที่ไทล์ข้างเคียงที่เปิดอยู่มีคะแนนการเคลื่อนไหวต่ำสุดและคะแนนฮิวริสติกต่ำสุด
กระบวนการนี้จะทำซ้ำจนกว่าจะถึงโหนดเป้าหมายหรือไม่มีโหนดเปิดอีกต่อไป (หมายถึงเอเจนต์ถูกบล็อก)
สำหรับแผนภาพแสดงขั้นตอนเหล่านี้อ้างถึงนี้กวดวิชาเริ่มต้นที่ดีของ
มีการปรับปรุงบางอย่างที่สามารถทำได้ส่วนใหญ่ในการปรับปรุงการแก้ปัญหา:
คำนึงถึงความแตกต่างของภูมิประเทศความหยาบความสูง ฯลฯ
บางครั้งมันก็มีประโยชน์ที่จะทำการ "กวาด" ข้ามเส้นตารางเพื่อสกัดกั้นพื้นที่ของแผนที่ที่ไม่ใช่เส้นทางที่มีประสิทธิภาพเช่นรูปตัว U ที่หันหน้าไปหาตัวแทน หากไม่มีการทดสอบการกวาดตัวเอเจนต์จะเข้าสู่ U ก่อนหันหลังจากนั้นออกไปและเดินไปรอบ ๆ ขอบของเอเจนต์อัจฉริยะที่แท้จริงของแท้จะสังเกตเห็นกับดักรูปตัวยูและหลีกเลี่ยงมัน การกวาดสามารถช่วยจำลองสิ่งนี้
มันไกลจากสิ่งที่ดีที่สุด แต่นี่เป็นการนำไปใช้ที่ฉันทำในA * ใน C ++เมื่อไม่กี่ปีก่อน
มันอาจจะดีกว่าที่ฉันจะชี้ให้คุณไปที่แหล่งข้อมูลมากกว่าความพยายามที่จะอธิบายอัลกอริทึมทั้งหมด นอกจากนี้เมื่อคุณอ่านบทความ wiki ให้เล่นกับตัวอย่างและดูว่าคุณสามารถจินตนาการได้อย่างไรว่ามันทำงานอย่างไร แสดงความคิดเห็นหากคุณมีคำถามเฉพาะ
คุณอาจพบบทความของ ActiveTut ในการค้นหาเส้นทางที่มีประโยชน์ มันครอบคลุมทั้งอัลกอริทึมของ A * และ Dijkstra และความแตกต่างระหว่างพวกเขา มันมุ่งไปที่นักพัฒนา Flash แต่ควรให้ข้อมูลเชิงลึกเกี่ยวกับทฤษฎีที่ดีแม้ว่าคุณจะไม่ใช้ Flash
สิ่งหนึ่งที่สำคัญในการมองเห็นเมื่อต้องรับมือกับอัลกอริทึมของ A * และ Dijkstra คือ A * ถูกนำมาใช้ มันพยายามค้นหาเส้นทางที่สั้นที่สุดไปยังจุดใดจุดหนึ่งโดย "คาดเดา" ซึ่งทิศทางที่จะมอง อัลกอริทึมของ Dijkstra ค้นหาเส้นทางที่สั้นที่สุดไปยัง / ทุกๆ / จุด
ดังนั้นในฐานะที่เป็นแถลงการณ์แรก A * จึงเป็นหัวใจของอัลกอริธึมในการสำรวจกราฟ โดยปกติแล้วในเกมที่เราใช้ทั้งแผ่นกระเบื้องหรือเรขาคณิตโลกอื่นเป็นกราฟ แต่คุณสามารถใช้ A * เพื่อสิ่งอื่น ๆ อัลกอริธึมสองประการสำหรับการสำรวจเส้นทางกราฟคือการค้นหาความลึกครั้งแรกและการค้นหาแบบกว้างแรก ใน DFS คุณจะสำรวจสาขาปัจจุบันของคุณอย่างเต็มที่ก่อนที่จะดูพี่น้องของโหนดปัจจุบันและใน BFS คุณจะต้องดูพี่น้องก่อนและจากนั้นลูก A * พยายามหาจุดกึ่งกลางระหว่างสิ่งเหล่านี้ที่คุณสำรวจสาขา (เช่น DFS) เมื่อคุณเข้าใกล้เป้าหมายที่ต้องการ แต่บางครั้งก็หยุดและลองพี่น้องถ้ามันอาจมีผลดีกว่าสาขา คณิตศาสตร์ที่แท้จริงคือคุณเก็บรายการของโหนดที่เป็นไปได้เพื่อสำรวจถัดไปโดยที่แต่ละอันมี "ความดี" คะแนนที่บ่งบอกว่าใกล้ถึง (ในแง่ของความรู้สึกเชิงนามธรรม) ไปถึงเป้าหมายได้อย่างไรคะแนนที่ลดลงจะดีกว่า (0 หมายถึงคุณพบเป้าหมาย) คุณเลือกสิ่งที่จะใช้ถัดไปโดยค้นหาคะแนนขั้นต่ำรวมถึงจำนวนโหนดที่อยู่ห่างจากรูท (ซึ่งโดยทั่วไปคือการกำหนดค่าปัจจุบันหรือตำแหน่งปัจจุบันในการค้นหาเส้นทาง) แต่ละครั้งที่คุณสำรวจโหนดคุณจะเพิ่มลูกทั้งหมดลงในรายการนี้จากนั้นเลือกโหนดที่ดีที่สุดใหม่
ในระดับนามธรรม A * ทำงานได้ดังนี้: