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

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

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

非常感谢!

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

编辑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

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

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