简体   繁体   English

Python连接4检查win函数

[英]Python connect 4 check win function

I am writing a connect 4 game in which you can choose the size of the board.我正在编写一个连接 4 游戏,您可以在其中选择棋盘的大小。 The game works flawlessly for most board sizes but gives me problems when the board is taller then it is wide.该游戏适用于大多数棋盘尺寸,但当棋盘比它高时会给我带来问题。 I keep getting index out of range errors and im not sure what I have done wrong.我不断得到索引超出范围的错误,我不确定我做错了什么。 This is what I have right now in terms of my check function as it is the only part giving me issues.这就是我现在拥有的检查功能,因为它是唯一给我带来问题的部分。

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

Any help or suggestions would be greatly appreciated.任何帮助或建议将不胜感激。 Thanks in advance!提前致谢!

Although the successive nested for loops are the obvious solution for win detection, it is a rather slow approach in a language such as python.尽管连续嵌套的 for 循环是检测获胜的明显解决方案,但在 Python 等语言中这是一种相当慢的方法。 The problem can actually be assimilated to a convolution operation on the two dimensions of the Connect 4 board, with convolution kernels designed to match horizontal, vertical and diagonal lines of 4 tiles.该问题实际上可以同化为 Connect 4 板的两个维度上的卷积操作,其卷积核旨在匹配 4 个瓦片的水平、垂直和对角线。

A faster approach would thus be to:因此,更快的方法是:

  1. Create kernels for horizontal, vertical and diagonal win detection.创建用于水平、垂直和对角线获胜检测的内核。
 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. Create a 2D array from your board, in which all of a player's tiles are set to 1, and all empty/opponent tiles are set to 0.从您的棋盘创建一个 2D 数组,其中玩家的所有图块都设置为 1,所有空/对手图块都设置为 0。

  2. Run the board through the convolution operations using Scipy's highly optimized convolve2d function.使用 Scipy 高度优化的 convolve2d 函数通过卷积操作运行电路板。

  3. In the array formed by the convolution output, any "4" indicates that there were 4 connected tiles in the board.在卷积输出形成的数组中,任何“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

This allows for a huge speed-up for detection of the winning conditions which is crucial when implementing tree-search like algorithms on the game tree.这可以极大地加速检测获胜条件,这对于在博弈树上实施类似树搜索的算法至关重要。 I also find this solution to be more elegant and readable.我还发现这个解决方案更加优雅和可读。

You've just mixed up your dimensions, you should set them this way:您刚刚混淆了尺寸,您应该这样设置它们:

def checkOWin(board):
    boardHeight = len(board[0])
    boardWidth = len(board)

Because when you refer to board[x], that's counting the number of lists in the board, and when you refer to board[x][y] that's just referring to the length of one specific row in the board.因为当你提到 board[x] 时,这是计算板中列表的数量,而当你提到 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:

When I flipped those values the function ran without errors.当我翻转这些值时,函数运行没有错误。

Ok, so this is 3 years later, and I am learning programming and Python and doing my own Connect Four project so bear with me... but I think the problem lies in the conditional.好的,这是 3 年后,我正在学习编程和 Python,并在做我自己的 Connect Four 项目,所以请耐心等待……但我认为问题在于条件。

Here is a sample input that should be similar to what OP is using:这是一个示例输入,应该类似于 OP 使用的内容:

board = [['_','_','_','_','_','_','_'],
         ['_','_','_','_','_','_','_'],
         ['_','_','_','X','_','_','_'],
         ['_','_','_','O','_','_','_'],
         ['_','X','X','O','O','O','O'],
         ['X','X','X','O','O','X','O']]

I've reworked the conditional to be:我已经将条件修改为:

  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

We have 6 different lists stored in the board list.我们在板列表中存储了 6 个不同的列表。 The y comes first when accessing the board because it first tells us which list of those 6 we need to use, moving us up or down in the board list.访问板时 y 排在最前面,因为它首先告诉我们需要使用这 6 个列表中的哪个列表,在板列表中向上或向下移动我们。 Now the x index moves us within whichever y list we have accessed.现在 x 索引将我们移动到我们访问过的任何 y 列表中。

The try and except allow you to remove the for x in range(boardWidth - 3) because if an index error is received, we know we've reached the edge of the game board and cannot meet the win condition. try 和 except 允许您删除for x in range(boardWidth - 3)因为如果收到索引错误,我们知道我们已经到达游戏板的边缘并且无法满足获胜条件。 So we move on to the next point to test.所以我们继续下一个测试点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM