Tải bản đầy đủ (.pdf) (46 trang)

Đề tài xây dựng game giải mê cung dùng các thuật toán trong việc tìm đường đi tối ưu

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.62 MB, 46 trang )

<span class="text_page_counter">Trang 1</span><div class="page_container" data-page="1">

<b>TRƯỜNG ĐH SƯ PHẠM KỸ THUẬT TP. HỒ CHÍ MINHKHOA CƠNG NGHỆ THƠNG TIN</b>

<b>TIỂU LUẬN CUỐI KỲ Mơn học: TRÍ TUỆ NHÂN TẠO</b>

<b>ĐỀ TÀI: XÂY DỰNG GAME GIẢI MÊ CUNGDÙNG CÁC THUẬT TỐN TRONG VIỆC TÌM</b>

<b>ĐƯỜNG ĐI TỐI ƯU</b>

Giảng viên: PGS.TS. Hoàng Văn Dũng

<b>Danh sách sinh viên thực hiện</b>

</div><span class="text_page_counter">Trang 2</span><div class="page_container" data-page="2">

<b>MỤC LỤC</b>

<b>PHẦN 1. MỞ ĐẦU... 1</b>

<b>1.1.Lời nói đầu...1</b>

<b>1.2.Phát biểu bài tốn...1</b>

<b>1.3.Mục đích, u cầu cần thực hiện...2</b>

<b>2.4.2.Mô tả trong code...6</b>

<b>2.5.Giải thuật UCS...8</b>

<b>2.5.1.Ý tưởng...8</b>

<b>2.5.2.Mô tả trong code...8</b>

<b>2.6.Giải thuật Greedy Search...10</b>

<b>2.6.1.Ý tưởng...10</b>

<b>2.6.2.Mô tả trong code...10</b>

<b>2.7.Giải thuật A*...12</b>

<b>2.7.1.Ý tưởng...12</b>

<b>2.7.2.Mô tả trong code...13</b>

<b>2.8.Giải thuật ID...14</b>

<b>2.8.1.Ý tưởng...14</b>

<b>2.8.2.Mô tả trong code...14</b>

<b>2.9.Giải thuật Beam Search...16</b>

<b>2.9.1.Ý tưởng...16</b>

<b>2.9.2.Mô tả trong code...16</b>

</div><span class="text_page_counter">Trang 3</span><div class="page_container" data-page="3">

<b>PHẦN 3. PHÂN TÍCH, THIẾT KẾ GIẢI PHÁP...19</b>

<b>3.1.Phân tích...19</b>

<b>3.2.Thiết kế giao diện...20</b>

<b>3.1.1.Giao diện trang chủ...20</b>

<b>3.1.2.Giao diện người chơi...21</b>

<b>3.1.3.Giao diện AI...22</b>

<b>4.3.Thuật toán UCS...27</b>

<b>4.4.Thuật toán Greedy...28</b>

<b>4.5.Thuật toán A*...29</b>

<b>4.6.Thuật toán ID...30</b>

<b>4.7.Thuật toán Beam...31</b>

<b>4.8.Phân tích chi phí cho nhiều map và trung bình...31</b>

<b>4.9.Đánh giá kết quả các thuật toán...35</b>

</div><span class="text_page_counter">Trang 4</span><div class="page_container" data-page="4">

<b>DANH MỤC HÌNH ẢNH</b>

Hình 1. Code cho thuật tốn BFS...5

Hình 2. Code cho thuật tốn DFS...7

Hình 3. Code cho thuật tốn UCS...9

Hình 4. Code cho thuật tốn Greedy...11

Hình 5. Code cho thuật tốn Astar...14

Hình 6. Code cho thuật tốn ID...16

Hình 7. Code cho thuật tốn Beam...18

Hình 8. Giao diện trang chủ...20

Hình 9. Giao diện chế độ người chơi...21

Hình 10. Giao diện chế độ AI chơi...22

Hình 11. Vẽ bản đồ...23

Hình 12. Dừng khẩn cấp...24

Hình 13. Demo thuật tốn BFS...25

Hình 14. Demo thuật tốn DFS...26

Hình 15. Demo thuật tốn UCS...27

Hình 16. Demo thuật tốn Greedy...28

Hình 17. Demo thuật tốn A*...29

Hình 18. Demo thuật tốn ID...30

