使用minimax算法的井字游戏无法正常工作

时间:2020-01-18 17:10:40

标签: python tic-tac-toe minimax

我的井字游戏似乎无法正常工作。我已经尝试了各种方法,但是没有任何变化。

您可以自己运行脚本,只是看到每次询问玩家的移动后,游戏都会在所需的列处形成X的垂直线并在此处终止。

尽管我无法在其中找到任何错误,但我实现minimax或computeMove函数可能存在问题。

# Boardsize initialization
boardSize = 0
# Board initialization
board = []

person = 'X'
ai = 'O'

#This variable indicates the player who has their turn at the moment.
currentPlayer = ''

# This shows the board.
for n in range (boardSize):
    for m in range (boardSize):
        print (" - "),
    print ("\n")

#Checking if somebody won (only horizontal or vertical)
def winLine(line, letter):
    return all(n == letter for n in line)

#New list from diagonals
def winDiagonal(board):
    return (board[n][n] for n in range (boardSize))

#The function universally checks whether somebody has won, or not.
def checkWinner (board):
    #Liczenie wolnych pol
    openSpots = 0
    for n in range(boardSize):
        for m in range(boardSize):
            if board[n][m] == '0':
                openSpots += 1

    #Transposition of the board, so it's possible to use winline() here
    for letter in (person, ai):
        transPos = list(zip(*board))

        #Horizontal check
        if any(winLine(row, letter) for row in board):
            return letter

        #Vertical check
        elif any (winLine(col, letter) for col in transPos):
            return letter

        #Diagonal check
        elif any (winLine(winDiagonal(dummy), letter) for dummy in (board, transPos)):
            return letter    

        elif openSpots == 0: return 'tie'

        else: return 'N/A'

#This function returns the player's move
def playerMove (row, col):

    #Checking if the field is clear
    if board[row][col] == '0':
        board[row-1][col-1] = person
    else:
        print('You cannot make that move.')

#Minimax constants

plusInf = float('inf')
minusInf = float('-inf')


#Lookup table for minimax scores
scores = {
    'X': 10,
    'O': -10,
    'None': 0
}

#Minimax itself

def minimax(baord, depth, maximizes):

    #Checking whether anybody has won
    res = checkWinner(board)
    if (res != 'N/A'):
        return scores[res]

    #Maximizing player
    if maximizes:
        minmaxBoard = board.copy()
        maxTarget = minusInf
        for n in range(boardSize):
            for m in range(boardSize):
                if minmaxBoard[n][m] == '0':
                    minmaxBoard[n][m] = ai
                    score = minimax(minmaxBoard, depth + 1, False)
                    maxTarget = max(score, maxTarget)

        return maxTarget

    #Minimizing player
    else:
        minTarget = plusInf
        minmaxBoard = board.copy()
        for n in range(boardSize):
            for m in range(boardSize):
                if minmaxBoard[n][m] == '0':
                    minmaxBoard[n][m] = person
                    score = minimax(minmaxBoard, depth + 1, True)
                    minTarget = min(score, minTarget)

        return minTarget

#The computer uses this function to make its move
def computedMove():
    computedTarget = minusInf
    for n in range(boardSize):
        for m in range(boardSize):
            newBoard = board.copy()
            if newBoard[n][m] == '0':               
                newBoard[n][m] = ai
                score = minimax(newBoard, 0, False)
                if score > computedTarget:
                    computedTarget = score
                    move = (n,m)
        board[move[0]][move[1]] = ai

# Getting input for the player's move
def getPlayerMove():
    res = input('Please type in your move on the form \"x y\", x being the number of the column and y the number of the row of your choosing.\n')
    col, row = res.split(" ")
    row = int(row)
    col = int(col)
    move = (row, col)
    return move

# Drawing the board
def drawBoard():
    for n in range(boardSize):
        for m in range(boardSize):
            if board[n][m] == '0':
                print(' - ', end='')
            else:
                print(' '+board[n][m]+' ', end='')
        print('\n')

# Current state of the game, False at first

playing = False

#The game loop

while True:
    currentPlayer = person
    boardSize = int(input("Please enter the size of the board. (one sie)\n"))
    board = [['0']*boardSize]*boardSize
    print("You go first.")
    playing = True

    while playing:
        if currentPlayer == person:
            drawBoard()
            move = getPlayerMove()
            playerMove(move[0]-1, move[1]-1)

            if checkWinner(board) == person:
                drawBoard()
                print("Yaay, you won!")
                playing = False

            else:
                if checkWinner(board) == 'tie':
                    drawBoard()
                    print('It\'s a tie!')
                    break
                else:
                    currentPlayer = ai

        if currentPlayer == ai:
            computedMove()

            if checkWinner(board) == ai:
                drawBoard()
                print('You lose!')
                playing = False
            else:
                if checkWinner(board) == 'tie':
                    drawBoard()
                    print('It\'s a tie!')
                    break
                else:
                    currentPlayer = person

    if not input('Do you want to play again?').lower().startswith('y'):
        break

1 个答案:

答案 0 :(得分:0)

查看以下语句:

board = [['0']*boardSize]*boardSize

您实际上是在创建boardSize次相同列表引用的列表。这就是为什么当您向board[i][j]元素分配内容时,它被分配给所有rows(从board[0]board[len(board)])的第j个元素,因为所有行都是引用相同的列表。

改为使用此:

board = [['0'] * boardSize for _ in range(boardSize)]

此代码还有其他问题。例如,我确定您要递减(x, y)索引。我没有进一步检查。