Java中的国际象棋游戏:Square类应该有;生成可能的移动”;方法?

Java中的国际象棋游戏:Square类应该有;生成可能的移动”;方法?,java,Java,我在写一盘棋。我的基本设计是拥有一个由正方形对象组成的二维阵列(8 x 8)。正方形有许多字段:整数高度、整数宽度、工件(如果为空则为null,否则为某些类型的工件对象) 注:车,骑士,主教等,所有扩展件 现在,考虑到我的OOP设计,我有点被弄糊涂了,如何找出什么动作对给定的工件是合法的。下面是我的想法: 1) 用户点击方块 2) 我们确定哪一块在正方形上(如果为空,则返回错误消息) 3) 为那个方块上的那块产生合法的移动 我很担心编写这样的代码: if (clickedSquare.piece

我在写一盘棋。我的基本设计是拥有一个由正方形对象组成的二维阵列(8 x 8)。正方形有许多字段:整数高度、整数宽度、工件(如果为空则为null,否则为某些类型的工件对象)

注:车,骑士,主教等,所有扩展件

现在,考虑到我的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

您不需要创建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
    }
}
公共抽象类片段{
公共摘要列表getFieldsAllowed(字段);
}
公共级车扩展件{
@凌驾
公共列表getFieldsAllowed(字段){
//TODO自动生成的方法存根
返回null;
}    
}
公共类字段{
公共件getPiece(){
//获取当前片段
}
}

像这样的。试着找到你自己的解决办法。这一个并不完美。

如果Rook、Bishop等:

public class Rook extends Piece {
    @Override
    public String getLegalDestinationSquares() {
       // returns all leagal Rook squers 
       return null;
    }
}
这一部分是:

public abstract class Piece {
    public abstract String getLegalDestinationSquares();
}
然后您可以这样做(在您的示例中):

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

公共最终类点{
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
    }
}
公共最终int x,y; 公共点(整数x,整数y){ 这个.x=x; 这个。y=y; } } 公共抽象类文章{ 专用点位置; 受保护件(点首字母){ 这个位置=初始位置; } 公共点getLocation(){return location;} 公共点设置位置(点位置){this.location=location;} 公共摘要列表getLegalMoves(); } 公共末级车{ 公共车(点首字母){ 超级(首字母); } 公共列表getLegalMoves(){ //你知道现在的位置,你知道你是一辆车, //所以你有所有你需要确定的可能点 //这辆车可以去 } }
然后在其他代码中,您可以执行以下操作:

List<Point> legalMoves = clickedSquare.piece.getLegalMoves();
List legalMoves=单击square.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
    }
}
public final class Rook{
//建造师等。
公共列表getLegalMoves(){
return Rook.getLegalMoves(getLocation());
}
公共静态列表getLegalMoves(点开始){
//您知道位置(开始),并且您知道此方法适用于Rook,
//因此,您已经具备了确定可能的终点所需的一切
}
}
但是,如果不需要该静态方法,则不要使用甚至不要编写它(或者至少不要在类的API中公开它)。否则,类的用户将开始滥用它,最终将按照您在“开始”帖子中提供的方式编写代码——这是不计其数的if elses


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

来自OOD的一些批评者

  • 即使场上没有人物,场也是场。因此,空字段不存在()
  • 一个人永远不知道他能做什么动作,这只能由游戏规则来设定。创建一个名为
    Rules
    的新类。规则有责任知道他能做什么动作。一个国王(例如)必须知道他是否已经做了一次掷骰来决定他是否可以做一次掷骰,因此他必须知道之前的动作,这打破了-啊,这里我们错过了另一个类:
    ChessNotation
  • instanceof在继承内容时很有用,Rook不能继承字段(,)
    你的代码正在编译吗?基本上你是在定义工厂。。。那么,它有什么问题吗?单击square.piece.getLegalDestinationSquares(单击square)怎么样?i、 e.创建一个在
    Piece
    的每个子类型中定义的重载方法,我会将isLegalMove(Piece,Square)放入ChessBoard类。创建一个抽象父类,该父类具有方法
    getlegaldestationsquares
    ,并让每个不同的片段实现它。
    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
        }
    }