Hình 19. Demo thuật tốn Beam...31

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="6">

<b>DANH MỤC BIỂU ĐỒ</b>

Biểu đồ 1. Biểu đồ cột so sánh số nút duyệt giữa các thuật toán...32

Biểu đồ 2. Biểu đồ cột so sánh số bước di chuyển giữa các thuật toán...33

Biểu đồ 3. Biểu đồ cột so sánh thời gian chạy giữa các thuật toán...34

Biểu đồ 4. Biểu đồ so sánh tổng hợp các thuật toán...35

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

<b>DANH MỤC CÁC TỪ VIẾT TẮT</b>

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="8">

<b>PHẦN 1. MỞ ĐẦU1.1 Lời nói đầu</b>

Ngày nay cùng với sự phát triển về khoa học và kỹ thuật là sự phát triển mạnh mẽ của nền công nghệ thông tin. Trong cơng nghiệp, nghiên cứu khoa học thì cơng nghệ thơng tin đống vai trị rất quan trong trong sự phát triển của đât nước cũng như toàn thế giới

Trên thế giới cũng như ở Việt Nam, công nghệ thông tin đã trở thành một ngày công nghiệp mũi nhọn, nó là một ngày khoa học kỹ thuật khơng thể thiếu trong việc áp dụng vào các hoạt động xã hội và khoa học. Nền công nghiệp hiện nay mang tính chất tự động hóa cao kèm theo đó là sự địi hỏi về việc ứng dụng cơng nghệ thơng tin cho lĩnh vực này. Vậy để có thể đáp ứng tốt những yêu cầu của ngày càng cao hơn trong lĩnh vực tự động hóa người ta đã tiến hành lập trình cho những cỗ máy, những người máy có thể tư duy như con người nhằm giảm bớt các gánh nặng cơng việc. Việc ứng dụng trí tuệ nhân tạo đã tạo ra một cuộc cách mạng lớn trong việc tìm hiểu và chinh phục những điều mà con người khơng dám mơ tới. Đó là những robot thơng minh, những cỗ máy thơng minh có thể thay thế con người làm việc trong những môi trường khắc nghiệt hay chinh phục không gian bao la.Và bên cạnh đó là việc ứng dụng những thành tựu đó vào lĩnh vực giải trí của con người. Đó là những con vật robot, những trị chơi. Đó là những ứng dụng lớn lao của trí tuệ nhân tạo vào của sống của con người.

Trong bài tập lớn này chúng em sử dụng những thuật toán đã học cùng với giao diện trực quan mô tả cách thức hoạt động của các thuật toán AI để sinh viên dể dàng hiểu được cũng như vận dụng chúng cho chính cơng việc của họ sau này.

Mặc dù rất cố gắng để hồn thành cơng việc, xong thời gian có hạn và kiến thức chưa nhiều nên việc chương trình cịn nhiều thiếu sót cần được bổ xung. Vì vậy chúng em mong nhận được những đóng góp của thầy cơ và bạn bè để chương trình ngày càng hồn thiện hơn và giúp ích được nhiều hơn.

<small>1</small>

</div><span class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

<b>1.2 Phát biểu bài toán</b>

Bài toán đặc ra là dùng các giải thuật đã học trong trí tuệ nhân tạo để giải mã một mê cung và tìm đường đi đến vị trí chìa khóa và vị trí cửa cuối cùng.

<b>1.3 Mục đích, yêu cầu cần thực hiện</b>

Mục đích của đề tài này là dùng giao diện trực quan mô tả q q trình giải mã các thuật tốn AStar, Breadth First Search, Depth First Search, Uniform-Cost Search, Greedy Search, Iterative Deepening Search, Beam Search đồng thời tính tốn thời gian thực thi của từng thuật tốn cho từng khơng gian trạng thái khác nhau.

Bài tốn tìm đường đi trong một mê cung dùng để mô phỏng đánh giá các thuật toán trong việc giải mã các mê cung khác nhau, từ đó đưa ra nhận xét và kết luận về việc giải mã mê cung, đánh giá không gian trạng thái cũng như tính tốn thời gian thực hiện thuật tốn để xác định với mỗi khơng gian trạng thái khác nhau thì ta cần sử dụng thuật tốn nào để tối ưu hóa nhất có thể. Đồ án học phần này có giá trị như một phần mơ phỏng phục vụ cho mục đích giáo dục sau này.

