Minimax算法仅返回特定的值集

时间:2018-02-08 04:34:21

标签: python algorithm minimax

我在Python中为基本的井字游戏AI实现了一个minimax算法,如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    FILE *passwords = fopen("/Users/mcicco/Desktop/passwords.txt", "r");
    FILE *usernames = fopen("/Users/mcicco/Desktop/usernames.txt ", "r");
    FILE *merged_file = fopen("/Users/mcicco/Desktop/merged.txt" , "w");
    if (usernames == NULL || passwords == NULL || merged_file == NULL)
    {
        printf("Cannot open file \n");
        return (-1);
    }

    char username[1024];
    char password[1024];
    while(1)
    {
        if(!fgets(username, sizeof(username), usernames))
            break;
        if(!fgets(password, sizeof(password), passwords))
            break;
        username[strcspn(username, "\n")] = 0;
        password[strcspn(password, "\n")] = 0;
        fprintf(merged_file, "%s\n%s\n", username, password);
    }
    fclose(usernames);
    fclose(passwords);
    fclose(merged_file);    
    return 0;
}

其他支持功能非常明显。但是,此脚本无法正常运行。例如,它似乎始终选择[0,0],然后继续进行相对恒定的移动,即使有更好的移动可用。此外,考虑到以下状态(以及一般情况下可获胜的行动):

enter image description here

其中def minimax(currentBoard, player): if isGameOver(currentBoard): score = evaluate(currentBoard) return score for cell in getEmptySpots(currentBoard): x = cell[0] y = cell[1] currentBoard[x][y] = player bestScore = -1000000 score = minPlay(currentBoard, -player) currentBoard[x][y] = 0 if score > bestScore: bestScore = score bestMove = cell print('Best move:') print(bestMove) print('\n') return bestMove def minPlay(currentBoard, player): if isGameOver(currentBoard): score = evaluate(currentBoard) return score for cell in getEmptySpots(currentBoard): x = cell[0] y = cell[1] currentBoard[x][y] = player bestScore = 1000000 score = maxPlay(currentBoard, -player) currentBoard[x][y] = 0 if score < bestScore: bestScore = score return bestScore def maxPlay(currentBoard, player): if isGameOver(currentBoard): score = evaluate(currentBoard) return score for cell in getEmptySpots(currentBoard): x = cell[0] y = cell[1] currentBoard[x][y] = player bestScore = -1000000 score = minPlay(currentBoard, -player) currentBoard[x][y] = 0 if score > bestScore: bestScore = score return bestScore 代表人类,1代表计算机,计算机选择移动-1作为最佳移动,而不是[2][1][2][2]这将导致胜利。

我已经经历了一些与不同语言的minimax实现有关的问题,据我所知,我的代码在逻辑上是有道理的。因此,我不确定问题是什么。 我的完整代码可以找到here

enter image description here

2 个答案:

答案 0 :(得分:1)

你的循环中空单元格中存在逻辑错误! 您必须在循环之前初始化bestScore,并在循环之后初始化return bestScore。否则minimaxminPlaymaxPlay将始终选择第一个空单元格。

以下是minPlay的修正案(minimaxmaxPlay可以同样修复):

def minPlay(currentBoard, player):
    if isGameOver(currentBoard):
        score = evaluate(currentBoard)
        return score
    # initialize the "best score" before the loop
    bestScore = 1000000
    for cell in getEmptySpots(currentBoard):
        x = cell[0]
        y = cell[1]
        currentBoard[x][y] = player
        score = maxPlay(currentBoard, -player)
        currentBoard[x][y] = 0
        # update the "best score"
        if score < bestScore:
            bestScore = score
    # return the "best score" after inspecting *all* empty cells
    return bestScore

答案 1 :(得分:1)

有两个问题。首先是@Flopp答案中的逻辑问题。第二个是当没有剩下的动作时isGameOver不会返回true。得分0作为初始最高或最低分数返回。

这里:

def minPlay(currentBoard, player):
    if isGameOver(currentBoard):
        score = evaluate(currentBoard)
        return score

相关(固定)线在这里(它不漂亮,它只是证明它会起作用):

def isGameOver(currentBoard):
    return checkGameOver(currentBoard, HUMAN) or checkGameOver(currentBoard, COMPUTER) or getEmptySpots(currentBoard) == []

对于minimax,确保最初的bestMove也是一个好主意。

def minimax(currentBoard, player):
    if isGameOver(currentBoard):
        score = evaluate(currentBoard)
        return score
    allMoves = getEmptySpots(currentBoard)
    bestMove = allMoves[0]
    for cell in allMoves: