确定2D网格上的所有相邻空间

时间:2016-12-17 09:03:47

标签: algorithm python-2.7 adjacency-list

我似乎无法找到解决这个问题的好方法。

假设我在描述角色位置的2D网格上有一个点(棋盘游戏):

                                 [n,m]

现在,每次转弯我都可以根据骰子的滚动(1,2,3 ......)移动角色,我想找到角色可以移动的所有可能方式。

移动角色一次意味着仅更改nm,其中对角线移动计为2次移动(即[n + 1,m]移动一次,[ n + 1,m + 1]移动两次。

例如,如果我滚动2,那么所有可能的动作都是:

                                 [n,m+2]
                        [n-1,m+1][n,m+1][n+1,m+1]
                    [n-2,m][n-1,m][n,m][n+1,m][n+2,m]
                        [n-1,m-1][n,m-1][n+1,m-1]
                                 [n,m-2]

我似乎无法为此获得明确的算法。

到目前为止,Daniel Lew

提出了另一项建议
position = [3,2] #position
n = 2 #number of moves allowed
for i in range(position[0]-n,position[0]+n):
    for j in range(position[1]-n,position[1]+n):
        if abs(position[0]-i) + abs(position[1]-j) <= n:
                print i,j,'works\n'

然而,它错过了[n][m+2],[n+2,m](或者我写的方式错过了它)。

有关简明答案或修正的任何建议吗?

3 个答案:

答案 0 :(得分:1)

穿过(倾斜的)钻石线并转换为法线坐标。 Python代码

n = 2 #number of moves allowed
for i in range(0, n+1):
    for j in range(0,n+1):
       print i + j - n, i - j,'\n'

替代方法:您可以沿着n范围内的第一个坐标向两个方向移动。如果剩下一些移动(movesleft),您可以使用movesleft步骤沿任意方向移动第二个坐标。第二阶段必须保留奇数(奇偶校验?),因此使用第2步。

伪代码

n_moves = 2
for dy = -n_moves to n_moves do
     movesleft = n_moves - Abs(dy)
     for dx = - movesleft to movesleft] step 2 do
         make_turn(pos_x + dx, pos_y + dy)     

n = 2且n = 3的Delphi代码给出了结果

var
  n, ml, dx, dy: Integer;
begin
  n := 3;
  for dy := - n to n do begin
    ml := n - Abs(dy);
    dx := - ml;
    repeat
      Memo1.Lines.Add(Format('[%d, %d]', [dy, dx]));
      dx := dx + 2;
    until dx > ml;

  end;
[-2, 0]
[-1, -1]
[-1, 1]
[0, -2]
[0, 0]
[0, 2]
[1, -1]
[1, 1]
[2, 0]

[-3, 0]
[-2, -1]
[-2, 1]
[-1, -2]
[-1, 0]
[-1, 2]
[0, -3]
[0, -1]
[0, 1]
[0, 3]
[1, -2]
[1, 0]
[1, 2]
[2, -1]
[2, 1]
[3, 0]

第一种方法(另一种顺序的结果相同):

for  i := 0 to n do
    for j := 0 to n do begin
        dx := i + j - n;
        dy := i - j;
        Memo1.Lines.Add(Format('[%d, %d]', [dy, dx]));
    end;

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

答案 1 :(得分:1)

假设骰子显示p。 现在你想知道你当前位置有曼哈顿距离p的点数。 现在你可以做到这一点。

伪代码:

for i=0..p
   if( x+i or x-i is valid and y+p-i or y-p+i is valid )
      then move in (x+i,y+p-i) or/and (x-i,y-p+i) or/and (x-i,y+p-i) or/and (x-i,y+-i)

答案 2 :(得分:1)

使用Python 2.7:

import math

# Get coordinates of possible dislocations

def get_possible_dislocations(initial_x, initial_y, max_steps):
    possible_dislocations = []

    for x in range(-max_steps,max_steps+1):
        for y in range(-max_steps,max_steps+1):
            if math.pow(x, 2) + math.pow(y, 2) <= math.pow(max_steps, 2):
                possible_dislocations += [[initial_x + x, initial_y + y]]
    return possible_dislocations

print get_possible_dislocations(0,0,2)

# Returns [[-2, 0], [-1, -1], [-1, 0], [-1, 1], [0, -2], [0, -1], [0, 0], [0, 1], [0, 2], [1, -1], [1, 0], [1, 1], [2, 0]]

如果你想用PyGame测试它,你可以这样做:

import math
import pygame, sys
from pygame.locals import *

# Get coordinates of possible dislocations

def get_possible_dislocations(initial_x, initial_y, max_steps):
    possible_dislocations = []

    for x in range(-max_steps,max_steps+1):
        for y in range(-max_steps,max_steps+1):
            if math.pow(x, 2) + math.pow(y, 2) <= math.pow(max_steps, 2):
                possible_dislocations += [[initial_x + x, initial_y + y]]
    return possible_dislocations

# Initialize Pygame

pygame.init()

crashed = False
display_width = 500
display_height = 500
clock = pygame.time.Clock()
display=pygame.display.set_mode((display_width,display_height),0,32)
white=(255,255,255)
blue=(0,0,255)

display.fill(white)

center_w = display_width/2
center_h = display_height/2

# Calculate possible dislocations
possible_dislocations = get_possible_dislocations(center_w, center_h, 50)

# Draw pixels on every possible dislocation, starting from the center of the display

for loc in possible_dislocations:
    pygame.draw.rect(display,blue,(loc[0],loc[1],2,2))

# Run the display
while not crashed:
    for event in pygame.event.get():
        if event.type==QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()

    clock.tick(60)

在此示例中,角色可以移动50步。如果围绕与中心保持相同距离的点移动,则结果为圆形。如果你可以去那个圆圈内的任何地方,你就可以获得磁盘的笛卡尔坐标。