Skip to main content
 首页 » 编程设计

Python编码——如何在列表的列表中找到特定元素的踪迹

2025年05月04日26bjzhanghao

我正在 python 上进行 groklearning,我正在尝试解决如下问题:

您熟悉 Hansel 和 Gretel 的故事,因此当您决定去探索时,请始终确保记下您的来历。既然您知道留下痕迹是多么不可靠,您决定编写一个程序来帮助您绘制痕迹。

您的程序应首先读入您将探索的网格的大小,然后按方向读入:左、右、上或下。您总是从 map 的左上角开始探索。在每一步之后,您应该打印出踪迹,阅读说明直到输入空白行。 你的程序应该像这样工作:

输出应该是这样的:

Grid size: 3 
x.. 
... 
... 
Direction: right 
xx. 
... 
... 
Direction: down 
xx. 
.x. 
... 
Direction: right 
xx. 
.xx 
... 
Direction:  

我的代码如下,我卡在这里了。我对如何找到“x”以及如何更改“x”的特定邻居感到困惑。

size = int(input('Grid size: ')) 
table = [] 
for i in range(size): 
  row=[] 
  for j in range(size): 
    row.append('.') 
  table.append(row) 
table[0][0] = 'x' 
for row in table: 
  print(*row,sep='') 
 
Direction = input('Direction: ') 
while Direction: 
  if Direction == 'right': 
    for i in range(size): 
      for j in range(size-1): 
        if table[i][j] == 'x': 
          table[i][j+1] = 'x' 
          table[i-1][j+1] = '.' 
        break 
  elif Direction == 'down': 
    for i in range(size): 
      for j in range(size-1): 
        if table[j][i] == 'x': 
          table[j+1][i] = 'x' 
          table[j+1][i-1] = '.' 
        break 
  Direction = input('Direction: ') 

请您参考如下方法:

本质上,你想携带一些状态,即你当前所在的位置,以及棋盘的状态,你想在这个封装的状态上执行操作。这是类的完美用例。这是一个快速而肮脏的实现。

class Grid: 
    def __init__(self, size): 
        self.data = [['.']*size for _ in range(size)] 
        self.size = size 
        self.x = 0 
        self.y = 0 
        self.data[0][0] = 'x' 
    def right(self): 
        self.x = min(self.x + 1, self.size - 1) 
        self.mark_position() 
    def left(self): 
        self.x = max(self.x - 1, 0) 
        self.mark_position() 
    def up(self): 
        self.y = max(self.y - 1, 0) 
        self.mark_position() 
    def down(self): 
        self.y = min(self.y + 1, self.size - 1) 
        self.mark_position() 
    def mark_position(self): 
        self.data[self.y][self.x] = 'x' 
    def __str__(self): 
        return '\n'.join([''.join(sub) for sub in self.data]) 

请注意,我们的原点 (0,0) 位于左上角。绊脚石:列表列表是存储此数据的自然方式,但列表的第一个“维度”选择“行”,第二个维度选择“列”,因此“x”和“y” "在 data[0][1] 是第一行第二列的意义上是相反的,即 0 在 y 中,1 在 x 中。另请注意,我实现的逻辑不允许您越过网格边界(使用 min 和 max 为您截断),但您的其他可能性是抛出一个错误,或者你可以让世界环绕。一旦您掌握了这种方法,请尝试自己实现。

测试一下:

In [2]: grid = Grid(3) 
 
In [3]: print(grid) 
x.. 
... 
... 
 
In [4]: grid.right() 
 
In [5]: print(grid) 
xx. 
... 
... 
 
In [6]: grid.down() 
 
In [7]: print(grid) 
xx. 
.x. 
... 
 
In [8]: grid.right() 
 
In [9]: print(grid) 
xx. 
.xx 
... 

请注意,您不必使用类,但您可能需要进行大量重复的参数传递,即将状态作为参数传递。在这里我做了一个非常直译为更程序化的方法来强调两者之间的关系。请注意,为了安全起见,我复制了 data,因为到处都是状态,而改变全局状态是将错误引入程序的好方法。否则,这可能是类的直译。

def initialize_game_state(size): 
    data = [['.']*size for _ in range(size)] 
    x = 0 
    y = 0 
    data[0][0] = 'x' 
    return data, x, y 
 
def right(data, x, y): 
    new_x = min(x + 1, len(data) - 1) 
    new_data = mark_position(data, new_x, y) 
    return new_data, new_x, y 
 
def left(data, x, y): 
    new_x = max(x - 1, 0) 
    new_data = mark_position(data, new_x, y) 
    return new_data, new_x, y 
 
def up(data, x, y): 
    new_y = max(y - 1, 0) 
    new_data = mark_position(data, x, new_y) 
    return new_data, x, new_y 
 
def down(data, x, y): 
    new_y = min(y + 1, len(data) - 1) 
    new_data = mark_position(data, x, new_y) 
    return new_data, x, new_y 
 
def mark_position(data, x, y): 
    data_copy = [sub.copy() for sub in data] 
    data_copy[y][x] = 'x' 
    return data_copy 
 
def grid_to_string(data): 
    return '\n'.join([''.join(sub) for sub in data])