</div><span class="text_page_counter">Trang 10</span><div class="page_container" data-page="10">

<b>PHẦN 2. CƠ SỞ LÝ THUYẾT</b>

<b>2.1 Môi trường lập trình</b>

Với bài tập lớn này chúng em sử dụng Python làm ngơn ngữ chính để viết code với trình soạn thảo code Visual Studio Code và trình biên dịch spyder (anaconda3)

<b>2.2 Thư viện chính sử dụng</b>

Thư viện chính được nhóm chúng em sử dụng là pygame. Đây là thư viện mã nguồn mở trên ngôn ngữ Python dùng để lập trình video game. Pygame chứa đầy đủ các cơng cụ hỗ trợ lập trình game như đồ họa, hoạt hình, âm thanh, và sự kiện điều khiển. Pygame cũng đồng thời cung cấp các cơng cụ tích hợp hiệu ứng âm thanh cũng như nhạc nền cho game. Cuối cùng, các sự kiện điều khiển từ bàn phím, chuột cũng được Pygame hỗ trợ một cách hiệu quả.

Trong đề tài này, nhóm chúng em sử dụng Pygame để xây dựng giao diện và mơ phỏng chuyển động thuật tốn.

Đầu mỗi file, khai báo thư viện pygame qua câu lệnh <b>‘import pygame’</b>.

<b>2.3 Giải thuật BFS</b>

Thuật toán <b>duyệt đồ thị ưu tiên chiều rộng </b>là thuật tốn tìm kiếm mù mà những đỉnh gần với đỉnh gốc sẽ được duyệt trước.

<b>2.3.1. Ý tưởng</b>

Với đồ thị không trọng số và đỉnh nguồn . Đồ thị này có thể là đồ thị có hướng hoặcs vơ hướng, điều đó khơng quan trọng đối với thuật toán.

Đầu tiên ta thăm đỉnh nguồn .s

Việc thăm đỉnh sẽ phát sinh thứ tự thăm các đỉnh (u1 , u2 ,…up) kề với s s (những đỉnh gần nhất). Tiếp theo, ta thăm đỉnh u1, khi thăm đỉnh u1 sẽ lại phát sinh yêu cầus thăm những đỉnh (v1, v2, …, vp) kề với u1. Nhưng rõ ràng những đỉnh này “xa” v s hơn những đỉnh uu nên chúng chỉ được thăm khi tất cả những đỉnh uu đều đã được thăm. Tức là thứ tự thăm các đỉnh sẽ là: , u1 , u2, …, up , v1, v2, …, vp.s

<small>3</small>

</div><span class="text_page_counter">Trang 11</span><div class="page_container" data-page="11">

<b>2.3.2. Mô tả trong code</b>

<small>def bfs(GUI Grid start end, , , ): came_from.pop(start) returncame_from, count</small>

<small> fornei inGrid.neighbors[flat(current, Grid.size)]: ifnei incame_from):</small>

<small> ifcame_from[nei] not incame_from): came_from[nei] current else:</small>

<small> came_from[nei] current</small>

<small> ifneinot in states_history: count+=1</small>

<small> states.append((count, nei)) states_history.add(nei)</small>

</div><span class="text_page_counter">Trang 12</span><div class="page_container" data-page="12">

<b>2.4 Giải thuật DFS</b>

Thuật tốn <b>tìm kiếm theo chiều sâu </b>là một thuật tốn duyệt hoặc tìm kiếm trên một cây hoặc một đồ thị. Thuật toán khởi đầu tại gốc (hoặc chọn một đỉnh nào đó coi như gốc) và phát triển xa nhất có thể theo mỗi nhánh.

<b>2.4.1 Ý tưởng</b>

Đây là thuật tốn tìm các đỉnh bằng cách duyệt theo chiều sâu. Đầu tiên ta thăm đỉnh nguồn .s

Xuất phát từ 1 đỉnh và đi cho đến khi không thể đi tiếp, sau đó đi về lại đỉnh đầu. Trong quá trình quay lại:

Nếu gặp đường đi khác thì đi cho đến khi không đi tiếp được nữa. Nếu không tìm ra đường đi nào khác thì ngừng việc tìm kiếm.

