2012-12-08 50 views
0

我在这里有一个python类方法的怪胎。我认为做这件事的唯一方法是一个巨大而丑陋的if/elif/else块。你们有没有想出任何想法来使这个更好?你可以漂亮吗?

对于上下文来说,这是pygame的一个网格制作库的一部分,它是一个函数,它接受网格中的一个瓦片并返回周围的瓦片。如果“水平”设置为false,则它仅返回与瓦片垂直相邻的瓦片,反之亦然。

def getSurroundingTiles(self, tile, horizontal = True, vertical = True): 
    index = list(self.getTiles()).index(tile) 
    maxtile = self.sqrtnum - 1 # Offset for 0 indexing 

    i = int(math.floor(index/self.sqrtnum)) 
    j = int(index % self.sqrtnum) 

    surroundingTiles = [] 

    if i == 0 and j == 0: 
     #Top left corner 
     if horizontal: 
      surroundingTiles.extend((self[i + 1][j], self[i][j + 1])) 
     if vertical: 
      surroundingTiles.append(self[i + 1][j + 1]) 
    elif i >= maxtile and j == 0: 
     #Top right corner 
     if horizontal: 
      surroundingTiles.extend((self[i - 1][j], self[i][j + 1])) 
     if vertical: 
      surroundingTiles.append(self[i - 1][j + 1]) 
    elif i == 0 and j >= maxtile: 
     #Bottom left corner 
     if horizontal: 
      surroundingTiles.extend((self[i + 1][j], self[i][j - 1])) 
     if vertical: 
      surroundingTiles.append(self[i + 1][j - 1]) 
    elif i >= maxtile and j >= maxtile: 
     #Bottom right corner 
     if horizontal: 
      surroundingTiles.extend((self[i - 1][j], self[i][j - 1])) 
     if vertical: 
      surroundingTiles.append(self[i - 1][j - 1]) 

    elif i == 0: 
     #Top border 
     if horizontal: 
      surroundingTiles.extend((self[i + 1][j], self[i][j + 1], 
            self[i][j - 1])) 
     if vertical: 
      surroundingTiles.extend((self[i + 1][j + 1], 
            self[i + 1][j - 1])) 
    elif i >= maxtile: 
     #Bottom border 
     if horizontal: 
      surroundingTiles.extend((self[i - 1][j], self[i][j + 1], 
            self[i][j - 1])) 
     if vertical: 
      surroundingTiles.extend((self[i - 1][j + 1], 
            self[i - 1][j - 1])) 
    elif j == 0: 
     #Left border 
     if horizontal: 
      surroundingTiles.extend((self[i + 1][j], self[i - 1][j], 
            self[i][j + 1])) 
     if vertical: 
      surroundingTiles.extend((self[i + 1][j + 1], 
            self[i - 1][j + 1])) 
    elif j >= maxtile: 
     #Right border 
     if horizontal: 
      surroundingTiles.extend((self[i + 1][j], self[i - 1][j], 
            self[i][j - 1])) 
     if vertical: 
      surroundingTiles.extend((self[i + 1][j - 1], 
            self[i - 1][j - 1])) 

    else: 
     if horizontal: 
      surroundingTiles.extend((self[i + 1][j], self[i - 1][j], 
            self[i][j + 1], self[i][j - 1])) 
     if vertical: 
      surroundingTiles.extend((self[i + 1][j + 1], self[i + 1][j - 1], 
            self[i - 1][j + 1], self[i - 1][j - 1])) 

    return surroundingTiles 
+0

读取你的代码,它看起来像'垂直'这意味着'对角线'和'水平'实际上意味着('水平'+'垂直')。是对的吗? – jimhark

+2

http://codereview.stackexchange.com/ –

回答

2

尝试是这样的:(未测试)

# indices 0 - 3 are for horizontal, 4 - 7 are for vertical 
dij = [(0, 1), (1, 0), (0, -1), (-1, 0), 
     (1, 1), (1, -1), (-1, 1), (-1, -1)] 

def getSurroundingTiles(self, tile, horizontal = True, vertical = True): 
    index = list(self.getTiles()).index(tile) 
    maxtile = self.sqrtnum - 1 # Offset for 0 indexing 

    i = int(math.floor(index/self.sqrtnum)) 
    j = int(index % self.sqrtnum) 

    surroundingTiles = [] 

    startat = 0 if horizontal else 4 
    stopat = 8 if vertical else 4 

    for di, dj in dij[startat:stopat]: 
     if 0 <= i + di <= maxtile and 0 <= j + dj <= maxtile: 
      surroundingTiles.append(self[i + di][j + dj]) 

    return surroundingTiles 

它计算邻居指数相对使用单位的步骤,使您不必下明确键入出来。它也一次测试所有out of bounds个案。

我假设你的意思是horizontalvertical,就像horizontally and vertically adjacentdiagonally adjacent,正如代码所示。

+0

你应该把'di'和'dj'合并到一个元组列表中[[(0,1),(1,0),...]',然后你的循环可以只是'对于ni,在dij的nj [startat:stopat]:' – Duncan

+0

@Duncan对,但也许这样更具可读性? (首选项,因为您可以垂直读取列表以查看元组)。无论如何,两种方法在for循环中都需要大致相同的代码量。 – irrelephant

+0

我刚刚测试过它,它完美地工作(尽管我将函数内的di和dj赋值)。如果我分发这个信息,你想获得信用吗? – user1149589

2

以@ irrelephant的想法更进一步(它是合乎逻辑的结论或归谬法,你决定):

d = (
    ((0, 1), (1, 0), (0,-1), (-1, 0)), 
    ((1, 1), (1,-1), (-1, 1), (1,-1)) 
) 

def getSurroundingTiles(self, tile, horizontal = True, vertical = True): 
    index = list(self.getTiles()).index(tile) 
    maxtile = self.sqrtnum - 1 # Offset for 0 indexing 

    fhv = (horizontal, vertical) 
    ij = (int(math.floor(index/self.sqrtnum)), 
      int(index % self.sqrtnum)) 

    surroundingTiles = [] 
    for ihv in range(2): 
     if fhv[ihv]: 
      for k in range(4): 
       n = [sum(p) for p in zip(ij, d[ihv][k])] 
       if all([0 <= n[i] <= maxtile for i in range(2)]): 
        surroundingTiles.append(self[n[0]][n[1]]) 

    return surroundingTiles 

请注意:此代码是未经测试。

+0

@irrelephant基本上发布了类似的30秒提前重写。 – jimhark

+0

我觉得这牺牲了可读性。 – user1149589

+0

@ user1149589,是的更简洁往往不易读。用numpy书写这种类型的代码会更好。 – jimhark