首页 文章

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

提问于
浏览
1

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

NB:鲁克,骑士,主教等等都延伸了片段 .

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

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

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

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

  • 2
    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 ),与您提供的方法相比,这为您提供了可维护性优势 .

  • 1

    如果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();
    }
    

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

    return clickedSquare.piece.getLegalDestinationSquares();
    

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

  • 0

    从OOD有一些评论家 .

    • 即使字段上没有数字,字段也是字段 . 因此,无效存档(LSP)!

    • 一个数字永远不知道他能做什么动作,这必须只由游戏规则设定 . 创建一个名为 Rules 的新类 . 规则的责任是知道他可以做什么动作(SRP) . 一个国王(例如)必须知道他是否已经做了一个Castling来决定他是否可以做一个Castling,因此他必须知道之前的动作,这打破了DIP - 啊,这里我们有另一个我们想念的课: ChessNotation .
      当你继承东西时,

    • instanceof很有用,一个Rook无法继承一个字段(LSPDIP) .

相关问题