Trong q trình đi đến đỉnh khác, thuật tốn sẽ lưu lại đỉnh cha vừa đi qua để khi đi ngược lại từ đỉnh Kết thúc đến đỉnh Xuất phát, ta có thể xem được đường đi từ đỉnh Kết thúc đến đỉnh Bắt Đầu (có thể số lần đi khơng ít nhất, các bạn có thể tham khảo thuật tốn BFS).

<b>2.4.2 Mơ tả trong code</b>

<small>def dfs(GUI Grid start end, , , ):</small>

</div><span class="text_page_counter">Trang 13</span><div class="page_container" data-page="13">

<small> returncame_from, count</small>

<small> neis =Grid.neighbors[flat(current, Grid.size)] .np random.shuffle(neis)</small>

<small> fornei inneis: ifnei incame_from):</small>

<small> ifcame_from[nei] not incame_from): came_from[nei] current else:</small>

<small> came_from[nei] current</small>

<small> ifneinot in states_history: count+=1</small>

<small> states.append((count, nei)) states_history.add(nei)</small>

</div><span class="text_page_counter">Trang 14</span><div class="page_container" data-page="14">

<b>2.5 Giải thuật UCS</b>

Thuật toán <b>tìm kiếm chi phí đều </b>là một biến thể của thuật toán Dijkstra, được sử dụng hiệu quả trong những đồ thị vô hạn hoặc những đồ thị quá lớn để biểu diễn trong bộ nhớ. Thuật toán UCS được sử dụng chính trong ngành Trí tuệ Nhân tạo.

<b>2.5.1 Ý tưởng</b>

Việc tìm kiếm sẽ bắt đầu tại nút gốc và tiếp tục tìm bằng cách duyệt các nút tiếp theo với trọng số (chi phí) thấp nhất tính từ nút gốc. Các nút được duyệt tiếp tục cho đến khi đến được nút đích.

Thuật tốn tìm kiếm với chi phí cực tiểu

<b>2.5.2 Mơ tả trong code</b>

<small>def ucs(GUI Grid start end, , , ):</small>

<small> g_score=float("inf") forrow inGrid.data for _inrow] g_score[flat(start, Grid.size)] =0</small>

<small> whilenotstates.empty(): ifabortCatch(): return ( , )0 0</small>

<small> current =states.get()[2] # start point ifcurrent==end:</small>

<small> returncame_from, count</small>

<small> fornei inGrid.neighbors[flat(current, Grid.size)]: temp_g_score =g_score[flat(current, Grid.size)] +1 iftemp_g_score <g_score[flat(nei, Grid.size)]: came_from[nei] current</small>

<small>7</small>

</div><span class="text_page_counter">Trang 15</span><div class="page_container" data-page="15">

<small> g_score[flat(nei, Grid.size)] =temp_g_score ifnei instates_history:</small>

<small> continue</small>

<small> count+=1</small>

<small> states.put((g_score[flat(nei, Grid.size)], count nei, )) states_history.add(nei)</small>

</div><span class="text_page_counter">Trang 16</span><div class="page_container" data-page="16">

<b>2.6 Giải thuật Greedy Search</b>

Thuật tốn <b>tìm kiếm tham lam </b>(Greedy Search) là một thuật toán giải quyết một bài toán theo kiểu metaheuristic để tìm kiếm lựa chọn tối ưu địa phương ở mỗi bước đi với hy vọng tìm được tối ưu tồn cục

<b>2.6.1 Ý tưởng</b>

Nói chung, giải thuật tham lam có năm thành phần:

● Một tập hợp các ứng viên (candidate), để từ đó tạo ra lời giải

● Một hàm lựa chọn, để theo đó lựa chọn ứng viên tốt nhất để bổ sung vào lời giải ● Một hàm khả thi (feasibility), dùng để quyết định nếu một ứng viên có thể được

dùng để xây dựng lời giải

● Một hàm mục tiêu, ấn định giá trị của lời giải hoặc một lời giải chưa hoàn chỉnh ● Một hàm đánh giá, chỉ ra khi nào ta tìm ra một lời giải hồn chình

<b>2.6.2 Mơ tả trong code</b>

<small>def greedy(GUI Grid start end, , , ):</small>

<small> f_score=float("inf") forrow inGrid.data for _inrow] f_score[flat(start, Grid.size)] =heu(start, end)</small>

<small> whilenotstates.empty(): ifabortCatch():</small>

