#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); } } Предполагается, что корабли могут быть только в виде одной линии. Также не учитывается то, что после поворота корабль может "выйти" за край поля.
Комментариев нет:
Отправить комментарий