2048年所有可能的随机瓷砖

时间:2014-08-28 19:42:53

标签: python arrays append

我正在尝试制作一个接收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合作的唯一功能,到目前为止,我无法解决已经提出的任何答案的问题。

4 个答案:

答案 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附加两次,每次修改单个副本。