(Python)Minimax Connect 4算法不阻止玩家移动

iih3973s  于 2023-08-02  发布在  Python
关注(0)|答案(2)|浏览(93)

(连接4是一个游戏,你下降的圆圈,并尝试创建4个连接的圆圈,无论是垂直,水平或对角线形式的颜色。
我正在构建一个connect 4 minimax算法,它无法防止损失,但似乎只会努力获胜。它只试图连接自己的碎片,而不是阻止我连接我的。
算法:(X是玩家,O是计算机)

def minimax(board, depth, is_maximizing, depthLimit):
    if detect(board, ' O '):
        return 100 - depth
    elif detect(board, ' X '):
        if is_maximizing:
            return 100 - depth
        else:
            return -100
    elif boardFull(board):
        return 0
    elif depth == depthLimit + 1:
        return 0

    if is_maximizing:
        max_eval = float('-inf')
        for row in range(6):
            for column in range(7):
                if board[row][column] == '   ' and not isColumnFull(board, column):
                    board[row][column] = ' O '
                    eval = minimax(board, depth + 1, False, depthLimit)
                    board[row][column] = '   '
                    max_eval = max(max_eval, eval)
        return max_eval
    else:
        min_eval = float('inf')
        for row in range(6):
            for column in range(7):
                if board[row][column] == '   ' and not isColumnFull(board, column):
                    board[row][column] = ' X '
                    eval = minimax(board, depth + 1, True, depthLimit)
                    board[row][column] = '   '
                    min_eval = min(min_eval, eval)
        return min_eval

def isColumnFull(board, column):
    for row in range(6):
        if board[row][column] == '   ':
            return False
    return True

def computerMove(board):
    best_score = float('-inf')
    best_move = None
    
    for row in range(6):
        for column in range(7):
            print(f'{round(((row/6)*100)+(column/7)*10, 2)}% Done Calculating')
            if board[row][column] == '   ' and not isColumnFull(board, column):
                board[row][column] = ' O '
                score = minimax(board, 0, False, depth)
                board[row][column] = '   '
                if score > best_score:
                    best_score = score
                    best_move = column

    for row in range(6):
        if board[row][best_move] != '   ':
            board[row - 1][best_move] = ' O '
            break
        elif row == 5:
            board[row][best_move] = ' O '
            break

    if detect(board, ' O '):
        print('O Wins!')
        return False
    return True

字符串
'board'本质上是一个包含board的矩阵:第一个月
示例:x1c 0d1x
我还排除了detect()函数的缺陷,因为它可以很好地检测胜利。(detect()本质上检查是否有4个相同颜色/播放器的连接件)

j0pj023g

j0pj023g1#

问题似乎在这里。

def minimax(board, depth, is_maximizing, depthLimit):
    if detect(board, ' O '):
        return 100 - depth
    elif detect(board, ' X '):
        if is_maximizing:
            return 100 - depth
        else:
            return -100

字符串
如果O赢了,它总是返回一个大的正数。如果X赢了,它将返回负数或正数,具体取决于轮到谁。如果我们最大化,那么轮到X,所以我们返回一个大的正数。换句话说,AI在X的回合中对O获胜和X获胜之间是无所谓的。
修复方法是使X与O相反:

def minimax(board, depth, is_maximizing, depthLimit):
    if detect(board, ' O '):
        return 100 - depth
    elif detect(board, ' X '):
        return -100 + depth


在做出这一改变之后,它可以找出如何阻止X获胜。

x7yiwoj4

x7yiwoj42#

看起来你的极大极小算法没有正确地阻止玩家的移动,以防止他们获胜。问题在于你在minimax评估过程中更新电路板的方式。在minimax函数中,您在评估移动后不会恢复对棋盘所做的更改。因此,它不能准确地模拟对手的动作。
要解决此问题,您需要在评估极小极大算法中的移动时正确修改棋盘。以下是minimax函数的更新版本,具有正确的板处理:

def minimax(board, depth, is_maximizing, depthLimit):
    if detect(board, ' O '):
        return 100 - depth
    elif detect(board, ' X '):
        if is_maximizing:
            return 100 - depth
        else:
            return -100
    elif boardFull(board):
        return 0
    elif depth == depthLimit + 1:
        return 0

    if is_maximizing:
        max_eval = float('-inf')
        for row in range(6):
            for column in range(7):
                if board[row][column] == '   ' and not isColumnFull(board, column):
                    board[row][column] = ' O '
                    eval = minimax(board, depth + 1, False, depthLimit)
                    board[row][column] = '   '  # Revert the move after evaluation
                    max_eval = max(max_eval, eval)
        return max_eval
    else:
        min_eval = float('inf')
        for row in range(6):
            for column in range(7):
                if board[row][column] == '   ' and not isColumnFull(board, column):
                    board[row][column] = ' X '
                    eval = minimax(board, depth + 1, True, depthLimit)
                    board[row][column] = '   '  # Revert the move after evaluation
                    min_eval = min(min_eval, eval)
        return min_eval

字符串
通过在评估每一步棋后正确地恢复棋盘,极大极小算法将正确地模拟对手的棋步,并考虑阻止玩家的获胜棋步。
此外,您应该更新computerMove函数以存储最佳行,从而将'O'标记放置在极大极小值计算之后,而不仅仅是最佳列。下面是更新后的computerMove函数:

def computerMove(board):
    best_score = float('-inf')
    best_move = None
    
    for row in range(6):
        for column in range(7):
            print(f'{round(((row/6)*100)+(column/7)*10, 2)}% Done Calculating')
            if board[row][column] == '   ' and not isColumnFull(board, column):
                board[row][column] = ' O '
                score = minimax(board, 0, False, depth)
                board[row][column] = '   '
                if score > best_score:
                    best_score = score
                    best_move = (row, column)  # Store both row and column

    if best_move:
        row, col = best_move
        for r in range(5, -1, -1):
            if board[r][col] == '   ':
                board[r][col] = ' O '
                break

    if detect(board, ' O '):
        print('O Wins!')
        return False
    return True


有了这些更新,你的极大极小算法现在应该正确地阻止玩家的获胜动作,并在游戏中做出更多的战略决策。

相关问题