2012-03-02 11 views
2

チェスピースが特定の動きをしないようにブロックされているかどうかを判断するには、次の方法が使用されます。このメソッドが呼び出された時点で、モーション自体(つまり、ビショップの対角線移動能力)は既に検証済みです。このメソッドは、そのピースが受けなければならない「パス」を調べます。このスニペットのロジックはどのように抽象化できますか?

わかりやすく、この方法は冗長性に満ちています。実際には、6つのほぼ同じfor-loopsがあります。その違いは、1)どの変数が反復を制御しているか、2)変数が増減しているかどうか、3)対角線方向の動きの場合は、 xと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; 
} 

EDIT:今より良い

うわー!

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; 
} 

答えて

2

この機能を正しい方向に1ステップ書くと考えてください。各ステップでxとy方向にどれだけ移動するかを表す2つの変数dxとdyを入力できるとします。これは、開始位置と終了位置の違いを調べることで計算できます。一度それを持っていれば、その方向に沿って移動しようとする単一の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

ありがとうございました!これは明らかに優れた見通しです。私は方向を感謝します。 –

関連する問題