我正在尝试制作一个接收2048板的功能(嵌套列表制作4乘4格),像这样,
[[0, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]
注意:我知道这不是一个真实的2048主板,但我选择了简单的例子
并且该函数应输出随机图块可能出现的所有位置的列表(2或4)
例如,如果我在上面的板上运行该函数,则输出应为。
[[[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]],
[[4, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]]
所以在任何地方都有一个0,我们想要制作一块板,其中0已被2替换,另一块被4替换。
到目前为止,这是我的代码。
def all_rand_tiles(state):
states = []
changed = []
old_states = [None]
while old_states != states:
old_states = states
new_state = state
for row in range(4):
for tile in range(4):
if state[row][tile] == 0:
#AREA WITH PROBLEM BELOW THIS LINE
if [row, tile] not in changed:
new_state[row][tile] = 2
states.append(new_state)
new_state[row][tile] = 4
states.append(new_state)
changed.append([row, tile])
return states
问题在于,当我在最终的if语句中追加两个不同的状态时,两个状态都将零更改为4.因此,如果在顶部的电路板上运行它,函数的输出将如下所示
[[[4, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]],
[[4, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]]
当我运行new_state[row][tile] = 4
时,我刚刚创建的状态因为其中包含2而被更改为4。
如果您在错误代码区域中运行new_state
之前和之后打印new_state[row][tile] = 4
,则可以看到问题。
我对此感到非常困惑,我不知道为什么我会遇到这个愚蠢的问题。
编辑:请在发布前试用您的解决方案。我已经为您提供了与all_rand_tiles
合作的唯一功能,到目前为止,我无法解决已经提出的任何答案的问题。
答案 0 :(得分:2)
问题在于,当您致电states.append(new_state)
时,您要将参考附加到列表的new_state,而不是副本。因此,对new_state对象所做的任何修改都将影响对它的所有引用。为了获得所需的行为,您需要对新状态进行修改,然后将具有该状态的列表副本附加到new_states对象。有几种方法可以做到这一点:
states.append(new_state[:]) # slice the list
states.append(copy.copy(new_state)) # use the copy function
states.append(list(new_state)) # explicitly construct a new list
答案 1 :(得分:2)
您必须创建state
的副本并将其设置为new_state
。因为您有2D array
,所以必须使用deepcopy
,因此请将代码更改为:
from copy import deepcopy
state=[[0, 0, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]
def all_rand_tiles(state):
states = []
changed = []
old_states = [None]
while old_states != states:
old_states = states
new_state = deepcopy(state)
for row in range(4):
for tile in range(4):
if state[row][tile] == 0:
if [row, tile] not in changed:
new_state[row][tile] = 2
states.append(new_state)
new_state = deepcopy(state)
new_state[row][tile] = 4
states.append(new_state)
new_state = deepcopy(state)
changed.append([row, tile])
return states
print all_rand_tiles(state)
样本:
[[[2, 0, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]],
[[4, 0, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]],
[[0, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]
[[0, 4, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]]
答案 2 :(得分:2)
我并不专门了解Python,但我已经编程了大约20年,所以我的回答可能真的有意义。您可以在以下代码中将数组追加两次:
if [row, tile] not in changed:
new_state[row][tile] = 2
states.append(new_state) <--- appended the first time here
new_state[row][tile] = 4
states.append(new_state) <--- appended the second time here
changed.append([row, tile])
它是追加new_state数组本身,还是只追加new_state数组的参考?如果它是对new_state数组的引用,那么两个实例都是相同的,因为两个引用都引用了new_state的最新版本(在该行&amp; tile中有&#34; 4&#34;)
如果这是原因,那么解决方案是对数组进行实际复制/克隆,或者在使用states.append之前,将new_state中的每个值分别复制到新数组。 / p>
答案 3 :(得分:1)
我相信您遇到问题Strange behavior of python's append?中遇到的问题。您将相同的new_state附加两次,每次修改单个副本。