<small>9</small>

</div><span class="text_page_counter">Trang 17</span><div class="page_container" data-page="17">

<small> return ( , )0 0</small>

<small> current =states.get()[2] # start point ifcurrent==end:</small>

<small> came_from.pop(start, None) returncame_from, count</small>

<small> fornei inGrid.neighbors[flat(current, Grid.size)]: f_score[flat(nei, Grid.size)] =heu(nei, end) ifnei instates_history:</small>

<small> continue</small>

<small> came_from[nei] current count+=1</small>

<small> states.put((f_score[flat(nei, Grid.size)], count nei, )) states_history.add(nei)</small>

</div><span class="text_page_counter">Trang 18</span><div class="page_container" data-page="18">

<b>2.7 Giải thuật A*</b>

Thuật tốn <b>A* </b>là một thuật tốn tìm đường đi từ một nút khởi đầu tới một nút đích cho trước (hoặc tới một nút thỏa mãn một diều kiện đích). Thuật toán này sử dụng một “đánh giá heuristic” để xếp loại từng nút theo ước lượng về tuyến đường tốt nhất đi qua nút đó. Thuật tốn này duyệt các nút theo thứ tự của đánh giá heuristic này. Do đó, thuật tốn A* là một ví dụ của tìm kiếm theo lựa chọn tốt nhất (best-first search).

<b>2.7.1 Ý tưởng</b>

Xét bài tốn tìm đường – bài tốn mà A* thường được dùng để giải. A* xây dựng tăng dần tất cả các tuyến đường từ điểm xuất phát cho tới khi nó tìm thấy một đường đi chạm tới đích. Tuy nhiên, cũng như tất cả các thuật tốn tìm kiếm có thơng tin nó chỉ xây dựng các tuyến đường “có vẻ” như dẫn về phía đích.

A* lưu giữ một tập các lời giải chưa hoàn chỉnh, nghĩa là các đường đi qua đồ thị, bắt đầu từ nút xuất phát. Tập lời giải này được lưu trong một hàng đợi ưu tiên (priority queue). Thứ tự ưu tiên gán cho một đường đi x được quyết định bởi hàm f(x) = g(x) + h(x).

Trong đó, g(x) là chi phí của đường đi cho đến thời điểm hiện tại, nghĩa là tổng trọng số của các cạnh đã đi qua. h(x) là hàm đánh giá heuristic về chi phí nhỏ nhất để đến đích từ x. Ví dụ, nếu "chi phí" được tính là khoảng cách đã đi qua, khoảng cách đường chim bay giữa hai điểm trên một bản đồ là một đánh giá heuristic cho khoảng cách cịn phải đi tiếp.

Hàm f(x) có giá trị càng thấp thì độ ưu tiên của x càng cao (do đó có thể sử dụng một cấu trúc heap tối thiểu để cài đặt hàng đợi ưu tiên này).

<small>11</small>

</div><span class="text_page_counter">Trang 19</span><div class="page_container" data-page="19">

<b>2.7.2 Mô tả trong code</b>

<small>def a_star(GUI Grid start end, , , ):</small>

<small> g_score=float("inf") forrow inGrid.data for _inrow] g_score[flat(start, Grid.size)] =0</small>

<small> f_score=float("inf") forrow inGrid.data for _inrow] f_score[flat(start, Grid.size)] =heu(start, end)</small>

<small> whilenotstates.empty(): ifabortCatch(): return ( , )0 0</small>

<small> current =states.get()[2] # start point states_history.remove(current) ifcurrent==end:</small>

<small> returncame_from, count</small>

<small> fornei inGrid.neighbors[flat(current, Grid.size)]: temp_g =g_score[flat(current, Grid.size)] +1 iftemp_g>=g_score[flat(nei, Grid.size)]: continue</small>

<small> came_from[nei] current g_score[flat(nei, Grid.size)] =temp_g</small>

<small> f_score[flat(nei, Grid.size)] =temp_g +heu(nei, end) ifnei instates_history:</small>

<small> continue</small>

<small> count+=1</small>

<small> states.put((f_score[flat(nei, Grid.size)], count nei, )) states_history.add(nei)</small>

</div><span class="text_page_counter">Trang 20</span><div class="page_container" data-page="20">

