#java #инспекция_кода
Морской бой. Пишу метод для поворота корабля. tt - это текущее положение корабля: 0 - вертикально (по умолчанию) 1 - горизонтально (0 + 90°) 2 - вертикально (0 вверх ногами) 3 - горизонтально (0 - 90°) ckw - это флаг поворота: true - по часовой стрелке false - против часовой стрелки Код метода поворота: public void turn (boolean ckw) { if ((tt == 0 && !ckw) || (tt == 1 && ckw)) { //b -> c } else if ((tt == 1 && !ckw) || (tt == 2 && ckw)) { //c -> d } else if ((tt == 2 && !ckw) || (tt == 3 && ckw)) { //d -> a } else if ((tt == 3 && !ckw) || (tt == 0 && ckw)) { //a -> b } if (ckw) tt++; else tt--; } Комментариями обозначены 4 цикла for-each с логикой разворота. Мне бы вот эту лесенку if-ов сократить. Это возможно? Логика поворота Корабль представляет собой ArrayList позиций в сетке. Например, 4-палубный, находящийся в середине поля: 35, 45, 55, 65. Чтобы его повернуть по часовой стрелке, надо прибавить к каждой позиции её индекс, умноженный на 11. b -> c (90° -> 180°) или (0° -> 270°) for (int i = 0; i < col.size(); i++) { int num = col.get(i); int new_num = num + 11 * i; col.set(i, new_num); } И т.д.
Ответы
Ответ 1
Храним только базовые координаты, длину и текущее состояние разворота. Всё остальное вычисляемо из этих данных. Демка на коленке: public class Main { public static void main(String[] args) { Ship ship = new Ship(4, 1, 3, 5); // 35, ship.print(); System.out.println("Clockwise"); ship.turn(true).print(); ship.turn(true).print(); ship.turn(true).print(); ship.turn(true).print(); System.out.println("Counter-clockwise"); ship.turn(false).print(); ship.turn(false).print(); ship.turn(false).print(); ship.turn(false).print(); } } public class Ship { private int state; private int x; private int y; private int length; public Ship(int length, int initialState, int x, int y) { state = initialState; this.x = x; this.y = y; this.length = length; } public Ship turn(boolean clockwise) { if (clockwise) { state = (state + 1) % 4; } else { state = (state + 3) % 4; } return this; } public Ship print() { for (int i = 0; i < length; i++) { switch (state) { case 0: System.out.print("("+(10*x+y-i)+")"); break; // N case 1: System.out.print("("+(10*(x+i)+y)+")"); break; // E case 2: System.out.print("("+(10*x+y+i)+")"); break; // S case 3: System.out.print("("+(10*(x-i)+y)+")"); break; // W } } System.out.println(""); return this; } }Ответ 2
Мы выполняем ту или иную операцию в случае если tt == n и ckw == false или tt == n + 1 и ckw == true. Следовательно, если для случая ckw == false мы увеличим сравниваемое значение на 1, то потом нам нужно будет проверить только случай tt == n + 1. Такую цепочку проверок легко организовать при помощи оператора switch Update как поправил меня @vp_arth вместо switch (val) лучше использовать switch (val % 4). Тогда можно убрать проверку case 4: public void turn(boolean ckw) { int val = tt; if (!ckw) val++; switch (val % 4) { case 1: //b -> c break; case 2: //c -> d break; case 3: //d -> a break; case 0: //a -> b break; } if (ckw) tt++ else tt--; }Ответ 3
Если не отходить от того, что координаты корабля хранятся в ArrayList, то можно сделать так. В методе turn вычисляется новое значение tt, после чего координаты корабля считаются заново с учетом нового значения tt и фиксированной точки корабля (например, головы). public void turn(boolean ckw) { tt += ckw ? 1 : -1; tt = (tt + 4) % 4; int sign = (tt == 1 || tt == 2) ? 1 : -1; int shift = (tt % 2 == 0) ? 10 : 1; int head = col.get(0); for (int i = 1; i < col.size(); i++) { int newNum = head + sign * shift * i; col.set(i, newNum); } } Предполагается, что корабли могут быть только в виде одной линии. Также не учитывается то, что после поворота корабль может "выйти" за край поля.
Комментариев нет:
Отправить комментарий