Java中的国际象棋游戏:方形类应该“产生可能的移动”方法吗?

时间:2015-01-08 12:46:02

标签: java

我正在写一个国际象棋游戏。我的基本设计是有一个由方形物体组成的二维阵列(8 x 8)。正方形有许多字段:int height,int width,Piece piece(如果为空则为null,否则为某种类型的Piece对象。

NB:Rook,Knight,Bishop等等都延伸到了片段。

现在,考虑到我的OOP设计,我有点想知道如何确定哪些动作对于给定的作品是合法的。这就是我的想法:

1)用户点击方块 2)我们确定方块上的块(如果为空,则返回错误消息) 3)在该广场上为该作品生成合法动作

我担心写代码如下:

if (clickedSquare.piece.instanceOf(Rook)) {
    return Rook.getLegalDestinationSquares(clickedSquare);
} else if (clickedSquare.piece.instanceOf(Bishop)) {
    return Bishop.getLegalDestinationSquares(clickedSquare);
} else if...

这看起来真的很糟糕。必须有一种方法可以做到更好地符合OOP,但我还在学习。

感谢您的帮助, Mariogs

4 个答案:

答案 0 :(得分:2)

您不需要创建 if 语句。只需获取该字段上的当前部分并调用某些方法(getLegalMoves())或其他方法。 如果字段为空 - 返回允许移动的空列表。

public abstract class Piece {

    public abstract List<Field> getFieldsAllowed(Field field);
}
public class Rook extends Piece {

    @Override
    public List<Field> getFieldsAllowed(Field field) {
        // TODO Auto-generated method stub
        return null;
    }    
}
public class Field {

    public Piece getPiece() {
        // get current piece
    }
}

像这样的东西。尝试找到自己的解决方案。这个并不完美。

答案 1 :(得分:1)

public final class Point {
    public final int x, y;

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

public abstract class Piece {
    private Point location;

    protected Piece (Point initial){
        this.location = initial;
    }

    public Point getLocation(){ return location; }

    public Point setLocation(Point location){ this.location = location; }

    public abstract List<Point> getLegalMoves ();
}

public final class Rook {
    public Rook (Point initial){
        super(initial);
    }

    public List<Point> getLegalMoves (){
         // you know the current location, and you know you are a Rook,
         // so you have all you need to determine the possible points where
         // this Rook can go to
    }
}

然后在其他代码中,你可以这样做:

List<Point> legalMoves = clickedSquare.piece.getLegalMoves();

显然可以抽象出它所采用的实际作品。

如果您确实需要静态方法用于其他目的,可以在每个类中定义它们,例如Rook。将实例方法委托给静态方法以避免代码重复。像这样:

public final class Rook {
    // constructor etc.

    public List<Point> getLegalMoves (){
         return Rook.getLegalMoves (getLocation());
    }

    public static List<Point> getLegalMoves(Point start){
         // you know the location (start), and you know this method is for a Rook,
         // so you have all you need to determine the possible end points
    }
}

但是,如果您不需要静态方法,请不要使用,甚至不要编写它(或者至少不要在类的API中公开它)。否则,您的课程用户将开始滥用它,最终将编写您在开始帖子中提供的代码 - 那些无数的if-elses。

通过使用此解决方案,您可以在将来添加更具体的子类(PawnKing,...),而无需触及任何现有代码(现在作用于Piece) ,与您提供的方法相比,这为您提供了可维护性优势。

答案 2 :(得分:0)

如果Rook,Bishop等是:

public class Rook extends Piece {
    @Override
    public String getLegalDestinationSquares() {
       // returns all leagal Rook squers 
       return null;
    }
}

和Piece是:

public abstract class Piece {
    public abstract String getLegalDestinationSquares();
}

然后你可以这样做(在你的样本中):

return clickedSquare.piece.getLegalDestinationSquares();

返回字符串只是示例,可能您应该返回正方形集合。

答案 3 :(得分:0)

从OOD有一些评论家。

  1. 即使字段上没有数字,字段也是字段。因此,空字段不存在(LSP)!
  2. 一个人物永远不知道他能做什么动作,这只能由游戏规则设定。创建一个名为Rules的新类。规则的责任是知道他可以做什么动作(SRP)。一个国王(例如)必须知道他是否已经做了一个Castling来决定他是否可以做一个Castling,因此他必须知道之前的动作,这打破了DIP - 啊,这里我们还有另一个我们想念的课程:ChessNotation
  3. instanceof在您继承事物时非常有用,Rook无法继承字段(LSPDIP)。