Как я могу добавить ИИ в игру в крестики-нолики с помощью генератора случайных чисел на python?

#python #tic-tac-toe

#python #крестики-нолики

Вопрос:

Это одна из моих первых программ для онлайн-курса Python, который я прохожу. Я собрал некоторый код, который выполняет большую часть работы, но у меня все еще возникают проблемы с тем, чтобы заставить моего компьютерного игрока перейти к использованию библиотеки случайных чисел и прочитать их на доске. Я пытался переместить код внутри DrawMove() непосредственно в основной код, но безуспешно. В настоящее время я настроил его так, чтобы два игрока могли играть друг против друга, но я хочу добавить randrange к игроку ‘X’, чтобы игрок мог играть против компьютера.

 import itertools
from random import randrange

board = [[1,2,3],
         [4,'X',6],
         [7,8,9]]
   
         
def InitialBoard(board):
    print(" ------- ------- ------- n|       |       |       |n|  ",board[0][0],"  |  ",board[0][1],"  |  ",board[0][2],"  |")
    print("|       |       |       |n ------- ------- ------- n|       |       |       |")
    print("|  ",board[1][0],"  |  ",'X',"  |  ",board[1][2],"  |n|       |       |       |n ------- ------- ------- ")
    print("|       |       |       |n|  ",board[2][0],"  |  ",board[2][1],"  |  ",board[2][2],"  |n|       |       |       |")
    print(" ------- ------- ------- ")
    
def DisplayBoard(gameMap, playerMove, row, column):

    try:
        if board[row][column] == 'X' or board[row][column] == 'O':
            print("This space is occupied by X, please try another one.")
            return False
        gameMap[row][column] = playerMove #add parameters to our function
        for row, column in enumerate(gameMap):
            print(" ------- ------- ------- n|       |       |       |n|  ",board[0][0],"  |  ",board[0][1],"  |  ",board[0][2],"  |")
            print("|       |       |       |n ------- ------- ------- n|       |       |       |")
            print("|  ",board[1][0],"  |  ",'X',"  |  ",board[1][2],"  |n|       |       |       |n ------- ------- ------- ")
            print("|       |       |       |n|  ",board[2][0],"  |  ",board[2][1],"  |  ",board[2][2],"  |n|       |       |       |")
            print(" ------- ------- ------- ")
        return gameMap
    except IndexError: #handles index error
        print("Out of range, please choose a number between 0-2.")
        return False
    except Exception as e: #handles general errors, prints description of type of error
        print(str(e))
        return False


def VictoryFor(current_game):
   #horizontal
    for row in board:
     
        column1 = row[0] #all the same on top row
        column2 = row[1]
        column3 = row[2]
        if column1 == column2 == column3:#checks if top row same
            print(f"Player {row[0]} is the winner!")#f string is used to pass variables inside of curly braces
        

#vertical
    if board[0][0] == board[1][0] == board[2][0]:
        print("Winner in first column!")
        for row in board:
            print(row[0])
    elif board[0][1] == board[1][1] == board[2][1]:
        print("Winner in second column!")
        for row in board:
            print(row[1])
    elif board[0][2] == board[1][2] == board[2][2]:
        print("Winner in third column!")
        for row in board:
            print(row[2])

#diagonal
    if board[0][0] == board[1][1] == board[2][2]:
        print("Diagonal Winner down!")
    if board[2][0] == board[1][1] == board[0][2]:
        print("Diagonal Winner up!")


def DrawMove(board):#computer move
           
    row_choice = int(randrange(2))
    columnn_choice = int(randrange(2))

#main
play = True 
players = ['X','O']#computer is X, player is O. Computer makes first move.
while play:
    board = [[1, 2, 3],
             [4,'X',6],
             [7, 8, 9]]
             
    game_won = False
    player_cycle = itertools.cycle(['X','O'])
    InitialBoard(board)
    while not game_won:
        current_player = 'O'#computer has made move in center of board, your turn now
        current_player = next(player_cycle)
        played = False
        while not played:
            print(f"Player: {current_player}")
            column_choice = int(input("Pick a column 0-2:"))
            row_choice = int(input("Pick a row 0-2:"))
            played = DisplayBoard(board, playerMove = current_player, row = row_choice, column = column_choice)
    if VictoryFor(board):
        game_won = True
        again = input("The game is over, play again? Type (y/n)")
        if again.lower() == "y":
            print("Restarting")
        elif again.lower() == "n":
            print("Goodbye")
            play = False
        else:
            play = False
 

Комментарии:

1. Вопрос для меня неясен. В чем ваша конкретная проблема программирования?

Ответ №1:

Это может быть лучше подходит для https://codereview.stackexchange.com / но с одного места можно начать рассматривать вашу board переменную как «состояние игры».

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

Таким образом, вы можете думать о своей доске как о начальном значении, которое в конечном итоге заполняется неиграбельными пробелами, и вместо «случайного числа» вы можете думать о нем как о случайном «розыгрыше» из этого пула вариантов. Подумайте, что «рисовать из колоды карт» больше, чем «скажите мне случайное число».

Я думаю, что это было бы более эффективно, чем надеяться случайным образом выбрать правильную позицию.

Например, в тривиальной 1-строчной версии tic-tac-toe:

 row1 = [1, 2, 3]
mask = [1, 1, 1] # initial state
# human places an X at position 2:
mask = update() # mask for row1 becomes [1, 0, 1]

# AI now can determine that position 2 is not a valid spot:
valid_spots = list(filter(bool, [i*j for i,j in zip(row1, mask)])) # [1,3]

# choose a valid spot from the available indexes
choice_index = random.randint(0, len(valid_spots)-1)
new_move = row1[choice_index]
 

Ответ №2:

вы сбрасываете доску каждый раз, когда запускается цикл воспроизведения while

Комментарии:

1. Это хороший комментарий, но он не отвечает на вопрос OP.

2. я отложил это, потому что в op сразу же используется случайное значение, поскольку сразу после этого они сбрасывают плату, и это может восприниматься как неработающее