国际象棋:运动验证中的重复代码-Java

时间:2019-01-02 13:43:29

标签: java duplicates chess

我目前正在学习Java并从事课堂作业。我们应该制作国际象棋的“怪异版本”。 就像在原始国际象棋中一样,如果有棋子移动,棋子也不会移动,最明显的例外是马,它可以跳过除国王以外的所有棋子。

我有一个抽象类Piece,该类被所有作品类型所继承,每种类型都有各自的移动规则。他们中的大多数人都有这种运动限制,因此我在此类中定义了方法:

    public boolean freeWayHorizontally(int xO, int yO, int xD) {
    //RIGHT
    if (xO < xD) {
        for (int x = xO + 1; x < xD; x++) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO);
            if (thereIsPiece != null){
                return false;
            }
        }
    //LEFT
    } else if (xO > xD) {
        for (int x = xO - 1; x > xD; x--) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO);
            if (thereIsPiece != null){
                return false;
            }
        }
    }
    return true;
}

public boolean freeWayVertically(int xO, int yO, int yD) {
    //UP
    if (yO < yD) {
        for (int y = yO + 1; y < yD; y++) {
            CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(xO, y);
            if (thereIsPiece != null){
                return false;
            }
        }
    //DOWN
    } else if (yO > yD) {
        for (int y = yO - 1; y > yD; y--) {
            CrazyPiece thereIsPiece = Simulador.checkIfThereIsPiece(xO, y);
            if (thereIsPiece != null){
                return false;
            }
        }
    }
    return true;
}

thereIsPiece(int x, int y)是国际象棋Simulator类的函数,给定棋盘上的某个位置,则将棋子返回该位置。

很明显,这两个接收相同的参数(原点坐标和目标坐标,其中目标坐标之一是工件的原点坐标之一),因此唯一真正改变的是{{1} } 叫做。 编辑:因此,它们被标记为重复项,根据我的告诉,这非常糟糕!

但是,我似乎无法找出一种仅使用以下方法之一来解决此问题的方法; 还可以编辑:我尝试过重载它,但是它只能垂直或水平地工作(可能做错了)。

问题是我需要分别完成这些操作以实现Horse的移动,从而覆盖以下方法:

thereIsPiece()

然后调用自己的移动检查类型,该检查类型也在public boolean freeWayHorizontally(int xO, int yO, int xD) { //Overriden by the Horse class //RIGHT if (xO < xD) { for (int x = xO + 1; x <= xD; x++) { CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO); if (thereIsPiece != null && thereIsPiece.isKing){ return false; } } //LEFT } else if (xO > xD) { for (int x = xO - 1; x >= xD; x--) { CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(x, yO); if (thereIsPiece != null && thereIsPiece.isKing){ return false; } } } return true; } public boolean freeWayVertically(int xO, int yO, int yD) { //Overriden by the Horse class //UP if (yO < yD) { for (int y = yO + 1; y <= yD; y++) { CrazyPiece thereIsPiece = Simulador.checkIfTheresPiece(xO, y); if (thereIsPiece != null && thereIsPiece.isKing){ return false; } } //DOWN } else if (yO > yD) { for (int y = yO - 1; y >= yD; y--) { CrazyPiece thereIsPiece = Simulador.checkIfThereIsPiece(xO, y); if (thereIsPiece != null && thereIsPiece.isKing){ return false; } } } return true; } 类中定义:

Piece

如何避免所有这些重复,甚至使这些验证更好?

1 个答案:

答案 0 :(得分:0)

代码的第一个问题是您在Simulador类上使用不同的方法来检查位置:

// When is checking horizontally
CrazyPiece thereIsPiece = Simulador.pegaPecaPorCoordenada(x, yO);

// When is checking vertically
CrazyPiece thereIsPiece = Simulador.checkIfThereIsPiece(xO, y);

我不明白为什么这不应该是一个单一方法。

我在这里可以看到2个不同的改进点:

  1. 重写循环的开始和结束,使其只有一个循环。

例如:

public boolean freeWayHorizontally(int xO, int yO, int xD) {
    int destination = xD;
    int origin = xO + 1;
    if (xO > xD) {
        destination = xO - 1;
        origin = xD;
    }

    for (int x = origin; x < destination; x++) {
        CrazyPiece thereIsPiece = Simulador.pegaPecaPorCoordenada(x, yO);
        if (thereIsPiece != null){
            return false;
        }
    }

    return true;
}

当原点位于目的地之前时,您将从原点移到目的地。

当目的地在起点之前时,您只需交换并从目的地移至起点。

  1. 第二点是检查条件。

我认为您应该添加一个方法:

private boolean checkPositionIsFree(int x, int y) {
    return Simulador.pegaPecaPorCoordenada(x, y) != null;
}

现在,在不能合并这两种方法之前,您需要水平放置一个,垂直放置一个。

然后您可以像这样重写您的方法:

public boolean freeWayHorizontally(int xO, int yO, int xD) {
    int destination = xD;
    int origin = xO + 1;
    if (xO > xD) {
        destination = xO - 1;
        origin = xD;
    }

    for (int x = origin; x < destination; x++) {
        if (checkPositionIsFree(x, yO)){
            return false;
        }
    }

    return true;
}

对于马来说,您只需@Override checkPositionIsFree()方法就具有适当的条件(在国王身上加支票),一切都会正常工作。

更新

要完全涵盖马箱,您可以使用一种处理输入数据的方法:

@Override
public boolean freeWayHorizontally(int xO, int yO, int xD) {
    return super.freeWayHorizontally(xO, yO, xD + 1);
}

通过这种方式,您可以避免重写所有代码。

  

顺便说一句,您的代码在这里有一些错别字,也许您可​​以重写它。最好检查这类事情,并拥有有效的代码(在您的情况下)或确切的代码失败,以避免由于错误的错误而浪费vouluntiers时间。