我正在嘗試使用不同的演算法(例如 BFS、DFS、A* 等)使用 python 制作一個 8 拼圖問題求解器。對于不熟悉問題的人來說,8 拼圖問題是一個由 3 行 3 列組成的游戲。您只能水平或垂直移動空瓷磚,0 代表空瓷磚。它看起來像這樣(由于我的帳戶聲譽,我無法添加影像。):
https://miro.medium.com/max/679/1*yekmcvT48y6mB8dIcK967Q.png
initial_state = [0,1,3,4,2,5,7,8,6]
goal_state = [1,2,3,4,5,6,7,8,0]
def find_zero(state):
global loc_of_zero
loc_of_zero = (state.index(0))
def swap_positions(list, pos1, pos2):
first = list.pop(pos1)
second = list.pop(pos2-1)
list.insert(pos1,second)
list.insert(pos2,first)
return list
def find_new_nodes(state):
if loc_of_zero == 0:
right = swap_positions(initial_state,0,1)
left = swap_positions(initial_state,0,3)
return(right,left)
find_zero(initial_state)
print(find_new_nodes(initial_state))
我的問題是,我希望函式“find_new_nodes(state)”回傳 2 個不同的串列,因此我可以選擇最有希望的節點,具體取決于演算法)等等。但是我的代碼的輸出由兩個相同的串列組成。
這是我的輸出:([4, 0, 3, 1, 2, 5, 7, 8, 6], [4, 0, 3, 1, 2, 5, 7, 8, 6])
我該怎么做才能讓它回傳 2 個不同的串列?我的目標是使用 find_new_nodes 函式根據 0 的位置回傳所有可能的移動。抱歉,如果這是一個簡單的問題,這是我第一次使專案如此復雜。
uj5u.com熱心網友回復:
問題是swap_positions獲得對全域的參考initial_state而不是它的克隆。所以這兩個呼叫都swap_positions改變了同一個陣列。一個解決方案是在第一次呼叫時克隆陣列:
right = swap_positions(initial_state[:],0,1)
可能更好的解決方案swap_positions是:
# please do not name variables same as builtin names
def swap_positions(lis, pos1, pos2):
# create a new tuple of both elements and destruct it directly
lis[pos1], lis[pos2] = lis[pos2], lis[pos1]
return lis
另見此處
uj5u.com熱心網友回復:
您實際上沒有“兩個相同的串列”,您只有一個要回傳兩次的串列物件。為了避免修改原始串列以及兩個使用不同串列的作業,您應該傳遞副本。
initial_state = [0,1,3,4,2,5,7,8,6]
goal_state = [1,2,3,4,5,6,7,8,0]
def find_zero(state):
global loc_of_zero
loc_of_zero = (state.index(0))
def swap_positions(states, pos1, pos2):
first = states.pop(pos1)
second = states.pop(pos2-1)
states.insert(pos1,second)
states.insert(pos2,first)
return states
def find_new_nodes(states):
if loc_of_zero == 0:
right = swap_positions(states.copy(),0,1) # pass around a copy
left = swap_positions(states.copy(),0,3) # pass around a copy
return(right,left)
find_zero(initial_state)
print(find_new_nodes(initial_state))
旁注 1:我已將您的變數重命名list為states,否則它會影響內置串列功能
旁注 2:find_new_nodes不使用引數,而是使用全域串列。我也是這樣改的。
旁注 3:有多種方法可以創建(淺)串列的副本。我認為list.copy()是最冗長的。您還可以使用 copy 模塊、use[:]或其他東西。
輸出:
([1, 0, 3, 4, 2, 5, 7, 8, 6], [4, 1, 3, 0, 2, 5, 7, 8, 6])
uj5u.com熱心網友回復:
好的,首先,一些想法......
盡量不要使用“list”作為變數,它是“list”型別的 Python 識別符號。看來您正在重新定義該術語。
通常,使用全域變數(例如 loc_of_zero)是一個壞主意。
關于你的問題:
我相信問題在于您獲得了大量相同變數的參考。盡量避免它。一個想法:
from copy import deepcopy
def swap_positions(list0, pos1, pos2):
list1 = deepcopy(list0)
first = list1.pop(pos1)
second = list1.pop(pos2-1)
list1.insert(pos1,second)
list1.insert(pos2,first)
return list1
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/363816.html
上一篇:遞回有序節點著色
