我的无敌井字游戏程序出现了问题

我尝试使用极小化极大算法来创建一个在井字游戏中不会输的程序。但在一些情况下,程序出现了问题。例如,当井字游戏棋盘上只剩下两个位置时(在某些情况下),程序会停止运行并要求用户连续输入两次。此外,在某些情况下,当电脑有明显的获胜机会时,它却没有选择正确的移动方式。

这是我的作业,今天任何形式的帮助都将非常感激。

非常感谢!

编辑:请注意,代码允许用户覆盖之前的移动。我会尽快修复这个问题。然而,即使我不覆盖之前的机会,我也得不到结果。我已经测试了代码,问题似乎出在极小化极大函数中,但我保留了整个代码,以防我错了,真正的问题在其他地方。

编辑2:抱歉之前的帖子不完整!下面是重现问题的测试案例。在我输入我的移动(位置5)后,程序停止运行并要求我玩完所有机会。

Would you like to go first (Y/N)?: n  . . .  . . .   . . .   x . .   . . .   . . .   Enter your choice (1-9): 5  x . .   . o .   . . .   x x .   . o .   . . .   Enter your choice (1-9): 7  x x .   . o .   o . .   x x .   . o .   o . .   Enter your choice (1-9): 

另外,我知道我的代码很混乱且业余——但尽管使用了全局变量,我应该能够让它工作。如果你能帮我解决这个问题,我会清理所有的代码。再次感谢!

编辑3:另一个测试案例:Would you like to go first (Y/N)?: y

. . . . . . . . . Enter your choice (1-9): 5. . . . o . . . . x . . . o . . . . Enter your choice (1-9): 3x . o . o . . . . x . o . o . x . . Enter your choice (1-9): 2x o o . o . x . . x o o . o . x . . Enter your choice (1-9): 6x o o . o o x . . x o o . o o x . . Enter your choice (1-9): 9You win!

我的代码是Python 3.6版本,代码如下:

move = -1n = 0def evaluateBoard(board):    global n    #Checking for rows    cnt = 0    for i in range(n):        res = 0        for j in range(n):           res += board[cnt * n + j]         cnt += 1        if res == n:            return 1        elif res == -n:            return -1    #Checking for columns    for i in range(n):        res = 0        for j in range(n):            res += board[i + n * j]        if res == n:            return 1        elif res == -n:            return -1    #Checking for diagonals    res = res2 = 0    for i in range(n):        res += board[i * (n + 1)]           res2 += board[(i + 1) * (n - 1)]    if n in [res, res2]:        return 1    elif -n in [res, res2]:        return -1    return 0def checkNonTerminal(board):   for pos in board:       if pos == 0:           return 1   return 0def getScore(board, depth):    if evaluateBoard(board) == 1:        return 10 - depth    elif evaluateBoard(board) == -1:        return depth - 10    else:        return 0def minimax(board, turn, depth):    if evaluateBoard(board) == 0 and checkNonTerminal(board) == 0:        return getScore(board, depth)    global move    moves = list()    scores = list()    for square, pos in enumerate(board):        if pos == 0:            #print(board)            new_board = board.copy()            new_board[square] = turn            moves.append(square)            #print("Moves:", moves, "depth:", depth, "turn:", turn, checkNonTerminal(new_board) == 0)            if evaluateBoard(new_board) in [1, -1] or checkNonTerminal(new_board) == 0:                return getScore(new_board, depth)            scores.append(minimax(new_board, turn * -1, depth + 1))        #print("scores", scores)     if turn == 1:        move = moves[scores.index(max(scores))]        return max(scores)    elif turn == -1:        move = moves[scores.index(min(scores))]        return min(scores)def displayBoard(board):    global n    for i in range(n):        for j in range(n):            if board[n*i+j] == 1:                print("x", end = " ")            elif board[n*i+j] == -1:                print("o", end = " ")            else:                print(".", end = " ")        print()def main():          global n     global move    n = 3    first_turn = input("Would you like to go first (Y/N)?: ")    if first_turn in ['Y', 'y']:        first_turn = -1        cnt = 1    else:        first_turn = 1        cnt = 2    board = [0] * 9    while evaluateBoard(board) == 0 and checkNonTerminal(board) == 1:        displayBoard(board)        if cnt % 2 == 0:            score = minimax(board, 1, 0)            print(score)            board[move] = 1        else:            choice = eval(input("Enter your choice (1-9): "))            board[choice - 1] = -1        cnt += 1    if evaluateBoard(board) == 1:        print("You lose!")    elif evaluateBoard(board) == -1:        print("You win!")    else:        print("It's a draw!")main()

回答:

如果您检查的第一个移动是结束游戏的移动,您在没有设置移动的情况下就返回了。这可能是您的获胜逻辑失败以及跳过回合的原因。

用更程序员的方式来说:
您的递归终止条件过早触发,您需要处理这种情况!

for square, pos in enumerate(board):    if pos == 0:        #print(board)        new_board = board.copy()        new_board[square] = turn        moves.append(square)        #print("Moves:", moves, "depth:", depth, "turn:", turn, checkNonTerminal(new_board) == 0)        if evaluateBoard(new_board) in [1, -1] or checkNonTerminal(new_board) == 0:            return getScore(new_board, depth) <----这里        scores.append(minimax(new_board, turn * -1, depth + 1))    #print("scores", scores) 

太忙了,没时间检查,但我相信您也可以在那里设置您的移动变量——如果您只是弹出递归堆栈,它稍后会被覆盖。

附言,这也是使用适当的返回变量而不是仅仅设置全局变量的另一个原因;)

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注