Python connect 4 检查win函数
Python connect 4 check win function
我正在编写一个 connect 4 游戏,您可以在其中选择棋盘的大小。该游戏对于大多数棋盘尺寸都可以完美运行,但是当棋盘高而宽时,我就会遇到问题。我不断收到索引超出范围的错误,我不确定自己做错了什么。这就是我现在的检查功能,因为它是唯一给我问题的部分。
def checkOWin(board):
boardHeight = len(board)
boardWidth = len(board[0])
tile = 'O'
# check horizontal spaces
for y in range(boardHeight):
for x in range(boardWidth - 3):
if board[x][y] == tile and board[x+1][y] == tile and board[x+2][y] == tile and board[x+3][y] == tile:
return True
# check vertical spaces
for x in range(boardWidth):
for y in range(boardHeight - 3):
if board[x][y] == tile and board[x][y+1] == tile and board[x][y+2] == tile and board[x][y+3] == tile:
return True
# check / diagonal spaces
for x in range(boardWidth - 3):
for y in range(3, boardHeight):
if board[x][y] == tile and board[x+1][y-1] == tile and board[x+2][y-2] == tile and board[x+3][y-3] == tile:
return True
# check \ diagonal spaces
for x in range(boardWidth - 3):
for y in range(boardHeight - 3):
if board[x][y] == tile and board[x+1][y+1] == tile and board[x+2][y+2] == tile and board[x+3][y+3] == tile:
return True
return False
如有任何帮助或建议,我们将不胜感激。提前致谢!
您刚刚混淆了尺寸,您应该这样设置它们:
def checkOWin(board):
boardHeight = len(board[0])
boardWidth = len(board)
因为当你引用 board[x] 时,那是在计算 board 中列表的数量,而当你引用 board[x][y] 时 那是到板中一个特定行的长度。
if board[x][y] == tile and board[x+1][y] == tile and board[x+2][y] == tile and board[x+3][y] == tile:
当我翻转这些值时,函数 运行 没有错误。
好的,所以这是 3 年后的事了,我正在学习编程和 Python 并正在做我自己的 Connect Four 项目所以请耐心等待...但我认为问题出在条件上。
这是一个示例输入,应该与 OP 使用的类似:
board = [['_','_','_','_','_','_','_'],
['_','_','_','_','_','_','_'],
['_','_','_','X','_','_','_'],
['_','_','_','O','_','_','_'],
['_','X','X','O','O','O','O'],
['X','X','X','O','O','X','O']]
我将条件修改为:
for x in range(boardWidth):
for y in range(boardHeight):
try:
if board[y][x] == tile and board[y][x+1] == tile and board[y][x+2] == tile and board[y][x+3] == tile:
return True
except IndexError:
next
我们在看板列表中存储了 6 个不同的列表。 y 在访问面板时排在第一位,因为它首先告诉我们需要使用这 6 个列表中的哪一个,从而在面板列表中向上或向下移动。现在 x 索引将我们移动到我们访问过的任何 y 列表中。
try 和 except 允许您删除 for x in range(boardWidth - 3)
,因为如果收到索引错误,我们知道我们已经到达游戏板的边缘并且无法满足获胜条件。所以我们继续下一个要测试的点。
虽然连续嵌套的 for 循环是检测获胜的明显解决方案,但在 python 等语言中这是一种相当缓慢的方法。该问题实际上可以被同化为在 Connect 4 board 的两个维度上进行卷积运算,卷积核设计为匹配 4 个图块的水平、垂直和对角线。
因此,更快的方法是:
- 为水平、垂直和对角线获胜检测创建内核。
horizontal_kernel = np.array([[ 1, 1, 1, 1]])
vertical_kernel = np.transpose(horizontal_kernel)
diag1_kernel = np.eye(4, dtype=np.uint8)
diag2_kernel = np.fliplr(diag1_kernel)
detection_kernels = [horizontal_kernel, vertical_kernel, diag1_kernel, diag2_kernel]
从您的棋盘创建一个二维数组,其中玩家的所有棋子都设置为 1,所有 empty/opponent 个棋子都设置为 0。
运行 棋盘使用 Scipy 高度优化的 convolve2d 函数进行卷积运算。
卷积输出形成的数组中,任意一个“4”表示棋盘上有4个相连的方块
from scipy.signal import convolve2d
def winning_move(board, player):
for kernel in detection_kernels:
if (convolve2d(board == player, kernel, mode="valid") == 4).any():
return True
return False
这允许大量 speed-up 用于检测获胜条件,这在对游戏树实施 tree-search 类算法时至关重要。我还发现此解决方案更加优雅和可读。
我正在编写一个 connect 4 游戏,您可以在其中选择棋盘的大小。该游戏对于大多数棋盘尺寸都可以完美运行,但是当棋盘高而宽时,我就会遇到问题。我不断收到索引超出范围的错误,我不确定自己做错了什么。这就是我现在的检查功能,因为它是唯一给我问题的部分。
def checkOWin(board):
boardHeight = len(board)
boardWidth = len(board[0])
tile = 'O'
# check horizontal spaces
for y in range(boardHeight):
for x in range(boardWidth - 3):
if board[x][y] == tile and board[x+1][y] == tile and board[x+2][y] == tile and board[x+3][y] == tile:
return True
# check vertical spaces
for x in range(boardWidth):
for y in range(boardHeight - 3):
if board[x][y] == tile and board[x][y+1] == tile and board[x][y+2] == tile and board[x][y+3] == tile:
return True
# check / diagonal spaces
for x in range(boardWidth - 3):
for y in range(3, boardHeight):
if board[x][y] == tile and board[x+1][y-1] == tile and board[x+2][y-2] == tile and board[x+3][y-3] == tile:
return True
# check \ diagonal spaces
for x in range(boardWidth - 3):
for y in range(boardHeight - 3):
if board[x][y] == tile and board[x+1][y+1] == tile and board[x+2][y+2] == tile and board[x+3][y+3] == tile:
return True
return False
如有任何帮助或建议,我们将不胜感激。提前致谢!
您刚刚混淆了尺寸,您应该这样设置它们:
def checkOWin(board):
boardHeight = len(board[0])
boardWidth = len(board)
因为当你引用 board[x] 时,那是在计算 board 中列表的数量,而当你引用 board[x][y] 时 那是到板中一个特定行的长度。
if board[x][y] == tile and board[x+1][y] == tile and board[x+2][y] == tile and board[x+3][y] == tile:
当我翻转这些值时,函数 运行 没有错误。
好的,所以这是 3 年后的事了,我正在学习编程和 Python 并正在做我自己的 Connect Four 项目所以请耐心等待...但我认为问题出在条件上。
这是一个示例输入,应该与 OP 使用的类似:
board = [['_','_','_','_','_','_','_'],
['_','_','_','_','_','_','_'],
['_','_','_','X','_','_','_'],
['_','_','_','O','_','_','_'],
['_','X','X','O','O','O','O'],
['X','X','X','O','O','X','O']]
我将条件修改为:
for x in range(boardWidth):
for y in range(boardHeight):
try:
if board[y][x] == tile and board[y][x+1] == tile and board[y][x+2] == tile and board[y][x+3] == tile:
return True
except IndexError:
next
我们在看板列表中存储了 6 个不同的列表。 y 在访问面板时排在第一位,因为它首先告诉我们需要使用这 6 个列表中的哪一个,从而在面板列表中向上或向下移动。现在 x 索引将我们移动到我们访问过的任何 y 列表中。
try 和 except 允许您删除 for x in range(boardWidth - 3)
,因为如果收到索引错误,我们知道我们已经到达游戏板的边缘并且无法满足获胜条件。所以我们继续下一个要测试的点。
虽然连续嵌套的 for 循环是检测获胜的明显解决方案,但在 python 等语言中这是一种相当缓慢的方法。该问题实际上可以被同化为在 Connect 4 board 的两个维度上进行卷积运算,卷积核设计为匹配 4 个图块的水平、垂直和对角线。
因此,更快的方法是:
- 为水平、垂直和对角线获胜检测创建内核。
horizontal_kernel = np.array([[ 1, 1, 1, 1]]) vertical_kernel = np.transpose(horizontal_kernel) diag1_kernel = np.eye(4, dtype=np.uint8) diag2_kernel = np.fliplr(diag1_kernel) detection_kernels = [horizontal_kernel, vertical_kernel, diag1_kernel, diag2_kernel]
从您的棋盘创建一个二维数组,其中玩家的所有棋子都设置为 1,所有 empty/opponent 个棋子都设置为 0。
运行 棋盘使用 Scipy 高度优化的 convolve2d 函数进行卷积运算。
卷积输出形成的数组中,任意一个“4”表示棋盘上有4个相连的方块
from scipy.signal import convolve2d def winning_move(board, player): for kernel in detection_kernels: if (convolve2d(board == player, kernel, mode="valid") == 4).any(): return True return False
这允许大量 speed-up 用于检测获胜条件,这在对游戏树实施 tree-search 类算法时至关重要。我还发现此解决方案更加优雅和可读。