Python 2048年所有可能的随机瓷砖

Python 2048年所有可能的随机瓷砖,python,arrays,append,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

我正在尝试制作一个函数,它包含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语句中附加两个不同的状态时,两个状态的0都变为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[row][tile]=4前后打印new_state,则可以看到演示的问题

我被这件事弄糊涂了,我不知道为什么我会有这个愚蠢的问题


编辑:请在发布前试用您的解决方案。我已经为您提供了我正在使用的所有随机瓷砖的唯一功能,到目前为止,我无法用所提供的任何答案解决问题。

我相信您遇到的问题与问题中发现的问题相同。您两次追加相同的新状态,每次都修改单个副本。

问题是,当您调用states.appendnew\u state时,您是在列表中追加对新状态的引用,而不是副本。因此,对新的_state对象所做的任何修改都将影响对它的所有引用。为了获得您想要的行为,您需要对newstate进行修改,然后将具有该状态的列表副本附加到newstates对象。有几种方法可以做到这一点:

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  
您必须创建状态的副本,并将其设置为新状态。由于您有一个2D阵列,因此必须使用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)
演示:


我并不特别了解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])
它是附加新的_状态数组本身,还是只是对新的_状态数组的引用?如果是对新_state数组的引用,那么这两个实例将是相同的,因为这两个引用都引用了最新版本的新_state,该行和磁贴中有一个4


如果这是原因,那么解决方案就是在使用states之前,对数组进行实际的复制/克隆,或者只是将new_state中的每个值单独复制到一个新数组中。append.

@jornsharpe请详细说明。简短的回答可能是引用相等。作为一个简单的例子,a=[];b=a;b、 附录23;打印a将打印[23],即使您在创建a后没有对其进行任何明显的更改。您要替换0的这块板是在您刷卡后立即打印的,对吗?@TheSoundDefense!这是我刚才给出的非常长的解释的一个更简单的版本。我希望我们都能获得选票。我修改了代码以使用这个复制功能,但问题仍然存在。如果你不相信我,你可以在这里运行代码。因为我没有你的全部代码,所以我不能尝试任何东西。@DavidGreydanus我编辑代码,并且它可以工作,这是延迟的好借口…我还为你的好问题给了+1@Kasra朝着正确的方向迈出了一大步,但是如果你有一个以上的0在板上,这个函数不会给出所有的可能性,而是重复它自己;谢谢@Kasra!我在其他语言中也遇到过同样的问题,所以我认为它可能适用
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])