質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4711閲覧

Pythonで幅優先探索で迷路を解き、経路を全て表示したい

pyxis

総合スコア16

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/12/20 16:22

Pythonで迷路を幅優先探索で解き、全ての最短をルートを表示したいのですが、
最短距離をリストに格納するところまでは出来たのですがそれを元に
ルートを表示するところ(コード内のsearch_route関数)が上手く動作しません。
参考にしたサイト

具体的には次のようなマップな場合、(S:スタート G:ゴール $:ルート *:壁)

***** * * *S*G* * * *****

以下のように2つのルートを表示させたいのですが、

***** * * *S*G* *$$$* ***** ***** *$$$* *S*G* * * *****

コードを実行すると、次の様に2個目のルートに1つ目のルートが重なって表示されます。

***** * * *S*G* *$$$* ***** ***** *$$$* *S*G* *$$$* *****

以下のコードのsearch_route関数の部分をどのように直せばよいでしょうか?

Python

1map = [ 2 '*****', 3 '* *', 4 '*S*G*', 5 '* *', 6 '*****' 7 ]; 8 9 10def print_route(route): 11 for l in route: 12 print( "".join(l)) 13 14# mapから、'S'または'G'の位置を探して返す.無かったらNoneが返る 15def getLoc(map,SorG): 16 t=0 17 for l in map: 18 s=0 19 for n in l: 20 if n == SorG: 21 return (t,s) 22 s=s+1 23 t=t+1 24 25def search(map): 26 s = getLoc(map,'S') # mapからSの位置を探す 27 print ('スタート地点:'+str(s)) 28 if s == None: 29 print( 'スタート地点Sがないので、道はありません.') 30 else: 31 # s から'G'までの最短距離を返す 32 # search_from_s(map,s) 33 return search_from_s(map,s) 34 35 36# s から'G'までの最短距離を返す 37def search_from_s(map,s): 38 mapi = len(map) 39 mapj = len(map[0]) 40 # distanceは、Sから(t,s)までの仮の最短距離を保存する 41 distance=[[None for j in range(mapj)] for i in range(mapi)] 42 distance[s[0]][s[1]]=0 #スタート地点は距離0 43 next.append((s,0)) #探索位置とその位置までのそのルートでの最短距離を保存するリスト型キュー 44 45 while len(next) != 0: 46 n = next.pop(0) 47 a = n[0] # 探索位置 48 dis_a = n[1] # Sからa までの距離 49 # aの上下左右を見る. 50 if 0<=a[0]-1 : # 上。 回りが*で囲われているのでこの行はいらない 51 next_a(a[0]-1,a[1],dis_a,map,distance,next) 52 if a[0]+1<mapi : #下 53 next_a(a[0]+1,a[1],dis_a,map,distance,next) 54 if 0<=a[1]-1 : #左 55 next_a(a[0],a[1]-1,dis_a,map,distance,next) 56 if a[1]+1<mapj : #右 57 next_a(a[0],a[1]+1,dis_a,map,distance,next) 58 #結果出力。ついでにGの位置も出力 59 g=getLoc(map,'G') 60 print ('ゴール地点:'+str(g)) 61 print ('最短距離:'+str(distance[g[0]][g[1]])) 62 return distance 63 64 65#aの上下左右を見る.壁(*)だったら何もしない. 66#壁でなければdistanceのその位置と同じ位置を見て、 67#保存されている距離がdis_a+1よりも小さければ何もしない. 68#大きいか距離が保存されていなかったら、dis_a+1で置き換える 69#"G"だったら、dis_a+1を返し、探索終了. 70#"G"でなければ、nextにその位置とdis_a+1を保存する. 71def next_a(i,j,dis_a,map,distance,next): 72 if map[i][j] == '*': 73 return 74 if distance[i][j] == None: 75 distance[i][j]=dis_a+1 76 if map[i][j] != 'G': #ゴールでないないなら 77 next.append(((i,j),dis_a+1)) 78 else: 79 del next[:] 80 else: 81 # 元のコード distance[i][j] < dis_a+1 となっていたが、距離が同じなら調べる必要は無い 82 if distance[i][j] <= dis_a+1: 83 return 84 else: 85 distance[i][j] = dis_a+1 86 if map[i][j] != 'G': 87 next.append(((i,j),dis_a+1)) 88 else: del next [:] 89 90# nextをグローバル変数にしないと、next [:] と while len(next) != 0: 91# が意味をなさず、ゴールに来ても他の探索ルートが探索を止めない。 92 93""" 94map:マップ 95distance:スタートからの距離を記したリスト 96route:ゴールからの探索ルートに$を記したもの 97dis:スタート、ゴール間の最短距離から1ずつ引いた値 98s:スタートの座標 99g:ゴールの座標 100a:探索している座標 101""" 102def search_route(map, distance, route, dis, s, g, a): 103 route = route.copy() 104 a = a.copy() 105 106 if a == s: 107 # スタートとゴールも$になっているので、SとGで上書き 108 route[s[0]][s[1]]='S' 109 route[g[0]][g[1]]="G" 110 111 print_route(route) 112 print() 113 114 # 枠外に行くと終了 115 if a[0]>=mapi or a[0]<0 or a[1]<0 or a[1]>=mapj: 116 return 117 118 # 最短ルートでないと終了 119 if distance[a[0]][a[1]]!=dis: 120 return 121 122 if distance[a[0]][a[1]]==dis: 123 route[a[0]][a[1]]='$' 124 125 dis=dis-1 126 127 search_route(map,distance, route, dis,s, g, [a[0]+1,a[1]]) 128 search_route(map,distance, route, dis,s, g, [a[0]-1,a[1]]) 129 search_route(map,distance, route, dis,s, g, [a[0],a[1]-1]) 130 search_route(map,distance, route, dis,s, g, [a[0],a[1]+1]) 131 132 133next = [] 134# 迷路を示す配列を渡すとSからGまでの最短距離を返す 135distance = search(map) 136 137mapi = len(map) 138mapj = len(map[0]) 139 140route = [] 141 142for i in range(mapi): 143 lst=[] 144 for j in range(mapj): 145 lst.append(map[i][j]) 146 # print(lst) 147 route.append(lst) 148 149s=getLoc(map,'S') 150s = list(s) 151g=getLoc(map,'G') 152g = list(g) 153a=g 154 155dis=distance[g[0]][g[1]] 156 157search_route(map,distance, route, dis, s, g, a)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2019/12/20 23:38

「最短距離をリストに格納するところまでは出来た」とのことですが、コードのどの部分で確認できましたか?
guest

回答1

0

ベストアンサー

python

1 route = route.copy() 2 a = a.copy()

ここで「浅いコピー」を行っているからです。
二次元リストの複製を行いたい場合、「深いコピー」を行う必要があります。

「python deepcopy」等で検索してみてください。

なお、アルゴリズムの確認はしていません。

投稿2019/12/20 23:49

2KOH

総合スコア999

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pyxis

2019/12/21 07:27

ありがとうございました! deepcopyすることにより別々のルートを表示できるようになりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問