Как избавиться от множества If

137
19 декабря 2020, 01:20
 @Override
public List<Position> aviableMove() {
    List<Position> positionList = new ArrayList<>();
    for (int i = 1; i <= 7; i++) {
        if ((x + i) <= 7 && f[x + i][y] == null) {
            positionList.add(new Position((x + i), y));
        } else break;
    }
    for (int i = 1; i <= 7; i++) {
        if ((x - i) >= 0 && f[x - i][y] == null) {
            positionList.add(new Position((x - i), y));
        } else break;
    }
    for (int i = 1; i <= 7; i++) {
        if ((y + i) <= 7 && f[x][y + i] == null) {
            positionList.add(new Position(x, (y + i)));
        } else break;
    }
    for (int i = 1; i <= 7; i++) {
        if ((y - i) >= 0 && f[x][y - i] == null) {
            positionList.add(new Position(x, (y - i)));
        } else break;
    }
    return positionList;
}

этот метод-логика фигуры ладья из шахмат,метод возвращает все возможные ходы для фигуры по текущему ее местоположению.Я вижу что код по сути дублируется ,но ничего не могу придумать ,чтобы не дублировать.Грубо говоря сверху вниз-первый цикл проверяет по оси х вправо,потом по оси х влево и последние два цикла тоже самое с осью у.Сам иф записывает все клетки до тех пор пока не наткнется на клетку с фигурой - после этого вываливается из цикла вопрос как мне избежать этих повторов?

Answer 1

Пришлось изменить код , чтобы можно было его сделать лаконичнее:

 public static void iterate(Set<Position> positions, int px, int py){
    for (int i = 1; i <= 7; i++) {
        int mx = Math.max(0, Math.min(x + px*i, 7));
        int my = Math.max(0, Math.min(y + py*i, 7));
        // в реальной жизни вторая проверка не нужна, 
        // т.к. в этом месте стоит текущая фигура и первая проверка не пройдет
        if (f[mx][my] == null && !(mx==x && my==y)) 
            positions.add(new Position(mx, my));
        else break;
    }
}
public static Set<Position> aviableMove2() {
    Set<Position> positionList = new HashSet<>();
    iterate(positionList, 1,0);
    iterate(positionList, 0,1);
    iterate(positionList, -1,0);
    iterate(positionList, 0,-1);
    return positionList;
}

Простыня которой тестировал:

import java.util.HashSet; 
import java.util.Objects; 
import java.util.Set; 
 
public class CheckMate { 
 
    static Figure f[][] = new Figure[8][8]; 
 
    static int x, y; 
     
 
    public static void iterate(Set<Position> positions, int px, int py){ 
        for (int i = 1; i <= 7; i++) { 
            int mx = Math.max(0, Math.min(x + px*i, 7)); 
            int my = Math.max(0, Math.min(y + py*i, 7)); 
            if (f[mx][my] == null && !(mx==x && my==y)) 
                positions.add(new Position(mx, my)); 
            else break; 
        } 
    } 
 
    public static Set<Position> aviableMove() { 
        Set<Position> positionList = new HashSet<>(); 
        for (int i = 1; i <= 7; i++) { 
            if ((x + i) <= 7 && f[x + i][y] == null) { 
                positionList.add(new Position((x + i), y)); 
            } else break; 
        } 
        for (int i = 1; i <= 7; i++) { 
            if ((x - i) >= 0 && f[x - i][y] == null) { 
                positionList.add(new Position((x - i), y)); 
            } else break; 
        } 
        for (int i = 1; i <= 7; i++) { 
            if ((y + i) <= 7 && f[x][y + i] == null) { 
                positionList.add(new Position(x, (y + i))); 
            } else break; 
        } 
        for (int i = 1; i <= 7; i++) { 
            if ((y - i) >= 0 && f[x][y - i] == null) { 
                positionList.add(new Position(x, (y - i))); 
            } else break; 
        } 
        return positionList; 
    } 
 
    public static void main(String[] args) { 
        for (int i=0; i<8; i++) 
            for (int j=0; j<8; j++) 
                test(i, j); 
    } 
 
    static void test(int tx, int ty) { 
        x = tx; 
        y = ty; 
        Set<Position> moves1 = aviableMove(); 
        Set<Position> moves2 = aviableMove2(); 
        boolean eq = moves1.containsAll(moves2) && moves2.containsAll(moves1); 
        System.out.println("test x=" + tx + " y=" + ty + " " + eq); 
        if (eq)return; 
        System.out.println(moves1); 
        System.out.println(moves2); 
        System.out.println("---"); 
 
    } 
 
 
 
    public static Set<Position> aviableMove2() { 
        Set<Position> positionList = new HashSet<>(); 
        iterate(positionList, 1,0); 
        iterate(positionList, 0,1); 
        iterate(positionList, -1,0); 
        iterate(positionList, 0,-1); 
        return positionList; 
    } 
 
    static private class Position { 
 
        private final int x; 
        private final int y; 
 
        public Position(int x, int y) { 
            this.x = x; 
            this.y = y; 
        } 
 
        @Override 
        public String toString() { 
            return "[" + x + "," + y + "]"; 
        } 
 
        @Override 
        public boolean equals(Object o) { 
            if (this == o) return true; 
            if (o == null || getClass() != o.getClass()) return false; 
            Position position = (Position) o; 
            return x == position.x && 
                    y == position.y; 
        } 
 
        @Override 
        public int hashCode() { 
            return Objects.hash(x, y); 
        } 
    } 
 
    static private class Figure {} 
}

Answer 2

Вот мой метод, который правда генерирует Set возможных ходов.

public Set<Move> generateMoves(Position curPos) {
    Set<Move> moves = new HashSet<Move>();
    int curCol = curPos.getCol();
    int curRow = curPos.getRow();
    for (int dx = -1; dx <= 1; dx++) {
        for (int dy = -1; dy <= 1; dy++) {
            if (Math.abs(dx) != Math.abs(dy)) {
                int destCol = curCol + dx;
                int destRow = curRow + dy;
                while (ChessUtils.posBoundsTest(destRow, destCol)) {
                    Position destPos = new Position(destRow, destCol);
                    moves.add(new Move(curPos, destPos));
                    destCol = destCol + dx;
                    destRow = destRow + dy;
                }
            }
        }
    }
    return moves;
}

curCol - это по вашему x, curRow - y

public class ChessUtils {
    public static boolean posBoundsTest(int row, int col) {
        return row >= 0 && row < 8 && col >= 0 && col < 8;
    }
}

Разберетесь или "перевести"?

READ ALSO
Аналог ref в spring @Configuration

Аналог ref в spring @Configuration

@Configuration позволяет внутренние зависимостиОзначает ли это, что вызвав метод создания одного бина из другого, можно сымитировать поведение...

115
Как в JSP вывести одну из трех таблиц

Как в JSP вывести одну из трех таблиц

Подскажите, а то уже всю голову сломал! Задача: У меня есть три таблицы, с помощью "поля со списком" я должен выбрать одну из них и в цикле вывести:

102
Выводить дату на английском

Выводить дату на английском

Выводит четверг, а надо на английском

102