Перебор вложенного списка и пропуск строк или столбцов

#python-3.x #pygame

#python-3.x #pygame

Вопрос:

Я разрабатываю шахматное приложение / игру для Windows с python 3.7 и pygame в качестве моего первого проекта по программированию. Я уже зашел довольно далеко, но есть проблема, которую я пытался решать часами и не могу понять, как ее решить.

У меня есть вложенный список, в котором хранятся позиции моих шахматных фигур на доске, который выглядит так:

 ppos = [
    ["br", "bkn", "bb", "bq", "bk", "bb", "bkn", "br"],
    ["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
    ["e", "e", "e", "e", "e", "e", "e", "e"],
    ["e", "e", "e", "e", "e", "e", "e", "e"],
    ["e", "e", "e", "e", "e", "e", "e", "e"],
    ["e", "e", "e", "e", "e", "e", "e", "e"],
    ["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
    ["wr", "wkn", "wb", "wq", "wk", "wb", "wkn", "wr"],
]
 

Затем у меня есть функция, которая возвращает цвет фрагмента в моем вложенном списке ppos:

 def get_piece_colour(piece):
    blackpieceslist = ["br", "bkn", "bb", "bk", "bq", "bp"]
    whitepieceslist = ["wr", "wkn", "wb", "wk", "wq", "wp"]

    if piece in blackpieceslist:
        colour = "black"
    elif piece in whitepieceslist:
        colour = "white"
    elif piece == "e":
        colour = "e"
    return colour
 

Другая функция проверяет и выделяет все возможные ходы для фигуры, на которую нажали, выделяя частично прозрачный зеленый квадрат (поверхность) на каждой клетке доски, на которую можно переместить.

Вышеупомянутая функция с рабочим примером белой пешки:

 def highlight_possible_squares(from_row, from_col, piece):
    pygame.draw.rect(green_highlight, ALPHAGREEN, green_highlight.get_rect())

    # white pawn
    if piece == "wp":
        for r in range(0, 8):
            for c in range(0, 8):

                to_row = r
                to_col = c

                square_x = to_row * square_size
                square_y = to_col * square_size

                square_xy_tuple = (square_x, square_y)

                from_to_row_dif = from_row - to_row
                from_to_col_dif = from_col - to_col

                # if on starting row, squares that are one and two squares in front get highlighted
                if from_row == 6:
                    if from_to_row_dif == 1 and from_to_col_dif == 0 and get_piece_colour(ppos[r][c]) == "e":
                        highlight_squares_lst.append(square_xy_tuple)
                    elif from_to_row_dif == 2 and from_to_col_dif == 0 and get_piece_colour(ppos[r][c]) == "e":
                        highlight_squares_lst.append(square_xy_tuple)
                    # diagonal move to destroy other pieces
                    elif from_to_row_dif == 1 and from_to_col_dif == 1 and get_piece_colour(ppos[r][c]) == "black":
                        highlight_squares_lst.append(square_xy_tuple)
                    elif from_to_row_dif == 1 and from_to_col_dif == -1 and get_piece_colour(ppos[r][c]) == "black":
                        highlight_squares_lst.append(square_xy_tuple)

                # if not on starting row, pawn can only move one square in front
                elif from_row < 6:
                    if from_to_row_dif == 1 and from_to_col_dif == 0 and get_piece_colour(ppos[r][c]) == "e":
                        highlight_squares_lst.append(square_xy_tuple)
                    # diagonal move to destroy other pieces
                    elif from_to_row_dif == 1 and from_to_col_dif == 1 and get_piece_colour(ppos[r][c]) == "black":
                        highlight_squares_lst.append(square_xy_tuple)
                    elif from_to_row_dif == 1 and from_to_col_dif == -1 and get_piece_colour(ppos[r][c]) == "black":
                        highlight_squares_lst.append(square_xy_tuple)

        for t in highlight_squares_lst:
            board.blit(green_highlight, (t[1], t[0]))
 

Теперь я не могу понять, как это сделать, это ладья. Ладья может перемещаться влево, вправо, вверх и вниз, но ей не разрешается перепрыгивать через фигуры и перемещаться на квадраты позади них.

Это то, что у меня есть до сих пор:

 # white rook
if piece == "wr":

    for r in range(0, 8):
        for c in range(0, 8):

            square_x = r * square_size
            square_y = c * square_size

            square_xy_tuple = (square_x, square_y)

            if from_row == r and get_piece_colour(ppos[r][c]) == "e":
                highlight_squares_lst.append(square_xy_tuple)
            elif from_col == c and get_piece_colour(ppos[r][c]) == "e":
                highlight_squares_lst.append(square_xy_tuple)

    for t in highlight_squares_lst:
        board.blit(green_highlight, (t[1], t[0]))
 

Пример изображения того, как это выглядит в тот момент, когда я нажимаю на ладью в середине картинки:

выделите ходы белой ладьи

Итак, в этом примере квадрат слева от белой пешки слева, квадраты справа от белой пешки справа и квадрат между черным ферзем и черной пешкой не должны выделяться моей функцией.

Кто-нибудь может дать мне подсказку о том, как это сделать?

Спасибо.

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

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

1. Я предполагаю, что мы можем вычислить выделенную функцию в соответствии с происхождением выбранной части. Ладья, которая является позицией выбранной фигуры (3,3). У нас есть четыре направления, в которых его можно перемещать. Для направления вверх мы могли бы увеличить 1 для управления осью y. Например, (3,4) == ‘e’ нарисуйте и увеличьте, затем управляйте (3,5), если это не ‘e’, затем остановитесь и продолжайте управлять другими направлениями, подобными этому.

2. Спасибо за совет, но я все еще не могу заставить его работать. Я запускаю один цикл for от начальной строки до верха, один от начальной строки до низа, один от начальной строки вправо и один от начальной строки влево. Я также добавил разрыв для каждого цикла for, если цвет фрагмента не «e», но не работает.

Ответ №1:

Итак, частично благодаря shalom и частично благодаря исследованиям, я нашел решение.

Я попытался пойти во всех 4 направлениях, используя 4 цикла for, и разбить их, когда я попадаю на кусок / квадрат, цвет которого не «e». Что действительно сделало работу, так это параметр stage функции range .

 # white rook
    if piece == "wr":

        for c in range(from_col   1, 8):
            if get_piece_colour(ppos[from_row][c]) == "e":
                highlight_squares_lst.append((from_row * 100, c * 100))
            else:
                break

        for mc in range(from_col - 1, -1, -1):
            if get_piece_colour(ppos[from_row][mc]) == "e":
                highlight_squares_lst.append((from_row * 100, mc * 100))
            else:
                break

        for r in range(from_row   1, 8):
            if get_piece_colour(ppos[r][from_col]) == "e":
                highlight_squares_lst.append((r * 100, from_col * 100))
            else:
                break

        for mr in range(from_row - 1, -1, -1):
            if get_piece_colour(ppos[mr][from_col]) == "e":
                highlight_squares_lst.append((mr * 100, from_col * 100))
            else:
                break

        for t in highlight_squares_lst:
            board.blit(green_highlight, (t[1], t[0]))
 

введите описание изображения здесь