@SergeyBondarenko

Python создать функцию крестики-нолики с ИИ?

Ребят, я новичок, помогите пж как сделать чтобы вместо 2 игрока ходил компьютер? У меня уже есть функция computer.Не нужно просчитывать каждый ход, прост рандомное место чтоб выбирал. Только пожалуйста помогите с кодом, что за чем идёт и тд

from random import randint
    
    while True:
        BOARD_SIZE = 3
        board = [i for i in range(9)]
        is_winner = False
        current_player = randint(0, 1)
        markers = {0: 'O', 1: 'X'}
        available_turns = (x for x in range(9))
        rchoice = random.choice(board)
    
        def draw_board():
            res = ""
            for i, v in enumerate(board):
                res += str(v) + " "
                if (i+1) % BOARD_SIZE == 0:
                     res += "\n"
            print(res)
    
        def validate(value = " "):
            if not value.isdigit() and int(value) not in available_turns:
                raise ValueError ("Enter valid value and try again")
            if board[int(value)] in ('X', 'O'):
                raise ValueError ("This value has already played")
            if '.' in value:
                raise ValueError('Number must be int')
    
        def computer():
            if current_player == 1:
                flag = True
                while flag:
                    rchoice = randint(0,8)
                    validate()
                    flag = False
    
    
        def check_winner():
            current_marker = markers[current_player]
            if board[0] == current_marker and board[4] == current_marker and board[8] == current_marker or \
                    board[2] == current_marker and board[4] == current_marker and board[6] == current_marker or \
                    board[0] == current_marker and board[1] == current_marker and board[2] == current_marker or \
                    board[3] == current_marker and board[4] == current_marker and board[5] == current_marker or \
                    board[6] == current_marker and board[7] == current_marker and board[8] == current_marker or \
                    board[0] == current_marker and board[3] == current_marker and board[6] == current_marker or \
                    board[1] == current_marker and board[4] == current_marker and board[7] == current_marker or \
                    board[2] == current_marker and board[5] == current_marker and board[8] == current_marker:
                return True
            else:
                return False
    
        for i in range(9):
            try:
                input_error = True
                draw_board()
                while input_error:
                    computer()
                    choice = input(f"Player {markers[current_player]} enter your number:\n")
                    validate(choice)
                    input_error = False
                board[int(choice)] = markers[current_player]
                #проверить победителя
                is_winner = check_winner()
                if is_winner == True:
                    print(f'Player {markers[current_player]} won the game!!')
                    break
                current_player = 0 if current_player == 1 else 1
                # if is_winner == True:
            except ValueError as ex:
                print(ex)
    
        if is_winner == False:
            print('Draw')
        replay = input("Желаете переиграть? (Y or N)")
        if replay == "Y":
            continue
        else:
            break


И вот примерная функция компа (неправильная, но примерно что там должно по сути быть), над её правильно сделать:

def computer():
            if current_player == 1:
                flag = True
                while flag:
                    rchoice = randint(0,8)
                    validate(int(rchoice))
                    flag = False
  • Вопрос задан
  • 503 просмотра
Решения вопроса 1
D1os
@D1os
Начинающий программист
Ты импортируешь randint из модуля random.
from random import randint

При этом у тебя присутствует строка:
rchoice = random.choice(board)

Либо добавляй from random import choice, либо импортируй всю библиотеку.
Но это так, не по теме.
По поводу функции. Я бы сделал validate функцией, которая без всяких raise'ов проверяет значение на True или False и возвращает их вместе с ошибкой. Тогда эту функция можно будет использовать для проверки.
def validate(value=""):
    if value.isdigit():
        if int(value) in available_turns and board[int(value)] not in ["X", "O"]:
            return True
    print("Invalid input!")
    return False

Теперь эта функция проверяет ввод и возвращает истину только в верном случае. Соответственно, мы можем использовать её как логическое выражение.
if validate(choise):
    input_error = False

Далее computer. Тут допущена одна критическая ошибка: ты вызываешь validate() без аргумента.
validate()

Следовательно, функция всегда будет вызывать ошибку, т.е. нельзя преобразовать value = " " в число командой int(value) :)
if validate(rchoice):
    flag = False

Также, можно ускорить сам алгоритм нахождения случайного числа, использую массив доступных клеток, как сказал iddqda. У тебя есть список available_turns. В него можно запихнуть не иксы, а цифры от 0 до 8 - координаты полей, и каждым ходом удалять из него числа ходов (choice, rchoice). Проверке в validate это не навредит. Далее мы его используем в "вычислениях" хода компьютера.
rchoice = choice(available_turns)    # Если from random import choice

И он сразу найдёт случайное правильное число, а не будет по 300 раз находить одно и то же)
Есть ещё маленькая поправка, не влияющая на функционал: если переменная имеет значения не 0, True или строка как минимум с 1 символом, она будет считаться как True в логическом типе. Соответственно её можно вставлять в условие, как
v = "Hi!"
if v:
    print("Variable is true!")    # Вывод: Variable is true!

У тебя в коде можно заменить
if is_winner == True:

на
if is_winner:
Тоже в конце. А также, current_player у тебя либо 1, либо 0. Значит, это тоже true, false.
if current_player:
    flag = True
    # И так далее

И ещё кое-что :) желательно функции написать вне главного цикла while. Это не влияет на функционал, но код станет чуток приличнее.
P.s., если тебе нужен полный код функции, ответь на этот комм.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы