2010-11-30 9 views
2

私はJavaでチェスゲームを作っていて、移動中のピースのパスをブロックしているピースがないことを確認するためにテストしています。ピースは(srcx、srcY)から(dstX、dstY)に移動します。このコードを単純化するにはどうすればよいですか? (チェスゲームの妨害テスト)

私はルークのために障害物があるかどうかをチェックする。このコードは書いている:任意のアイデアは...

if(dstY == srcY) { 

      // No change on Y axis, so moving east or west 

      if(dstX > srcX) { 
       // Moving east 
       // Test every cell the piece will pass over 
       for(int x = srcX+1; x < dstX; x++) { 
        // Is the cell set? 
        if(isPiece(x, srcY)) { 
         return true; 
        } 
       } 
      } else { 
       // Must be moving west 
       // Test every cell the piece will pass over 
       for(int x = srcX-1; x > dstX; x--) { 
        // Is the cell set? 
        if(isPiece(x, srcY)) { 
         return true; 
        } 
       } 
      } 

     } else if(dstX == srcX) { 

      // No change on X axis, so moving north or south 

      if(dstY > srcY) { 
       // Moving north 
       // Test every cell the piece will pass over 
       for(int y = srcY+1; y < dstY; y++) { 
        // Is the cell set? 
        if(isPiece(srcX, y)) { 
         return true; 
        } 
       } 
      } else { 
       // Must be moving south 
       // Test every cell the piece will pass over 
       for(int y = srcY-1; y > dstY; y--) { 
        // Is the cell set? 
        if(isPiece(srcX, y)) { 
         return true; 
        } 
       } 
      } 
     } 

を、それは少し大きいですし、私はそれが簡体ことができると確信していますか?

ps、これは唯一の妨害試験です。私はすでに他のすべてを検証しました。

+0

ナイトとキャスティングの特別なケースはありませんか?それともすでに他の場所で扱っていますか? –

答えて

4

方向をテストしたら、dx、dyの値を設定できます(例:dx = 1、dy = 0 =東)。次に、すべてのケースに対して1つのforループを作成し、各反復でそれぞれxとyをdxとdyだけインクリメントします。

あなたはその後、方向は次のようにチェックを簡素化することができます:

if dstY == srcY: dy = 0 
else: dy = (dstY - srcY)/abs(dstY - srcY) 
if dstX == srcX: dx = 0 
else: dx = (dstX - srcX)/abs(dstX - srcX) 

コード:

int dx, dy; 
if (dstY == srcY) dy = 0; 
else dy = (dstY - srcY)/Math.abs(dstY - srcY); 
if (dstX == srcX) dx = 0; 
else dx = (dstX - srcX)/Math.abs(dstX - srcX); 

while (srcX != dstX || srcY != dstY) { 
    srcX += dx; srcY += dy; 
    if (isPiece(srcX, srcY)) 
    return true; 
} 
return false; 

がまた動きが垂直、水平でない場合は、このコード(とあなたが)失敗することを注意してくださいまたは対角線上にある。 (私は手にコンパイラを持っていないとしてテストされていない)

+1

この行 'dy =(dstY-srcY)/(dstY-srcY)'は常に1となるので間違っています。absを必要とするか、@aixのような比較を行います。 –

+0

@Paul Fixed ....... – marcog

+0

ありがとうございます。また、||正しくない? – Matt

2

あなたはこれらの線に沿って何かを行うことができます:

 
int dx = 0; 
int dy = 0; 
if (dstX != srcX) { 
    dx = (dstX > srcX) ? 1 : -1; 
} else if (dstY != srcY) { 
    dy = (dstY > srcY) ? 1 : -1; 
} 
int x = srcX + dx; 
int y = srcY + dy; 
while (x != dstX || y != dstY) { 
    if (isPiece(x, y)) return true; 
    x += dx; 
    y += dy; 
} 
0

まず、テストを書きます。たくさんのテスト。そうすれば、コードの意味を変えずに単純化していると確信することができます。

