【问题标题】:How can I use a recursive method of changing all adjacent elements in a 2D list?如何使用递归方法更改 2D 列表中的所有相邻元素?
【发布时间】:2020-03-29 16:53:18
【问题描述】:

我正在尝试制作一个小游戏,但我无法让它按照我需要的方式运行。我需要找到一种方法(我在递归地猜测?)来改变一个 2D 列表,以便所有相邻的字符都被替换为不同的字符。例如,如果我有一个这样的 2D 列表:

[['#', '#', '#', '@', '@', '#', '#', '#', '%'], ['#', '#' , '@', '@', '&', '&', '&', '#', '%'], ['@', '#', '#', '#', '#', '#', '&', '#', '%'], ['@', '@', '@', '@', '#', '#', '#', '%', '%'], ['#', '@ ', '%', '%', '%', '%', '%', '%', '%']]

它应该像这样打印在一个网格中:

   012345678
0  $$$@@$$$%
1  $$@@&&&$% 
2  @$$$$$&$%
3  @@@@$$$%%
4  $@%%%%%%%

例如,如果用户在第 3 行第 1 列输入“%”,则每个相互连接的“@”都应更改为所需的符号,使其变为:

   012345678
0  $$$@@$$$%
1  $$@@&&&$% 
2  %$$$$$&$%
3  %%%%$$$%%
4  $%%%%%%%%

我们的目标是让所有东西都成为同一个符号。我填充这些空间的功能目前如下所示,并且仅在所需位置替换符号,并且没有与之相邻的任何内容:

def fill(gameBoard, targetSymbol, userSymbol, row, col):

    if gameBoard[row][col] != targetSymbol:
        pass
    elif gameBoard[row][col] == targetSymbol:
        gameBoard[row][col] = userSymbol 

我知道目前这有点简单,但我尝试过的大部分方法最终都不起作用。让它也改变相邻点的最佳方法是什么?我假设递归是最好的,但我还没有真正用递归做太多事情,我正在努力弄清楚让它工作背后的逻辑。

【问题讨论】:

  • 为什么你不编辑你的问题,让它看起来像一个问题?例如,以我如何...开头,以问号结尾?
  • 快速提醒,直接从 stackoverflow 提出的家庭作业问题的解决方案是零分(或更差)。

标签: python list recursion multidimensional-array


【解决方案1】:

这是在选定位置填充矩阵的非常粗略的递归方式。它绝对可以写得更短,但至少可以开始:

matrix = [['#', '#', '#', '@', '@', '#', '#', '#', '%'],
          ['#', '#', '@', '@', '&', '&', '&', '#', '%'],
          ['@', '#', '#', '#', '#', '#', '&', '#', '%'],
          ['@', '@', '@', '@', '#', '#', '#', '%', '%'],
          ['#', '@', '%', '%', '%', '%', '%', '%', '%']]

def _fill(data, x, y, ch, orig=None, seen=None):
    if orig is None:
        orig = data.get((x, y), None)

    if seen is None:
        seen = set()

    #fill up
    if (x, y-1) in data and (x, y-1) not in seen and data.get((x, y-1), None) == orig:
        seen.add((x, y-1))
        _fill(data, x, y-1, ch, orig, seen)
        data[(x, y-1)] = ch

    #fill down
    if (x, y+1) in data and (x, y+1) not in seen and data.get((x, y+1), None) == orig:
        seen.add((x, y+1))
        _fill(data, x, y+1, ch, orig, seen)
        data[(x, y+1)] = ch

    #fill left
    if (x-1, y) in data and (x-1, y) not in seen and data.get((x-1, y), None) == orig:
        seen.add((x-1, y))
        _fill(data, x-1, y, ch, orig, seen)
        data[(x-1, y)] = ch

    #fill right
    if (x+1, y) in data and (x+1, y) not in seen and data.get((x+1, y), None) == orig:
        seen.add((x+1, y))
        _fill(data, x+1, y, ch, orig, seen)
        data[(x+1, y)] = ch

def fill(matrix, x, y, ch):
    d = {}
    for i, row in enumerate(matrix):
        for j, data in enumerate(row):
            d[(i, j)] = data

    _fill(d, x, y, ch)

    rv = []
    for i, row in enumerate(matrix):
        rv.append([])
        for j, data in enumerate(row):
            rv[-1].append(d[(i, j)])

    return rv

from pprint import pprint
print('Old matrix:')
pprint(matrix)
print('-' * 80)
print()
print('Filled matrix:')
matrix = fill(matrix, 3, 1, '%')
pprint(matrix)

打印:

Old matrix:
[['#', '#', '#', '@', '@', '#', '#', '#', '%'],
 ['#', '#', '@', '@', '&', '&', '&', '#', '%'],
 ['@', '#', '#', '#', '#', '#', '&', '#', '%'],
 ['@', '@', '@', '@', '#', '#', '#', '%', '%'],
 ['#', '@', '%', '%', '%', '%', '%', '%', '%']]