Thuật tốn <b>tìm kiếm ID </b>là một thuật tốn tìm kiếm khơng gian trạng trái với phiên bản giới hạn độ sâu của tìm kiếm theo chiều sâu được chạy lặp đi lặp lại với giới hạn độ sâu tăng dần cho đến khi đạt được mục tiêu được tìm thấy

<b>2.8.1 Ý tưởng</b>

Iterative Deepening Search gọi DFS cho các độ sâu khác nhau bắt đầu từ giá trị ban đầu. Trong mọi cuộc gọi, DFS bị hạn chế vượt quá độ sâu nhất định. Vì vậy, về cơ bản chúng thực hiện DFS theo kiểu BFS.

Bắt đầu tìm kiếm theo DFS với độ sâu tối đa là 0. Nếu khơng tìm thấy giải pháp ở độ sâu này thì năng lên độ sâu tiếp theo

<b>2.8.2 Mô tả trong code</b>

<small>def ideep(GUI Grid start end, , , ):</small>

<small> depth_limit_max =Grid.size **2 step =GUI.stepIDS</small>

<small> whiledepth_limit<=depth_limit_max: ifabortCatch():</small>

<small> return ( , )0 0 states_history.clear()</small>

<small>13</small>

</div><span class="text_page_counter">Trang 21</span><div class="page_container" data-page="21">

<small> whilelen(states) !=0: came_from.pop(start) returncame_from, count ifdepth==depth_limit: break</small>

<small> neis =Grid.neighbors[flat(current, Grid.size)] .np random.shuffle(neis)</small>

<small> fornei inneis: ifnei incame_from):</small>

<small> ifcame_from[nei] not incame_from): came_from[nei] current</small>

<small> states.append((count, nei)) states_history.add(nei) ifnei !=endandnei !=start: simulate(GUI, nei)</small>

<i>Hình 6. Code cho thuật tốn ID</i>

<b>2.9 Giải thuật Beam Search</b>

</div><span class="text_page_counter">Trang 22</span><div class="page_container" data-page="22">

biểu đồ bằng cách mở rộng nút trong một tập hợp giới hạn. Beam Search là sự tối ưu hóa của Best-First Search giúp giảm yêu cầu về bộ nhớ. Best-First Search là tìm kiếm đồ thị sắp xếp tất cả các giải pháp một phần trạng thái theo một số phương án heuristic. Nhưng trong Beam Search, chỉ một số giải pháp của từng phần tốt nhất được xác định trước mới được giữ làm ứng cử viên

<b>2.9.1 Ý tưởng</b>

Beam Search sử dụng tìm kiếm theo chiều rộng để xây dựng thuật tốn tìm kiếm. Ở mỗi cấp độ của cây, nó tạo ra các trạng thái kế tiếp ở cấp độ hiện tại, sắp xếp chúng theo thứ tự tăng dần về chi phí heuristic. Tuy nhiên nó chỉ lưu trữ số lương được sách sách trước

<b>2.9.2 Mô tả trong code</b>

<small>def beam(GUI Grid start end, , , ): Grid.generateNeighbors()</small>

<small> count =0</small>

<small> states =PriorityQueue() states.put((0count, start)) states.put((0count, start)) states_history= {start} came_from= {}</small>

<small> f_score=float("inf") forrow inGrid.data for _inrow] f_score[flat(start, Grid.size)] =heu(start, end)</small>

<small> whilenotstates.empty():</small>

</div><span class="text_page_counter">Trang 23</span><div class="page_container" data-page="23">

<small> returncame_from, count ifcurrent_second==end: came_from.pop(start, None) returncame_from, count</small>

<small> fornei inGrid.neighbors[flat(current_first, Grid.size)]: f_score[flat(nei, Grid.size)] =heu(nei, end) ifnei instates_history:</small>

<small> continue</small>

<small> came_from[nei] current_first count+=1</small>

<small> states.put((f_score[flat(nei, Grid.size)], count nei, )) states_history.add(nei)</small>

<small> ifnei !=end: simulate(GUI, nei)</small>

<small> fornei inGrid.neighbors[flat(current_second, Grid.size)]: f_score[flat(nei, Grid.size)] =heu(nei, end) ifnei instates_history:</small>

<small> continue</small>

<small> came_from[nei] current_second count+=1</small>

<small> states.put((f_score[flat(nei, Grid.size)], count nei, )) states_history.add(nei)</small>

</div>

×