Мой Ti c Ta c Toe с использованием минимаксного алгоритма не работает - PullRequest
0 голосов
/ 18 января 2020

My ti c -ta c - кажется, что работает неправильно. Я пробовал разные вещи, но ничего не меняется.

Вы можете запустить скрипт самостоятельно, просто чтобы увидеть, что каждый раз, когда он спрашивает ход игрока, игра делает вертикальную линию X в нужном столбце и заканчивается там.

Вероятно, это проблема с моей реализацией minimax или функции computedMove, хотя я не могу найти там никаких ошибок.

# 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 голосов
/ 19 января 2020

Проверьте это утверждение:

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

Вы по сути создаете список ссылок на один и тот же список boardSize раз. Вот почему, когда вы присваиваете что-то элементу board[i][j], он присваивается j-м элементам всех rows (от board[0] до board[len(board)]), потому что все строки ссылаются на один и тот же список.

Используйте это вместо:

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

Есть и другие проблемы с этим кодом. Я уверен, что вы уменьшаете свои (x, y) индексы, например, несколько раз. Я не проверял это дальше.

...