<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          制作迷宮地圖和行走路線(2)

          共 898字,需瀏覽 2分鐘

           ·

          2022-04-30 11:26

          說(shuō)在前面

          上節(jié)課我們介紹了“使用深度優(yōu)先搜索算法生成不含環(huán)迷宮”的方法,該程序只完成了構(gòu)造隨機(jī)迷宮圖案的功能,卻沒(méi)有記錄通道行進(jìn)路線。這樣只能通過(guò)肉眼觀察迷宮,手動(dòng)繪制從起點(diǎn)到終點(diǎn)的路線,而不能讓電腦自動(dòng)繪制行走路線。我們可以在繪制迷宮通道的同時(shí),把通道前進(jìn)的方向也記錄下來(lái),為后期遍歷迷宮做好準(zhǔn)備工作。

          今天我們就在上節(jié)課代碼的基礎(chǔ)上,增加記錄迷宮路線的功能;并實(shí)現(xiàn)給定任意起點(diǎn)和終點(diǎn)坐標(biāo),讓電腦自動(dòng)繪制行走路線的功能。

          第2節(jié)??????使用深度優(yōu)先搜索算法生成迷宮并尋找路徑

          成品效果圖

          1.使用深度優(yōu)先搜索來(lái)生成不含環(huán)迷宮,并記錄通道走向:

          第1節(jié)課介紹的程序只完成了構(gòu)造隨機(jī)迷宮圖案的功能,卻沒(méi)有記錄通道行進(jìn)路線。這樣只能通過(guò)肉眼觀察迷宮,手動(dòng)繪制從起點(diǎn)到終點(diǎn)的路線,而不能讓電腦自動(dòng)繪制行走路線。我們可以在繪制迷宮通道的同時(shí),使用二維數(shù)組route記錄迷宮路線,其中route[r][c]的值是一個(gè)列表,存儲(chǔ)了與格子(r, c)連通的相鄰格子的行列下標(biāo)(i, j),有幾個(gè)格子與(r, c)相鄰且連通,route[r][c]就有幾個(gè)元素。

          '''函數(shù)功能:使用深度優(yōu)先搜索來(lái)生成不含環(huán)迷宮,并記錄通道走向函數(shù)名:dfs(r, c)參數(shù)表:r,c -- 表示當(dāng)前格子在二維數(shù)組maze中的行列下標(biāo)。返回值:把二維數(shù)組maze和route當(dāng)做全局變量,直接使用畫筆繪制迷宮通道,不需要返回值。''' def dfs(r, c):    # 標(biāo)記(r, c)來(lái)過(guò)    maze[r][c] = 1    # 走到(r, c)    tt.goto(start_x+c*size, start_y-r*size)    # (r, c)的上下左右位置    d = [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]    # 打亂位置,下一個(gè)位置是隨機(jī)的    random.shuffle(d)    for (i, j) in d:        # 選所有可以走的下一個(gè)點(diǎn),如果此點(diǎn)在范圍內(nèi)并且沒(méi)去過(guò)        if 0<=iand 0<=jand maze[i][j]==0:            route[r][c].append((i, j)) # 記錄與(r, c)連通的位置(i, j)            route[i][j].append((r, c)) # 記錄與(i, j)連通的位置(r, c)            # 遞歸去走下一個(gè)點(diǎn)            dfs(i, j)            # 回溯到(r, c)            tt.goto(start_x+c*size, start_y-r*size)

          2.使用深度優(yōu)先搜索來(lái)尋找路徑

          有了二維數(shù)組route記錄的通道行進(jìn)信息,就可以給定任意起點(diǎn)和終點(diǎn)坐標(biāo),讓電腦自動(dòng)繪制行走路線。我們先將maze歸零,以便重新遍歷地圖。同時(shí)定義列表ans來(lái)存儲(chǔ)行走路徑,先將終點(diǎn)加入到ans中,之后逆序添加各個(gè)格子的行列下標(biāo)。

          那么使用什么方法來(lái)遍歷地圖呢?

          最容易想到的方法是模仿構(gòu)造迷宮地圖,使用深度優(yōu)先搜索算法。我們可以定義函數(shù)dfs_ans(r, c),把列表maze和ans當(dāng)做全局變量(因?yàn)榱斜硎强勺儗?duì)象,即使不聲明為global變量,仍可以修改其元素值),若從當(dāng)前格子出發(fā)能夠到達(dá)終點(diǎn),返回True,否則False。

          函數(shù)遍歷與當(dāng)前格子(r, c)連通的相鄰格子route[r][c],遞歸處理通道上的每一個(gè)格子,直到終點(diǎn)。若當(dāng)前格子與終點(diǎn)連通,將當(dāng)前格子行列下標(biāo)添加到ans,并返回True,否則返回False。

          '''函數(shù)功能:使用深度優(yōu)先搜索來(lái)尋找路徑函數(shù)名:dfs_ans(r, c)參數(shù)表:r,c -- 表示當(dāng)前格子在二維數(shù)組maze中的行列下標(biāo)。返回值:把列表maze和ans當(dāng)做全局變量,若從當(dāng)前格子出發(fā)能夠到達(dá)終點(diǎn),返回True,否則False。''' def dfs_ans(r, c):    if r==r2 and c==c2:        return True    for (i, j) in route[r][c]:        if maze[i][j] == 0: # 如果沒(méi)有去過(guò)該點(diǎn),則遞歸搜索該點(diǎn)            maze[i][j] = 1  # 標(biāo)記該點(diǎn)已經(jīng)來(lái)過(guò)            # 遞歸去走下一個(gè)點(diǎn)            if dfs_ans(i, j): #若當(dāng)前格子與終點(diǎn)連通,將當(dāng)前格子行列下標(biāo)加入到ans                ans.append((r, c))                return True    return False

          3.繪制使用深度優(yōu)先搜索獲得的路徑

          有了列表ans存儲(chǔ)的路徑信息,就可以繪制行走路線了。因?yàn)閍ns的元素值是采用回溯算法依次添加的,所以離終點(diǎn)越近的格子越早添加到ans中。因此我們需要逆序遍歷ans,才可以順序輸出從起點(diǎn)到終點(diǎn)的路線。我們定義函數(shù)display_ans()實(shí)現(xiàn)該功能,參考代碼如下:

          '''函數(shù)功能:根據(jù)ans的值,繪制使用深度優(yōu)先搜索獲得的路徑函數(shù)名:display_ans()參數(shù)表:直接使用列表ans的元素值,不需要任何參數(shù)。返回值:直接利用畫筆繪制路線,不需要返回值。''' def display_ans():    tt.speed(1)    tt.pensize(size*0.5) # 路線粗細(xì)    tt.color("red")    tt.penup()    tt.goto(start_x+ans[-1][1]*size, start_y-ans[-1][0]*size)    tt.pendown()    for (r, c) in ans[-2::-1]: #逆序遍歷ans,剛好可以順序輸出從起點(diǎn)到終點(diǎn)的路線        tt.goto(start_x+c*size, start_y-r*size)

          4.主函數(shù)部分代碼

          tt.TurtleScreen._RUNNING = True  # 啟動(dòng)繪圖,在IDE中運(yùn)行加這句可避免報(bào)錯(cuò)tt.ht()#隱藏筆頭tt.bgcolor('black')tt.color("white") # 路線顏色tt.speed(3)w, h = 20, 20 # 迷宮寬和高size = 30 # 每格大小tt.pensize(size*0.8) # 路線粗細(xì)maze = [[0] * w for i in range(h)]route = [[[] for j in range(w)] for i in range(h)] #記錄迷宮路線
          start_x = -w / 2 * sizestart_y = h / 2 * size# 讓畫筆到左上角位置tt.penup()tt.goto(start_x, start_y)tt.pendown()# 從左上角(0, 0)開(kāi)始走dfs(0, 0) # 使用深度優(yōu)先搜索來(lái)生成不含環(huán)迷宮
          # 使用深度優(yōu)先搜索來(lái)尋找路徑r1, c1 = [int(i) for i in input("起點(diǎn)行列下標(biāo):").split()]r2, c2 = [int(i) for i in input("終點(diǎn)行列下標(biāo):").split()]maze = [[0] * w for _ in range(h)] # 將maze歸零,重新遍歷地圖maze[r1][c1] = 1 # 標(biāo)記起點(diǎn)已經(jīng)去過(guò)了ans = [(r2, c2)] # 先將終點(diǎn)加入到ans中,之后逆序添加各個(gè)格子dfs_ans(r1, c1) # 使用深度優(yōu)先搜索來(lái)尋找路徑display_ans() # 繪制使用深度優(yōu)先搜索獲得的路徑
          tt.done() # 結(jié)束繪圖,這將不會(huì)關(guān)閉窗口

          代碼說(shuō)明:

          與第1節(jié)課的程序相比,本節(jié)課程序在主函數(shù)中增加了一個(gè)二維數(shù)組route,用來(lái)記錄記錄迷宮路線。還增加了使用深度優(yōu)先搜索來(lái)尋找路徑的功能:先從鍵盤依次讀入起點(diǎn)行、列下標(biāo)(用空格隔開(kāi))和終點(diǎn)行、列下標(biāo),然后將maze歸零,以便重新遍歷地圖。定義列表ans,并將終點(diǎn)的行列下標(biāo)(r2, c2)作為ans的第一個(gè)元素,之后調(diào)用函數(shù)dfs_ans(),使用深度優(yōu)先搜索算法逆序添加各個(gè)格子信息到ans中。最后調(diào)用函數(shù)display_ans()繪制使用深度優(yōu)先搜索獲得的路徑。

          至此,我們就完成了使用深度優(yōu)先搜索算法生成迷宮并尋找路徑功能。因?yàn)槊詫m通道把所有的格子都連通了,所以你可以將任意格子當(dāng)作起點(diǎn)或終點(diǎn),從鍵盤輸入它們的行、列坐標(biāo)后,觀察紅色畫筆的行進(jìn)路線。

          課后練習(xí)

          節(jié)課介紹的程序是使用深度優(yōu)先搜索算法來(lái)尋找路徑的,除此之外,我們還可以使用廣度優(yōu)先搜索算法來(lái)尋找路徑。請(qǐng)查閱廣度優(yōu)先搜索算法相關(guān)知識(shí),設(shè)置自定義函數(shù),實(shí)現(xiàn)給定任意起點(diǎn)和終點(diǎn)坐標(biāo),使用廣度優(yōu)先搜索算法來(lái)尋找路徑、并繪制行走路線的功能


          需要本文PPT、源代碼和課后練習(xí)答案的,可以加入“Python算法之旅”知識(shí)星球參與討論和下載文件,Python算法之旅”知識(shí)星球匯集了數(shù)量眾多的同好,更多有趣的話題在這里討論,更多有用的資料在這里分享。

          我們專注Python算法,感興趣就一起來(lái)!

          相關(guān)優(yōu)秀文章:

          閱讀代碼和寫更好的代碼

          最有效的學(xué)習(xí)方式

          Python算法之旅文章分類

          瀏覽 128
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一卡二卡三卡四卡在线 | 精品人妻一区二区三区含羞草 | 亚洲自拍偷拍视频 | 黄视频在线 | 伊人狠狠操|