【问题标题】:Finding neighbor cells in a grid with the same value. Ideas how to improve this function?在网格中查找具有相同值的相邻单元格。想法如何改进这个功能?
【发布时间】:2020-08-07 04:24:17
【问题描述】:

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

因此,我需要一个功能来搜索 - 根据客户输入 - 在板上的每个方向上搜索 3 个具有相同标记的连接单元格。

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

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

有8个循环(因为有8个方向),4组相反方向,每个循环检查下一个单元格是否与客户当前放置的单元格具有相同的值(标记)(要么'O' 或 'X')。如果是计数变量,则增加 1。如果不是 - 循环中断。然后我正在检查两个相反方向的循环是否成功计数 == 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

【问题讨论】:

  • 您是否只需要检查包含position 的获胜条件?只检查整个棋盘并查看是否有任何一名玩家的获胜条件可能更简单。
  • 绝对可以这样做,购买然后在每一步程序将 4 次通过整个网格,我只是希望它更高效。我知道对于这样的游戏没关系,但我这样做是为了学习新东西:)

标签: python matrix grid cell


【解决方案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

请注意,此函数最多假定一个获胜者,因此如果有多个获胜者,它只会返回其中一个 - 我将把它作为练习留给读者了解如何更改它来处理它情况较好。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 2012-11-06
    • 2017-06-12
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    相关资源
    最近更新 更多