Веселое упражнение для оттачивания вашего мозга и кода

Вы когда-нибудь задумывались, как с помощью Python найти разрешенные ходы короля на шахматной доске? Наверное, нет, но это забавное упражнение - прыгать по сетке, составленной из списков.

Король может двигаться только на одно поле в любом направлении. Это означает, что он может сделать восемь допустимых ходов, если он не находится на краю или в углу.

Я также добавил вам вызов в конце. Ты собираешься это взять?

В этой программе мы:

  • Создайте меню для пользователя, чтобы он мог разместить короля на доске
  • Распечатайте доску с точки зрения черного или белого
  • Распечатайте допустимые ходы короля в зависимости от того, где пользователь ставит своего короля

Доска

Чтобы написать эту программу, мы будем использовать один класс с именем Board в board.py и main.py для его запуска.

Создать доску довольно просто, но все же она имеет очень приятный оттенок. Я воспользуюсь пониманием списков, чтобы заполнить список восемью списками (строками). В них будет восемь элементов (столбцов).

Шахматная доска имеет размер 8х8 клеток. Строки пронумерованы, а столбцы обозначаются буквами A – H.

Вот доска объявлений

def __init __ (сам)

  • Первое, что вы замечаете, - это список self._letters. Это просто диапазон букв, возможных на шахматной доске в виде строк - например, A-H.
  • Следующий список - self._board_grid. Этот список пока пуст и будет заполнен несколькими списками, представляющими строки.
  • Цикл for letters in self._letters: использует понимание списка для выполнения следующих действий:
append_list = [(letter + str(x)) for x in range(1,9)]

Последняя часть, (for x in range(1,9)), сообщает нам, что мы проделаем действие восемь раз. Диапазон от 1 до 9 идет от 1 до 8.

Если вы не знакомы с пониманием списков, Рупеш Мишра написал об этом хорошую статью здесь.

Первая часть сообщает нам, что мы хотим объединить букву из списка букв self._letter с числом. letter + str(x) выберет «A» и добавит «1» для первой итерации диапазона (1,9), затем A2, A3 и так далее.

Когда это будет сделано с A, он перейдет к B, потому что он продолжит просмотр всего self._letters списка.

Поскольку мы перебираем весь список букв, получаем:

['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8']
['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8']
etc....

Они добавляются один за другим, поэтому они будут составлять список со списками, пока мы не закончим - A1-H8.

def print_board (сам)

Этот просто просматривает списки во вновь созданном self._board_grid и печатает строки.

Результат:

['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8']
['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8']
['C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8']
['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8']
['E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8']
['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8']
['G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8']
['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8']

Я знаю, о чем вы думаете: эта доска перевернута / вид с точки зрения черных. Да, на данный момент, это потому, что список был создан таким образом, но мы разберемся с этим позже.

Вы можете написать очень короткий main.py, чтобы протестировать этот код:

from board import Board
def main():
    board = Board()
    board.print_board()
main()

Самая сложная функция метода в этой программе - это функция, которая определяет допустимые ходы короля.

Мы позволим пользователю пройти фактический квадрат, где он / она помещает короля (например, E5) в виде строки.

Это означает, что мы должны немного настроить этот ввод, чтобы иметь возможность правильно перемещаться по сетке.

Вот код, но позвольте мне объяснить его, прежде чем вы начнете его атаковать.

Я хочу разделить это на две части, одну перед циклом и сам цикл с напечатанным результатом в конце.

Поскольку мы позволяем пользователю вводить буквы и цифры, мы сами усложняем задачу. Нам нужно получить числа, представляющие это. Если вы хотите перейти на E5, вы должны ввести self._board_grid[4][4].

Это означает, что мы должны преобразовать E в 4. Но мы должны сделать его независимым. Мы также хотим, чтобы F автоматически преобразовывалось в 5, а также A в 0 (A - это первый список). В Python первый индекс в списке равен 0.

upper_input_letter = coordinates[0].upper()    
get_letter_index = self._letters.index(upper_input_letter)
get_number_index = int(coordinates[1])-1

Первое выражение, upper_input_letter, гарантирует, что независимо от того, что пользователь вводит, мы будем работать с заглавной буквой. Если пользователь вводит «a1», мы хотим рассматривать его как A1.

