Страницы

Поиск по вопросам

пятница, 10 января 2020 г.

Как сократить слишком длинное выражение в условии if?

#python


if sea_player[x1 + 1][y1] != 'S' and sea_player[x1][y1 + 1] != 'S' and sea_player[x1
+ 1][y1 + 1] != 'S' and sea_player[x1 - 1][y1 ] != 'S' and sea_player[x1][y1 - 1] !=
'S' and sea_player[x1 - 1][y1 - 1] != 'S' and sea_player[x1 + 1][y1 - 1] != 'S' and
sea_player[x1 - 1][y1 + 1] != 'S' and sea_player[x1 - 1][y1 - 1]:


можно ли сократить этот участок кода?

p.s. пишу морской бой на питоне с использованием коммандной строки.
это условие проверяет,не граничит ли одноклеточный корабль при его установке с другими
кораблями на поле(список из списков)
    


Ответы

Ответ 1



Сам список смещений для соседних ячеек лучше генерировать, чем руками писать: adjacent_vector = [(x,y) for x in range(-1,2) for y in range(-1,2) if not (x == 0 and y == 0)] Тогда точно не пропустите или не продублируете какое-то направление. Кстати у вас дважды проверяется одна и та же ячейка sea_player[x1 - 1][y1 - 1] != 'S'. Список смещений можно один раз создать на все время работы программы. Далее с помощью генератора и встроенной функции any можно проверить наличие 'S' в ячейках. Примерный код (не учитывает выход за границы вашего поля): adjacent_vector = [(x,y) for x in range(-1,2) for y in range(-1,2) if not (x == 0 and y == 0)] adjacent_cells = (sea_player[x1 + a[0]][y1 + a[1]] == 'S' for a in adjacent_vector) if any(adjacent_cells): print 'found' Функция any прекратит работу как только будет найдена первая ячейка с 'S', чтобы не тратить время на остальные ячейки (и генератор вместо списка здесь по той же причине).

Ответ 2



Можно представить поле так: 0 0 S 0 0 0 0 S 0 Так как у вас условие одно и большое, то этот квадрат можно представить не как двумерный, а как одномерный массив: 0 0 S 0 0 0 0 S 0. Если карта - это двумерный массив map и координаты x, y - это центра квадрата для проверки, то получить одномерный можно операцией среза. В данном случае поле 5х5 и проверяем точку прямо по центру. import itertools my_map = [[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 1, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 0, 0]] y = 2 x = 2 current = my_map[x][y] my_map[x][y] = 'CURRENT' arr = itertools.chain(*[row[max(x - 1, 0): x + 2] for row in map[max(y - 1, 0): y + 2]]) print(1 in arr) my_map[x][y] = current Лишний массив можно и не инициализировать. Замена текущей клетки нужна, чтобы исключить клетку из рассмотрения без сложных формул или условий. Здесь было использовано несколько операторов: 1) Оператор среза ":" (slice). Пример использования: l = ['a', 'b', 'c', 'd', 'e', 'f'] print(l[2:4]) >>> ['c', 'd'] 2) Оператор распаковки коллекции "*" (doc): l = ['a', 'b', 'c', 'd', 'e', 'f'] print(*l) a b c d e f Суть оператора в том, что массив l превратился в 6 различных значений (был 1 список - стало 6 элементов без списка). 3) Функция chain из модуля itertools - склеивает массивы в один (doc): l = itertools.chain(['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'i', 'o']) print(list(l)) >>> ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i', 'o'] 4) Оператор in, который проверяет входит ли элемент в коллекцию или нет (doc): l = ['a', 'b', 'c', 'd', 'e', 'f'] print('a' in l) print('z' in l) >>> True >>> False

Ответ 3



Решение первое - вынести проверку в отдельную функцию, при этом имя функции будет самодокументировать код сообщая что она выполняет. Второе - просто нормально отформатировать: if sea_player[x1 + 1][y1 ] != 'S' and sea_player[x1 ][y1 + 1] != 'S' and sea_player[x1 + 1][y1 + 1] != 'S' and sea_player[x1 - 1][y1 ] != 'S' and sea_player[x1 ][y1 - 1] != 'S' and sea_player[x1 - 1][y1 - 1] != 'S' and sea_player[x1 + 1][y1 - 1] != 'S' and sea_player[x1 - 1][y1 + 1] != 'S' and sea_player[x1 - 1][y1 - 1] != 'S' : Можно придумать другие более изошренные способы, на которые вы, видимо, и расчитывали задавая вопрос. Но они только ненужно усложнят код.

Ответ 4



Можно так перебрать (с проверкой на выход из диапазона): for i in range(x1 - 1, x1 + 2): for j in range(y1 - 1, y1 + 2): if ((i < 0) or (j < 0)) or (i >= len(sea_player) or j >= len(sea_player)): if (i == x1) and (j == y1): continue if (sea_player[i][j] == 'S'): print('alarm')

Комментариев нет:

Отправить комментарий