在网格中查找具有相同值的相邻单元格.如何改进此功能



我是Python的新手(学习了一个多月(,我尝试创建了Tic-Tac-Toe。然而,一旦我完成了它,我决定将板扩展(根据客户的输入,从3x3扩展到9x9(,并通过在板中的任何位置按行、列或对角线连接4个来允许获胜。

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

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

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

有8个循环(因为有8个方向(,在4组相反的方向中,每个循环检查下一个单元格是否与客户当前放置的单元格具有相同的值(标记(("O"或"X"(。如果是,计数变量将增加1。如果没有,循环就会中断。然后我检查两个相反方向的循环是否成功计数==4。如果是,我们有一个赢家。如果没有,我们就去下一对。

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

谢谢你的帮助!

第页。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

这里有一种减少复制和粘贴的方法——希望它能让你了解如何将东西分解为尽可能少的最可重用的部分。:(

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

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

注意,这个函数假设最多有一个赢家,所以如果有多个赢家,它只会返回其中一个——我将把它留给读者一个练习,让读者找出如何更改它以更好地处理这种情况。:(

最新更新