在网格中寻找具有相同值的相邻单元格。有什么办法可以改进这个功能?

问题描述 投票:0回答:1

我是Python新手(学习了1个多月),我尝试着创建Tic Tac Toe。然而,一旦我完成了它,我决定扩大棋盘(从3x3到9x9,取决于客户的输入),并允许在棋盘的任何地方连接4个行、列或对角线来赢。

因此,我需要一个功能,根据客户的输入,在棋盘的各个方向上搜索--在不过度的情况下,寻找3个具有相同标记的连接单元。

然后我意识到,实际上我需要同时检查与标记相反的两个方向,因为有可能当前放置的标记可以连接相同标记的其他组,并通过这样做赢得。

下面你可以找到我的上述中奖条件的解决方案,它是有效的,然而它看起来并不漂亮,因为有很多重复的几乎相同的for循环。但是我完全不知道如何组合它们。

有8个循环(因为有8个方向),分为4组相反的方向,每个循环检查下一个单元格是否与客户当前放置的单元格('O'或'X')具有相同的值(标记),如果是,则计数变量增加1,如果不是,则循环中断。然后,我检查两个相反方向的循环是否能够使count == 4。如果是 - 我们有一个赢家。如果没有 - 我们进入下一个对子。

我相信应该有更容易维护的代码,但我想不出任何代码。

谢谢你的帮助

P.S.如果有需要,我会从我的代码中发布更多的信息

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
python matrix grid cell
1个回答
1
投票

这里有一个方法,涉及到较少的复制和粘贴 -- 希望它能给你一些想法,如何把事情分解成尽可能少的最可重复使用的部分。)

总的来说,这里的想法是想出一种方法来表达在不同方向上扫描一条线的概念,你可以只表达方向,然后让同一个代码块来处理扫描,不管方向是什么。

from typing import List, Optional, Tuple


def do_we_have_a_winner(board: List[List[Optional[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 four scans across the board -- right, down, and diagonals.
    for dx, dy in [(0, 1), (1, 0), (1, 1), (1, -1)]:
        edges: List[Tuple[int, int]] = []
        if dx > 0:
            # scanning right, start from left edge
            edges += [(0, y) for y in height]
        if dy > 0:
            # scanning down, start from top edge
            edges += [(x, 0) for x in width]
        if dy < 0:
            # scanning up, start from bottom edge
            edges += [(x, height[-1]) 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 mark is not None and 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

请注意,这个函数假设最多只有一个赢家,所以如果有多个赢家,它将只返回其中的一个--我将把它作为一个练习,让读者找出如何改变它来更好地处理这种情况。)

© www.soinside.com 2019 - 2024. All rights reserved.