这段代码的逻辑如何被抽象出来?

问题描述:

以下方法用于确定棋子是否被阻止进行某种移动。在调用此方法时,运动本身(即主教的对角移动能力)已经得到验证 - 此方法将查看片段必须采用的“路径”。这段代码的逻辑如何被抽象出来?

如同痛苦地清楚,这种方法充满了冗余。实际上,有6个几乎相同的for循环,区别在于1)哪些变量控制迭代,2)变量是递增还是递减,以及3)在对角运动的情况下,包含一个声明同时增加/减少x和y变量。

我已经做了很多尝试,将这些语句抽象成单独的方法。不幸的是,限制因素一直需要访问董事会[y] [x] - 当我试图抽象逻辑时,我忽视了,其中变量代表y和哪个x。

所以,我的问题是:Java可以提供什么工具来抽象这个逻辑并减少或消除这种方法中的冗余?我会指出,我对这门语言很陌生,所以请不要把我对普通习语的漠视看成是故意的或者简单的钝化;我在学!

谢谢。

private static boolean notBlocked(Piece[][] board, int xfrom, int yfrom, int xto, int yto) { 

    int x = xfrom; 
    int xstop = xto; 
    int y = yfrom; 
    int ystop = yto; 

    int xinc = (x < xstop) ? 1 : -1; 
    int yinc = (y < ystop) ? 1 : -1; 

    Piece to = board[yto][xto]; 
    Piece from = board[yfrom][xfrom]; 

    if (xfrom == xto) { 
     // x is constant, check in y direction 
     if (y <= ystop) { 
      for (; y <= ystop; y += yinc) { 
       if (board[y][x] != null && board[y][x] != to && board[y][x] != from) { 
        return false; 
       } 
      } 
     } else { 
      for (; y >= ystop; y += yinc) { 
       if (board[y][x] != null && board[y][x] != to && board[y][x] != from) { 
        return false; 
       } 
      } 
     } 
    } else if (yfrom == yto) { 
     // y is constant, check in x direction 
     if (x <= xstop) { 
      for (; x <= xstop; x += xinc) { 
       if (board[y][x] != null && board[y][x] != to && board[y][x] != from) { 
        return false; 
       } 
      } 
     } else { 
      for (; x >= xstop; x += xinc) { 
       if (board[y][x] != null && board[y][x] != to && board[y][x] != from) { 
        return false; 
       } 
      } 
     } 
    } else if (Math.abs(xfrom - xto) == Math.abs(yfrom - yto)){ 
     // the move is diagonal 
     if (y <= ystop) { 
      for (; y <= ystop; y += yinc) { 
       if (board[y][x] != null && board[y][x] != to && board[y][x] != from) { 
        return false; 
       } 
       x += xinc; 
      } 
     } else { 
      for (; y >= ystop; y += yinc) { 
       if (board[y][x] != null && board[y][x] != to && board[y][x] != from) { 
        return false; 
       } 
       x += xinc; 
      } 
     } 
    } 
    return true; 
} 

编辑:

哇...现在好多了!

private static boolean notBlocked(Piece[][] board, int xfrom, int yfrom, int xto, int yto) { 

    Piece from = board[yfrom][xfrom]; 
    Piece to = board[yto][xto]; 

    // Determine the direction (if any) of x and y movement 
    int dx = (xfrom < xto) ? 1 : ((xfrom == xto) ? 0 : -1); 
    int dy = (yfrom < yto) ? 1 : ((yfrom == yto) ? 0 : -1); 

    // Determine the number of times we must iterate 
    int steps = Math.max(Math.abs(xfrom - xto), Math.abs(yfrom - yto)); 

    if (xfrom == xto || yfrom == yto || Math.abs(xfrom - xto) == Math.abs(yfrom - yto)) { 
     for (int i = 1; i < steps; i++) { 
      int x = xfrom + i * dx; 
      int y = yfrom + i * dy; 
      if (isBlocked(board, from, to, x, y)) { 
       return false; 
      } 
     } 
    } 
    return true; 
} 

想想在正确的方向上按照一个步骤写这个函数。假设你可以填写两个变量dx和dy,它们代表你在每一步的x和y方向上移动了多少。您可以通过查看开始和结束x和y位置之间的差异来计算此值。一旦你有了,你可以编写一个单一的for循环,尝试沿着这个方向移动,检查每一步。例如:

for (int i = 1; i < numStepsRequired; i++) { 
    int currX = x + i * dx; 
    int currY = y + i * dy; 
    if (board[currY][currX] != null) { 
     return false; 
    } 
} 

您还需要计算多少步是必需的,这也将是简单的,只要你计算dx和dy。因为这是很好的编程习惯,所以我会把它作为练习。

希望这会有所帮助!

+0

谢谢!这是一个明显的优点。我欣赏方向。 – 2012-03-02 23:05:46