2

这是用 Python 和 Pygame 实现的,但这是一个相当普遍的编程问题(意味着独立于实现)。

我有一个函数,它将 x 和 y 整数作为输入,并且应该生成一个 3x3 的相邻点网格(包括 x 和 y)。

注意:0,0 原点从左上角开始。向右移动时 x 增加,向下移动时 y 增加。

例如。

def nearest_grid(x, y):
    return [[(x-1,y-1),(x,y-1),(x+1,y-1)],[(x-1,y)(x,y),(x+1,y)],[(x-1,y+1),(x,y+1),(x+1,y+1)]]

因此,给定一个网格和一个点(标记为 p),它会以 3 个列表的列表形式返回以下内容:

x  x  x
x  p  x
x  x  x

这是在 Python 中执行此操作的最有效/最清晰的方法吗?

编辑:假设我想传递一个半径值(上面的半径值为 1)。所以,如果我传递了一个半径值 2,那么上面的方法很快就会变得乏味。有没有更通用的方法?

4

2 回答 2

5
def nearby_grid_points(x, y, r=1):
    res = []
    for dy in xrange(-r, r+1):
        res.append([(x+dx, y+dy) for dx in xrange(-r, r+1)])
    return res
于 2012-07-15T21:32:25.600 回答
2

我更喜欢numpy基于此的解决方案:

>>> import numpy
>>> def nearest_grid(x, y, radius=1):
...     X, Y = numpy.mgrid[-radius:radius + 1, -radius:radius + 1]
...     return numpy.dstack((X + x, Y + y))
... 
>>> nearest_grid(1, 2)
array([[[0, 1],
        [0, 2],
        [0, 3]],

       [[1, 1],
        [1, 2],
        [1, 3]],

       [[2, 1],
        [2, 2],
        [2, 3]]])

这是一个高度通用的版本,可以接受任意数量的坐标。这不会将返回列表拆分为网格;为简单起见,它只返回一个平面的邻居列表。

>>> def nearest_grid(*dims, **kwargs):
...     radius = kwargs.get('radius', 1)
...     width = radius * 2 + 1
...     dims = (d - radius for d in dims)
...     return list(itertools.product(*(xrange(d, d + width) for d in dims)))
... 
>>> nearest_grid(1, 2, 3, radius=1)
[(0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 2), (0, 2, 3), (0, 2, 4), 
 (0, 3, 2), (0, 3, 3), (0, 3, 4), (1, 1, 2), (1, 1, 3), (1, 1, 4), 
 (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 3), (1, 3, 4), 
 (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 2), (2, 2, 3), (2, 2, 4), 
 (2, 3, 2), (2, 3, 3), (2, 3, 4)]

请注意,这两个都以您请求的相反顺序返回索引。从表面上看,这仅仅意味着您只需要颠倒参数的顺序——即通过(y, x)or(z, y, x)而不是(x, y)or (x, y, z)。我本可以为您做到这一点,请注意这种方法的问题。

>>> def nearest_grid(x, y, radius=1):
...     X, Y = numpy.mgrid[-radius:radius + 1, -radius:radius + 1]
...     return numpy.dstack((Y + y, X + x))
... 
>>> grid
array([[[0, 0],
        [1, 0],
        [2, 0]],

       [[0, 1],
        [1, 1],
        [2, 1]],

       [[0, 2],
        [1, 2],
        [2, 2]]])

现在我们有一个网格,其中的值按[x, y]顺序存储。当我们将它们用作索引时会发生什么grid

>>> grid = nearest_grid(1, 1)
>>> x, y = 0, 2
>>> grid[x][y]
array([2, 0])

我们没有得到我们期望的单元格!那是因为网格布局如下:

grid = [[(x, y), (x, y), (x, y)],
        [(x, y), (x, y), (x, y)],
        [(x, y), (x, y), (x, y)]]

grid[0]给我们第一行,即y = 0行。所以现在我们必须颠倒顺序:

>>> grid[y][x]
array([0, 2])

最好以行优先 ( (y, x)) 顺序存储值。

于 2012-07-15T21:54:30.690 回答