--------------------------------------------------------------------------------

Filled matrix:
[['#', '#', '#', '@', '@', '#', '#', '#', '%'],
 ['#', '#', '@', '@', '&', '&', '&', '#', '%'],
 ['%', '#', '#', '#', '#', '#', '&', '#', '%'],
 ['%', '%', '%', '%', '#', '#', '#', '%', '%'],
 ['#', '%', '%', '%', '%', '%', '%', '%', '%']]

【讨论】:

    【解决方案2】:

    是的,递归是一种可能的解决方案。这是我的方法。为了简单起见,我使用了 numpy,但应该与 python 列表类似。

    import numpy as np
    
    table = np.array([['#', '#', '#', '@', '@', '#', '#', '#', '%'],
                      ['#', '#', '@', '@', '&', '&', '&', '#', '%'],
                      ['@', '#', '#', '#', '#', '#', '&', '#', '%'],
                      ['@', '@', '@', '@', '#', '#', '#', '%', '%'],
                      ['#', '@', '%', '%', '%', '%', '%', '%', '%']])
    print('original:')
    print(table)
    
    def fill(gameBoard, i, j, symbol):
        if gameBoard[i, j] != symbol:
            originalSymbol = gameBoard[i, j]
            def r(i, j):
                if i < 0 or i >= gameBoard.shape[0] or j < 0 or j >= gameBoard.shape[1]:
                    # out of bounds
                    return
                #change symbol if it is adjacent
                if gameBoard[i,j] == originalSymbol:
                    gameBoard[i,j] = symbol
                    for di, dj in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                        r(i+di, j+dj)
            r(i, j)
        return gameBoard
    
    print('modified:')
    print(fill(table, 3, 1, '%'))
    

    输出:

    original:
    [['#' '#' '#' '@' '@' '#' '#' '#' '%']
     ['#' '#' '@' '@' '&' '&' '&' '#' '%']
     ['@' '#' '#' '#' '#' '#' '&' '#' '%']
     ['@' '@' '@' '@' '#' '#' '#' '%' '%']
     ['#' '@' '%' '%' '%' '%' '%' '%' '%']]
    modified:
    [['#' '#' '#' '@' '@' '#' '#' '#' '%']
     ['#' '#' '@' '@' '&' '&' '&' '#' '%']
     ['%' '#' '#' '#' '#' '#' '&' '#' '%']
     ['%' '%' '%' '%' '#' '#' '#' '%' '%']
     ['#' '%' '%' '%' '%' '%' '%' '%' '%']]
    

    【讨论】:

      【解决方案3】:

      没有进口:

      def fill(board, strT, strS, intR, intC):
          if (intR < len(board) and intC < len(board[0]) and strT == board[intR][intC] and strT != strS):
              board[intR][intC] = strS # Replace the symbol at the current coordinates
              fill(board, strT, strS, intR + 1, intC) # Search down
              fill(board, strT, strS, intR - 1, intC) # Search up
              fill(board, strT, strS, intR, intC + 1) # Search right
              fill(board, strT, strS, intR, intC - 1) # Search left
      

      【讨论】:

        【解决方案4】:

        我会推荐这个,但从您的回复来看,这似乎不是您想要的。您的游戏的其余代码是什么样的?如果没有上下文,我无法确切知道您需要什么。另一个用户推荐了这个用于填充功能,但我可以看到这对你可能没有用。因此,当您编辑评论时,您可以在此下方发表评论。到时候我会更好的回答。

        if seen is None:
            seen = set()
        
        #fill up
        if (x, y-1) in data and (x, y-1) not in seen and data.get((x, y-1), None) == orig:
            seen.add((x, y-1))
            _fill(data, x, y-1, ch, orig, seen)
            data[(x, y-1)] = ch
        
        #fill down
        if (x, y+1) in data and (x, y+1) not in seen and data.get((x, y+1), None) == orig:
            seen.add((x, y+1))
            _fill(data, x, y+1, ch, orig, seen)
            data[(x, y+1)] = ch
        
        #fill left
        if (x-1, y) in data and (x-1, y) not in seen and data.get((x-1, y), None) == orig:
            seen.add((x-1, y))
            _fill(data, x-1, y, ch, orig, seen)
            data[(x-1, y)] = ch
        
        #fill right
        if (x+1, y) in data and (x+1, y) not in seen and data.get((x+1, y), None) == orig:
            seen.add((x+1, y))
            _fill(data, x+1, y, ch, orig, seen)
            data[(x+1, y)] = ch
        

        【讨论】:

          猜你喜欢
          • 2020-03-22
          • 1970-01-01
          • 2021-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多