这是一种减少复制和粘贴的方法——希望它能让您了解如何将事物分解为尽可能少的最可重用的部分。 :)
这里的总体思想是想出一种方式来表达在不同方向上全盘扫描一条线的概念,这样你就可以只表达方向,然后让同一个代码块处理扫描,无论什么方向是。
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
请注意,此函数假设最多有一个获胜者,因此如果有多个获胜者,它只会返回其中一个 - 我将把它作为练习,让读者弄清楚如何更改它以更好地处理这种情况。 :)