在网格中查找具有相同值的相邻单元格。想法如何改进这个功能?

2024-05-20

我是 Python 新手(学习了 1 个多月),我尝试创建 Tic Tac Toe。然而,一旦我完成了它,我决定扩展棋盘(从 3x3 到 9x9,具体取决于客户的输入),并通过在棋盘上的任意位置连接 4 个行、列或对角线来获胜。

因此,我需要一个功能,根据客户的输入,在电路板上的各个方向上搜索 3 个具有相同标记的连接单元,而不会过度搜索。

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

下面您可以找到我对上述获胜条件的解决方案,该解决方案有效,但它看起来不太漂亮,因为有很多重复的几乎相同的 for 循环。但我对如何组合它们一无所知。

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

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

感谢您的帮助!

附:如果有需要,我会从我的代码中发布更多内容

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

这是一种减少复制和粘贴的方法——希望它能让您了解如何将事物分解为尽可能少的最可重用的部分。 :)

这里的总体思想是想出一种方式来表达在不同方向上全盘扫描一条线的概念,这样你就可以只表达方向,然后让同一个代码块处理扫描,无论什么方向是。

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

请注意,此函数假设最多有一个获胜者,因此如果有多个获胜者,它只会返回其中一个 - 我将把它作为练习,让读者弄清楚如何更改它以更好地处理这种情况。 :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在网格中查找具有相同值的相邻单元格。想法如何改进这个功能? 的相关文章

随机推荐