Python крестики-нолики AI

Я только что закончил работу над ИИ для крестиков-ноликов и был бы очень благодарен за мнения и комментарии по этому проекту. Я хотел бы добавить его в свой «портфель разработчиков Python начального уровня».

ПРОЧТИ МЕНЯ:

Простой ИИ, играющий сам с собой в крестики-нолики. Вначале ходы выбираются случайным образом, каждый возможный ход имеет одинаковую вероятность разыгрывания. Последовательность ходов, которая приводит к победе, набирает очки, поэтому в будущих играх будет больше шансов выбрать этот ход. Соответственно ходы, закончившиеся в проигрышном состоянии, будут выбираться реже. Примерно после 200 000 игр будет более 99% ничьих — оба игрока не сделают ни одной ошибки в более чем 99% игр.

Основной класс:

import rules

#main game loop. Number of repetition defines how many games are played

for i in range (1):

    #these two lists are used to store moves used in each game
    moves_X = []
    moves_O = []

    #creation of an empty board, flags move_X and move_O are used to define whether it is Xs or Os move at the moment
    board = [{'number': 100000, 'board': [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '], 'value': 100}]
    move_X = True
    move_O = False
    #change flag is the cap that prevents the game to be played for longher than 9 moves
    change = 0

    #this loop goes on until Os or Xs wins or it is a draw
    while True:


        if move_X and change <= 4:

            #to define new board after Xs move we use function called draw() defined in the rules module
            board = rules.draw(0, change, board)
            moves_X.append(board)

            #to visualize the game we use draw_board() function defined in rules module
            print(rules.draw_board(board))



            move_X = False
            move_O = True

            #using iswin function from rules() we check if Xs have alredy won
            if (rules.iswin(board[0]['board'], 'X')):

                print(rules.draw_board(board))
                print('X won!')



                #if Xs won we add points to all of Xs moves from that game
                #and take points from Os moves
                for move in moves_X:
                    move[0]['value'] += 1

                for move in moves_O:
                    if move[0]['value'] > 1:
                        move[0]['value'] -= 1

                break

        #next O play its move
        elif move_O and change<4:
            board = rules.draw(1, change, board)

            print(rules.draw_board(board))

            moves_O.append(board)
            move_X = True
            move_O = False

            change += 1
            if (rules.iswin(board[0]['board'], 'O')):

                print(rules.draw_board(board))
                print('O won!')



                for move in moves_O:
                        move[0]['value'] += 1

                for move in moves_X:
                    if move[0]['value'] > 1:
                        move[0]['value'] -= 1

                break

        #if the board is full and neither of the players won
        else:
            print('Draw!')
            break


#after compliton of the main game loop we save the results
rules.save()

all_data Класс:

import itertools

#used to create list of all combinations of ' ', X and O. Each combination have its number and value
#that list will be filtered and sorted in the data_base module
def board_init():

move_number = []

for b,i in enumerate(itertools.product(' XO', repeat=9)):

    if b==100000:
        break
    else:
        move_n_number = {'number': b, 'board': i, 'value': 100}
        move_number.append(move_n_number)

return move_number

data_base Класс:

import all_data
import json

#board_sort module sorts and filters list created with board_init() in the all_data module
def board_sort(move_n):

#move_list_X and move_list_O are used to sort moves by sign and number, from first to fifth in Xs and fourth in Os.
move_list_X=[[], [], [], [], []]
move_list_O=[[], [], [], []]

move_list = (move_list_X, move_list_O)



for i in move_n:
    if i.get('board').count('X')==1 and i.get('board').count('O')==0:
        move_list_X[0].append(i)


    elif i.get('board').count('X')==1 and i.get('board').count('O')==1:
        move_list_O[0].append(i)

    elif i.get('board').count('X')==2 and i.get('board').count('O')==1:
        move_list_X[1].append(i)

    elif i.get('board').count('X')==2 and i.get('board').count('O')==2:
        move_list_O[1].append(i)

    elif i.get('board').count('X')==3 and i.get('board').count('O')==2:
        move_list_X[2].append(i)

    elif i.get('board').count('X')==3 and i.get('board').count('O')==3:
        move_list_O[2].append(i)

    elif i.get('board').count('X')==4 and i.get('board').count('O')==3:
        move_list_X[3].append(i)

    elif i.get('board').count('X')==4 and i.get('board').count('O')==4:
        move_list_O[3].append(i)

    elif i.get('board').count('X')==5 and i.get('board').count('O')==4:
        move_list_X[4].append(i)

    else:
        continue

return move_list

def save(move_list):
with open('all_moves.txt', 'w') as f:
    json.dump(move_list, f)

правила Класс:

import random
import json
import all_data
import data_base



#if there is no file 'all_moves.txt' it is is created 
try:

    with open('all_moves.txt') as json_file:
        move_list = json.load(json_file)

except IOError:
    move_n = all_data.board_init()
    move_list = data_base.board_sort(move_n)



#iswin function is used to check if Xs or Os have alredy won
def iswin(board, letter="X"):

if board[0]==letter and board[1]==letter and board[2]==letter:
    return True
elif board[3]==letter and  board[4]==letter and board[5]==letter:
    return True
elif board[6] == letter and board[7] == letter and board[8] == letter:
    return True
elif board[0] == letter and board[3] == letter and board[6] == letter:
    return True
elif board[1] == letter and board[4] == letter and board[7] == letter:
    return True
elif board[2] == letter and board[5] == letter and board[8] == letter:
    return True
elif board[0] == letter and board[4] == letter and board[8] == letter:
    return True
elif board[6] == letter and board[4] == letter and board[2] == letter:
    return True
else:
    return False





#draw function is used to draw a move from a list of possible moves
#the probability of each choice is dependent on previous results
def draw(letter, number, board):
possible_moves=[]
move = move_list[letter][number]

for i in move:

    sum=0

    for z, g in zip(i['board'], board[0]['board']):

        if z==g:
            continue
        else:
            sum += 1
    if sum==1:
        possible_moves.append(i)
    else:
        continue

return(random.choices(possible_moves, weights=[i['value'] for i in possible_moves], k = 1))



#saves changes made in the 'all_moves.txt' file
def save():
with open('all_moves.txt', 'w') as f:
    json.dump(move_list, f)

#function used to visualize present state of the board
def draw_board(board):
return(
'''
{}
{}
{}
'''.format(board[0]['board'][:3], board[0]['board'][3:6], board[0]['board'][6:])
)

Ссылка на Github

Ваше здоровье!

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *