Python крестики-нолики с ИИ
Как сделать так, чтобы вместо 2 игрока играл компьютери просто выбирал рандомные пустые места (с объяснением решения если можно)
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))
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 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:
choice = input(f"Player {markers[current_player]} enter your number:\n")
validate(choice)
input_error = False
board[int(choice)] = markers[current_player]
if current_player == 1:
#проверить победителя
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
Ответы (2 шт):
Делал такого бота. Пусть крестики - игрок, а нолики - ИИ .Смысл таков:(игрок ходит первый)ВЫ должны проверять 3 клетки по горизонтали, вертикали и диагонали. Если там находится два крестика и нету ноликов, то бот должен поставить нолик в той линии, где два крестика чтобы не проиграть. Если нет такой линии (с двумя крестиками), то бот должен строить свою линию ноликов для победы. Он должен найти такую линию, где нету крестиков и ОБЯЗАТЕЛЬНО с максимальным кол-во ноликов. После того, как он эту линию нашел он должен поставить там нолик. Все это для поля 3х3
если еще актуально, в интернете есть алгоритм минимакс и его объяснение на примере игры крестики нолики. Сам тоже писал тг бота для крестиков ноликов, использовал этот алгоритм. Алгоритм заключается в том что рекурсионно просчитывает все варианты развития игры для каждой клетки и опираясь на конечный результат игры для каждой клеточки в некоей переменной, привязанной к этой клетке, увеличивает если выиграл бот, уменьшает если человек, не изменяет если ничья. И на основе этой переменной выбирает в какую клетку сходить. Это тяжело звучит, и всю суть я не передал, но сама функция minimax у меня в программе вышла не большая - строк 30-40.
Если будете его использовать, желаю вам не запутаться в рекурсии)
Вот такие консольные крестики нолики получились у меня, но есть одно но: первый ход бот делает почему-то не в центр(что более выгодно), а в угловую клетку(на счет этого есть выход - насильно заставить бота сходить в центр, если он еще пуст). Но в остальном бот играет адекватно. Вот код:
import sys
sys.setrecursionlimit(1000000) # увеличиваем максимальную глубину рекурсии
huplayer = 'O'
aiplayer = 'X'
class Move: # класс Ход
index = -1
score = 0
def get_empty_cells(board):
# возвращает список пустых клеток
l = []
for i in board:
if i != 'X' and i != 'O':
l.append(i)
return l
def check_win(board, player):
# Проверяем, выиграл ли player
if ((board[2] == player and board[4] == player and board[6] == player) or
(board[0] == player and board[1] == player and board[2] == player) or
(board[3] == player and board[4] == player and board[5] == player) or
(board[6] == player and board[7] == player and board[8] == player) or
(board[0] == player and board[3] == player and board[6] == player) or
(board[1] == player and board[4] == player and board[7] == player) or
(board[2] == player and board[5] == player and board[8] == player) or
(board[0] == player and board[4] == player and board[8] == player)):
return True
else:
return False
def minimax(new_board, player):
global aiplayer, huplayer
# доступные клетки
avail_spots = get_empty_cells(new_board)
if check_win(new_board, huplayer):
ret = Move
ret.score = -10
return ret
elif check_win(new_board, aiplayer):
ret = Move
ret.score = 10
return ret
elif len(avail_spots) == 0:
ret = Move
ret.score = 0
return ret
moves = []
for i in range(len(avail_spots)):
moves.append(Move())
moves[i].score = 0
moves[i].index = new_board[avail_spots[i]]
new_board[avail_spots[i]] = player
if player == aiplayer:
moves[i].score += minimax(new_board, huplayer).score
else:
moves[i].score += minimax(new_board, aiplayer).score
new_board[avail_spots[i]] = moves[i].index
best_move = Move()
if player == aiplayer:
best_move.score = -10000
for i in moves:
if i.score > best_move.score:
best_move.score = i.score
best_move.index = i.index
else:
best_move.score = 10000
for i in moves:
if i.score < best_move.score:
best_move.score = i.score
best_move.index = i.index
return best_move
def draw_board(board):
board4draw = []
for j in board:
if j in ('X', 'O'):
board4draw.append(j)
else:
board4draw.append(' ')
for h in range(3):
print(f'|{board4draw[h*3]}|{board4draw[h*3 + 1]}|{board4draw[h*3 + 2]}|')
def game():
board = [0, 1, 2, 3, 4, 5, 6, 7, 8]
# main game loop
run = True
global aiplayer, huplayer
player = aiplayer # кто первый ходит
while run:
if check_win(board, aiplayer):
print('bot win')
run = False
continue
elif check_win(board, huplayer):
print('you win')
run = False
continue
empty_cells = get_empty_cells(board)
if len(empty_cells) != 0:
if player == aiplayer:
print('bot made move:')
bot_move = minimax(board, aiplayer).index
board[bot_move] = aiplayer
draw_board(board)
player = huplayer
continue
elif player == huplayer:
human_move = int(input('ведите цифру: '))
# human_move = minimax(board, huplayer)
print('you made move:')
board[human_move] = huplayer
draw_board(board)
player = aiplayer
continue
else:
print('draw')
run = False
game()