Поиск соседних ячеек в сетке с тем же значением. Идеи, как улучшить эту функцию? - PullRequest
0 голосов
/ 23 апреля 2020

Я новичок в Python (изучаю его чуть более 1 месяца), и я попытался создать Ti c Ta c Toe. Однако, как только я закончу это, я решу расширить доску (с 3x3 до 9x9 в зависимости от ввода клиента) и разрешить выигрыш, соединив 4 в ряд, столбец или диагональ в любом месте доски.

Поэтому я нужна была функция, которая ищет - в зависимости от ввода клиента - во всех направлениях на доске, не выходя за борт, для 3-х подключенных ячеек с одной и той же отметкой.

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

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

Есть 8 петель (так как есть 8 направлений), в 4 группах противоположных направлений, и каждая l oop проверяет, есть ли следующая ячейка с тем же значение (отметка) как то, которое в данный момент размещено клиентом (либо «O», либо «X»). Если это значение, то переменная count увеличивается на 1. Если нет - l oop разрывается. Затем я проверяю, удалось ли двум противоположным петлям направления считать == 4. Если да - у нас есть победитель. Если нет - мы go к следующей паре.

Я уверен, что поддерживать код проще, но я не могу придумать ни одного.

Спасибо за вашу помощь !

PS если есть необходимость, я выложу больше из своего кода

def do_we_have_a_winner(position, current_mark):
    global game_board
    connect = 4
    # unpacking the coordinates of the current position
    x, y = coordinates[position]

    length = len(game_board)

    count = 0

    for i in range(0, connect):
        if (x-i in range(0, length)) and (y+i in range(0, length)):
            if game_board[x-i][y+i] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (x+i in range(0, length)) and (y-i in range(0, length)):
            if game_board[x+i][y-i] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    count = 0

    for i in range(0, connect):
        if (x+i in range(0, length)) and (y+i in range(0, length)):
            if game_board[x+i][y+i] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (x-i in range(0, length)) and (y-i in range(0, length)):
            if game_board[x-i][y-i] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    count = 0

    for i in range(0, connect):
        if (y+i in range(0, length)):
            if game_board[x][y+i] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (y-i in range(0, length)):
            if game_board[x][y-i] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    count = 0

    for i in range(0, connect):
        if (x+i in range(0, length)):
            if game_board[x+i][y] != current_mark:
                break
            else:
                count += 1

    for i in range(1, connect):
        if (x-i in range(0, length)):
            if game_board[x-i][y] != current_mark:
                break
            else:
                count += 1

    if count == connect:
        print("We have a winner!")
        return True

    return False

1 Ответ

0 голосов
/ 23 апреля 2020

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

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

from typing import List, Optional, Tuple


def do_we_have_a_winner(board: List[List[str]], length: int) -> Optional[str]:
    """Returns the 'mark' of the player with a row of the given length."""
    width = range(len(board))
    height = range(len(board[0]))
    # Do three passes across the board -- right, down, and diagonal.
    for dx, dy in [(0, 1), (1, 0), (1, 1)]:
        # dx, dy is the direction we're scanning in.
        edges: List[Tuple[int, int]] = []
        if dx:
            # include left edge in start of scan
            edges += [(0, y) for y in height]
        if dy:
            # include top edge in start of scan
            edges += [(x, 0) for x in width]
        for ex, ey in edges:
            mark: Optional[str] = None
            row = 0
            x, y = ex, ey
            while x in width and y in height:
                if board[x][y] == mark:
                    row += 1
                else:
                    mark = board[x][y]
                    row = 1
                if row >= length:
                    return mark
                x, y = x + dx, y + dy
    return None


print(do_we_have_a_winner([
    ['X', 'O', 'O'],
    ['O', 'X', 'O'],
    ['O', 'O', 'X'],
], 3))  # X

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

...