Как объединить все похожие методы зацикливания массива? Java 1.8

#java

#java

Вопрос:

Для изучения программирования я создаю игру 2048 на Java. В игре есть класс, в котором много повторяющихся фрагментов — циклов итерации полей. Вопрос в том, возможно ли создать такой метод, который будет принимать значения границ перечисления и исполняемый код?

Что-то вроде этого как для назначения, так и для сравнения.

 public void forField(int borderX, int borderY, ??? code){
    for (int x = 0; x < borderX; x  )
        for (int y = 0; y < borderY; y  )
            do code;
}

public boolean checkField(int borderX, int borderY, ??? code, boolean default_answer){
    for (int x = 0; x < borderX; x  )
        for (int y = 0; y < borderY; y  )
            return code;
    return default_answer;
}
 

Если нет, можете ли вы порекомендовать, как улучшить мой код? Спасибо за внимание.

 public class Field {
    private int[][] field;
    private int width, heigth;

    public Field(int sizeX, int sizeY) {
        this.width = sizeX;
        this.heigth = sizeY;
        this.field = new int[sizeX][sizeY];
    }

    public int getCell(int x, int y) {
        return this.field[x][y];
    }

    public void setCell(int val, int x, int y) {
        this.field[x][y] = val;
    }

    // for restart
    public void reset() {
        for (int x = 0; x < width; x  )
            for (int y = 0; y < heigth; y  )
                this.field[x][y] = 0;
    }

    // for step cancelling function
    public void copyOf(Field f) {
        for (int x = 0; x < width; x  )
            for (int y = 0; y < heigth; y  )
                this.field[x][y] = f.getCell(x, y);
    }

    // can field changed after pressing a key
    public boolean isEqualTo(Field f) {
        for (int x = 0; x < width; x  )
            for (int y = 0; y < heigth; y  )
                if (field[x][y] != f.getCell(x, y))
                    return false;
        return true;
    }

    private boolean canMergeByY() {
        for (int x = 0; x < width; x  )
            for (int y = 0; y < heigth - 1; y  )
                if (field[x][y] == field[x][y   1])
                    return true;
        return false;
    }

    private boolean canMergeByX() {
        for (int x = 0; x < width - 1; x  )
            for (int y = 0; y < heigth; y  )
                if (field[x][y] == field[x   1][y])
                    return true;
        return false;
    }

    // checking the possibility of continuing the game
    public boolean canMerge() {
        return canMergeByX() amp;amp; canMergeByY();
    }

    // checking 0 and 2048 cells for different tasks
    public boolean contains(int i) {
        for (int x = 0; x < width; x  )
            for (int y = 0; y < heigth; y  )
                if (field[x][y] == i)
                    return true;
        return false;
    }
}
 

Ответ №1:

??? In forField может быть просто a BiConsumer<Integer, Integer> , или вы можете объявить свой собственный IntBiConsumer интерфейс, если вам не нравится бокс:

 interface IntBiConsumer {
    void accept(int i, int j);
}
 

forField затем может быть объявлен как:

 public void forField(int borderX, int borderY, IntBiConsumer code){
    for (int x = 0; x < borderX; x  )
        for (int y = 0; y < borderY; y  )
           code.accept(x, y);
}
 

copyOf затем можно записать как:

 public void copyOf(Field f) {
    forField(width, height, (x, y) -> {
        this.field[x][y] = f.getCell(x, y);
    });
}
 

checkField немного сложнее, предлагаемый вами код на самом деле не будет работать, потому что вы ничего не проверяете перед собой return во внутреннем цикле. Циклы будут зацикливаться только один раз и немедленно возвращаться. Это должно быть больше похоже:

 public boolean checkField(int borderX, int borderY, ??? condition, boolean default_answer){
    for (int x = 0; x < borderX; x  )
        for (int y = 0; y < borderY; y  )
            if (condition) 
                return !default_answer;
    return default_answer;
}
 

??? здесь может быть a BiPredicate<Integer, Integer> или ваш собственный интерфейс, подобный этому:

 interface IntBiPredicate {
    boolean test(int i, int j);
}
 

checkField затем может быть объявлено следующим образом:

 public boolean checkField(int borderX, int borderY, IntBiPredicate condition, boolean defaultAnswer){
    for (int x = 0; x < borderX; x  )
        for (int y = 0; y < borderY; y  )
            if (condition.test()) 
                return !defaultAnswer;
    return defaultAnswer;
}
 

isEqualTo может быть переписан как:

 public boolean isEqualTo(Field f) {
    return checkField(width, height, (x, y) -> field[x][y] != f.getCell(x, y), true);
}