2017-03-23 13 views
2

How can I shift and merge elements of a matrix to have the following result ?移位和合並元件

向右移動: [[0,0,2,2,0,2],[8,4,2,2,0,2]] ==>[[0,0,0,0,4,2],[0,0,8,4,4,2]]

左移: [[0,0,2,2,0,2],[8,4,2,2,0,2]] ==>[[4,2,0,0,0,0],[8,4,4,2,0,0]]

It's like the 2048 game. For example, when the user do a left move, every numbers go to the left of the list and if 2 numbers side-by-side are equals, tere is an addition of the two numbers.

我想用循環來做到這一點。

我嘗試了一些我在互聯網上找到的代碼,但作爲開發者,我沒有找到明白如何做到這一點的簡單代碼。

在此先感謝您的幫助。

+2

請解釋你正在嘗試做什麼。你的輸入和輸出沒有明顯的模式。 (而且我注意到你已經爲同樣的輸入提供了兩個樣本輸出。) –

+0

感謝您的建議。我改進了我的解釋。 :) – titi157

+0

是的,就是這樣。 :) – titi157

回答

0

下面是元素向右移動一個例子:然後做

def move_right(matrix): 
    for row in matrix: 
     for i, number in reversed(list(enumerate(row))): 
      if number == row[i-1]: 
       row[i] = number + row[i-1] 
       row[i-1] = 0 
     row.sort(key=lambda v: v != 0) 

    return matrix 

matrix = [[0,0,2,2,0,2],[8,4,2,2,0,2]] 
print(move_right(matrix)) 

輸出:

[[0, 0, 0, 0, 4, 2], [0, 0, 8, 4, 4, 2]] 

它是如何工作的:

  1. 首先我們循環遍歷矩陣。在第一次迭代中:row = [0, 0, 2, 2, 0, 2]
  2. 然後我們使用enumerate()函數檢查該行中的數字。然後,我們應用reverse()來遍歷列表,以便在一個回合中不會將前一個和與另一個元素相結合。 e.g: [4,4,8] => [0, 8, 8] => [0, 0, 16]. This should actually equal [0, 0, 8] 當前行,這將輸出結果像這樣:

    i number 5 2 4 0 3 2 2 2 1 0 0 0

  3. 然後我們使用索引(i)來指代前面的號碼在列表中。例如在索引2處。當前數字是2,前一個數字(i-1)是2.由於這些數字相等,所以'if'語句中的代碼將執行。

  4. 然後將當前元素分配給它自己和前一個元素的總和。 row[i] = number + row[i-1]

  5. 上一個數字將變爲0,與當前數字合併。row[i-1] = 0

  6. 一旦我們結束了每一個數字,該行將是:[0, 0, 0, 4, 0, 2]。代碼row.sort(key=lambda v: v != 0)將進行排序,以便零點被推到左邊。有關更多詳細信息,請參閱here。 當將元素移動到左側而不是右側時,需要將其更改爲row.sort(key=lambda v: v != 0, reverse=True),以將零點推向另一個方向。

+0

你的代碼運行良好,但你可以解釋我下面的代碼行嗎?'row.sort(key = lambda v:v!= 0)' – titi157

+0

看到這個鏈接http://stackoverflow.com/questions/23844828/move如果你仍然有問題可以免費提問 –

+0

有沒有辦法將矩陣中的所有0移動到頂部或者例如: [[0,0,0,0],[0,0,0,0],[1,1,1,1],[0,0,0,0]]會變成[ [1,1,1,1] [0,0,0,0],[0,0,0,0],[0,0,0,0]]或[[0,0,0,0] ,[0,0,0,0],[0,0,0,0],[1,1,1,1]]。我做了一個循環,但我想知道是否有內置函數,在功能上 去做。 :) – titi157

1

如果我不要誤會你的意思,我寫了一些代碼,希望這有助於:

a = [[0, 0, 2, 2, 0, 2], [8, 4, 2, 2, 0, 2]] 
f = lambda x: [2 * x[0]] if x[0] == x[1] else x 

def move_left(l): 
    c, l = [], l + [0] if len(l) % 2 else l 

    for i in range(0, len(l), 2): 
     c = c + f(l[i:i + 2]) 
    c = list(filter(lambda x: x != 0, c)) 
    return c + ([0] * (len(l) - len(c))) 


def move_right(l): 
    c, l = [], l + [0] if len(l) % 2 else l 

    for i in range(len(l), 0, -2): 
     c = f(l[i - 2:i]) + c 
    c = list(filter(lambda x: x != 0, c)) 
    return ([0] * (len(l) - len(c))) + c 

for i in a: 
    print(move_left(i)) 

輸出:

[4, 2, 0, 0, 0, 0] 
[8, 4, 4, 2, 0, 0] 

看來你使用Python3 .x,所以你應該使用list(filter(lambda x: x != 0, c))來獲取列表。

+0

'range(0,len(l),2)'會使結果更容易閱讀。 –

+0

@MartinBonner謝謝,我更新它。 – McGrady

+0

我執行代碼時出現此錯誤。 :( ' in move_left return c +([0] *(len(l) - len(c))) TypeError:'filter'類型的對象沒有len()' – titi157