get_letter_index проверяет, какой индекс введен пользователем в исходном списке букв. E вернет индекс 4 как int.

get_number_index просто чтобы убедиться, что когда пользователь вводит число, мы вычитаем единицу, чтобы это число было правильно представлено в списке. Помните, что первый элемент в списке в Python равен 0, а не 1. Если пользователь вводит A1, нам нужно [0] [0].

Петля

Здесь мы переходим в буквенный ряд, а затем в номер столбца.

Список разрешенных ходов сохранит все разрешенные ходы и вернется в конце.

Путь поиска используется для определения того, насколько глубоко мы хотим искать. Для короля мы хотим искать по одной строке в обоих направлениях и по одному столбцу в каждом направлении. Это диапазон (-1,2), потому что тогда мы можем вернуться к предыдущей строке: (-1,0) будет проверять текущую строку, в которой мы находимся, а 1 проверяет следующую строку. То же самое и со столбцами.

Соседние буквы и числа, которые мы ищем, будут индексным номером, который мы передаем, например, при вводе команды E5. Но мы должны помнить об ассортименте. Поэтому мы складываем номера диапазонов от -1-2.

Чтобы убедиться, что мы можем вычитать и добавлять числа, мы всегда добавляем. Если вы добавляете отрицательное число, вы вычитаете. Если вы добавляете положительное число, вы добавляете.

neighbour_square_letter = get_letter_index + letter_row
neighbour_square_number = get_number_index + column_number

Статус юридического квадрата по умолчанию установлен на True. Затем мы проверяем, приземляется ли он за пределами доски. ‹0 или› 7 вне доски, как в строке, так и в столбце. Когда это произойдет, эти квадраты получат значение False.

Добавляются допустимые квадраты, и в конце мы удаляем исходные данные из списка разрешенных ходов, потому что нам не нужен квадрат, на котором мы стоим.

Мне пришлось преобразовать координаты в формат, который я мог сравнить.

print_kings_legal_moves

Мы могли бы просто оставить это в find_king_legal_moves, но лучше возвращать результат, чем печатать его. Если мы вернем его, мы можем сохранить его в переменной и распечатать по-разному, если захотим.

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

Помните, как шахматную доску печатали в перевернутом виде?

Давайте посмотрим на файл main.py:

Мы можем создать меню, в котором игрок может сказать нам, черные они или белые. Это player_color ввод.

Затем мы создаем плату, и когда мы ее распечатываем, мы передаем player_color в метод.

Вот как это выглядит в обновленном классе платы:

Пользователь может выбирать между белым или черным, и здесь происходят некоторые интересные вещи:

if color.upper() == 'WHITE':
    board = self._board_grid[::-1]

Мы можем использовать .upper(), чтобы убедиться, что любые проблемы с нижним / верхним регистром не влияют на нас. Затем, используя [::-1], мы переворачиваем список, чтобы он правильно печатался для белого игрока.

Функционал программы остался прежним, отличается только оформление.

Но ждать!

Можете ли вы отредактировать код, чтобы получить правильные легальные ходы?

Внимательный наблюдатель или шахматист наверняка заметил, как доска печатается боком.

Я переработал код, чтобы он работал лучше:

  • Статус черного / белого игрока определяет, как будет нарисовано поле.
  • Меньше взломов, чтобы распечатать доску
  • Убран раздутый код, свел его к паре методов

Обратите особое внимание на метод generate_board(). Это довольно весело. Обратите внимание, что он печатается по-другому, только когда у меня черный user_color. Это означает, что вы можете выполнять все проверки в исходном self._board_grid, в то время как он отображается по-разному в зависимости от цвета игрока. Это означает меньше кода для поиска ходов и большую гибкость для печати.

Новый board.py:

Новый main.py:

Готовы ли вы к этому вызову?

Можете ли вы отредактировать код, чтобы:

  1. Пусть пользователь вводит 0 или 1 вместо «черный» и «белый». Это снизит вероятность ошибок и ускорит использование программы пользователем.
  2. Дайте пользователю возможность продолжать размещать короля до тех пор, пока он / она не перестанет этого делать.
  3. Самое главное ... заставьте find_king_legal_moves() правильно работать с новым способом рисования доски.

Я обещаю вам: если вы погрузитесь в задачу, вы ее решите. Спасибо за прочтение!