ユニットテストのないリファクタリングは、安全ネットなしでハイワイヤーを歩くようなものです。

0

ほぼ同じですが、forループを持つ:

// move along x axis 
for (int x = 1; x < Math.abs(srcX - dstX); x++) { 
    int curX = (srcX - dstX) < 0 ? srcX - x : srcX + x; 
    if (isPiece(curX, srcY)) 
     return true; 
} 
// move along y axis 
for (int y = 1; y <= Math.abs(srcY - dstY); y++) { 
    int curY = (srcY - dstY) < 0 ? srcY - y : srcY + y; 
    if (isPiece(srcX, curY)) 
     return true; 
} 
0

マイsoultionは次のようになります。方向クラスを導入し、このスタイルでチェックを行います。 isBlocked(startPossition、方向、numberOfFields)

私は、3つのクラスを使用して少しの例を行いました。

  • 方向は - 、一人の線状移動を表す(startPossition - 位置
  • LinarMoveのxとyの値 - 列挙は(対角線垂直、水平2、2、4)
  • 位置を8つの方向を表すために方向、numberOfFields)とisBlockedMethod

に列挙型が含ま:

public enum Direction { 

    UP(0, 1), 
    DOWN(0, -1), 
    LEFT(1, 0), 
    RIGHT(-1, 0), 

    UP_LEFT(UP, LEFT), 
    UP_RIGTH(UP, RIGHT), 
    DOWN_LEFT(DOWN, LEFT), 
    DOWN_RIGHT(
      DOWN, RIGHT); 

    private final int incrementX; 
    private final int incrementY; 


    private Direction(int incrementX, int incrementY) { 
     this.incrementX = incrementX; 
     this.incrementY = incrementY; 
    } 

    private Direction(Direction sub1, Direction sub2) { 
     this.incrementX = sub1.incrementX + sub2.incrementX; 
     this.incrementY = sub1.incrementY + sub2.incrementY; 
    } 

    public Position oneField(Position start) { 
     return new Position(start.getX() + this.incrementX, start.getY() 
       + this.incrementY); 
    } 
} 

第2のコンストラクタを実行することは、対話的な動きをより読みやすい方法で書くことを目的とすることに過ぎない。あなたはそれを取得する方法小規模見ることができ、そしてそれがどのように読めるになる -

public class Position { 
    private final int x; 
    private final int y; 

    public Position(int x, int y) { 
     super(); 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    @Override 
    public String toString() { 
     return "x:" + x + ", y:" + y; 
    } 
} 

移動はisBlockedメソッドが含まれています。文が残っていれば、少なくとも1つの方向関連はありません。

名前LinareMoveは、他の種類の騎士の動きが可能であることを認めています。

public class LinearMove { 

    private final Position start; 
    private final Direction direction; 

    /** Length of the move. */ 
    private final int numberOfFields; 

    public LinearMove(Position start, Direction direction, int numberOfFields) { 
     super(); 
     this.start = start; 
     this.direction = direction; 
     this.numberOfFields = numberOfFields; 
    } 

    boolean isBlocked() { 
     Position pos = this.start; 
     for (int i = 0; i < (this.numberOfFields - 1); i++) { 
      pos = this.direction.oneField(pos); 
      if (isPiece(pos)) { 
       return true; 
      } 
     } 
     return false; 
    } 

    boolean isPiece(Position pos) { 
     //Dummy; 
     System.out.println(pos); 
     return false; 
    } 
} 

そしてこれは、それがどのように動作するかです:

public static void main(String[] args) { 
    new LinearMove(new Position(1, 1), Direction.RIGHT, 3).isBlocked(); 
    } 

あなたは多分騎士動きはprobemのいくつかの種類であること、気づきました。このソウルティションでは、次の2つの方法でモデル化できます。

- 4 special Directions 
- an other kind of move class (this is the more cleaner way, because you could always return true, in the isBockedMethod) 
関連する問題