Python 我不知道';我不能让我的AI玩Tictatcoe。如何提高其性能?

Python 我不知道';我不能让我的AI玩Tictatcoe。如何提高其性能?,python,pygame,neat,Python,Pygame,Neat,AI是用整洁的python构建的。输入是游戏板上的字段列表(0:Unoccubied,1:player1,2:player2)。AI产生9个输出,最大值(输出)的索引被选为要执行的字段。它针对随机选择田地的机器人进行训练。如果要转到的字段已被占用,则第一个空闲字段将被设置为要转到的字段 import neat import pygame import os import json import random import checkpoint import winsound import tim

AI是用整洁的python构建的。输入是游戏板上的字段列表(0:Unoccubied,1:player1,2:player2)。AI产生9个输出,最大值(输出)的索引被选为要执行的字段。它针对随机选择田地的机器人进行训练。如果要转到的字段已被占用,则第一个空闲字段将被设置为要转到的字段

import neat
import pygame
import os
import json
import random
import checkpoint
import winsound
import time
import matplotlib.pyplot as plt

pygame.init()
cloud = checkpoint.Checkpointer()
p = None
GEN = 0
screen = None
pygame.display.set_caption("Tic Tac Toe")
o_icon = pygame.image.load("o.png")
x_icon = pygame.image.load("x.png")

class Field:
    def __init__(self):
        self.field = [0,0,0, 0,0,0, 0,0,0]
        self.winner = None

    def reset(self):
        self.field = [0,0,0, 0,0,0, 0,0,0]
        self.winner = None

    def display(self):
        screen.fill([0,0,0])
        self.display_pieces()
        self.display_board()
        pygame.display.update()

    def display_pieces(self):
        pos_to_pix = {
            0: (0,0),
            1: (100,0),
            2: (200,0),
            3: (0,100),
            4: (100,100),
            5: (200,100),
            6: (0, 200),
            7: (100, 200),
            8: (200, 200)
        }
        for pos in range(len(self.field)):
            if self.field[pos] == 1:
                screen.blit(x_icon, pos_to_pix[pos])
            elif self.field[pos] == 2:
                screen.blit(o_icon, pos_to_pix[pos])

    @staticmethod
    def pos_to_field(pos):
        x = pos[0]
        y = pos[1]
        if x < 100:
            x = 0
        elif x < 200:
            x = 1
        else:
            x = 2
        if y < 100:
            y = 0
        elif y < 200:
            y = 1
        else:
            y = 2
        return x+y*3

    @staticmethod
    def display_board():
        pygame.draw.rect(screen, "White", [0,99, 300,2])
        pygame.draw.rect(screen, "White", [0,199, 300,2])
        pygame.draw.rect(screen, "White", [99,0, 2,300])
        pygame.draw.rect(screen, "White", [199,0, 2,300])

    def action(self, field_id, player_id):
        self.field[field_id] = player_id

    def field_is_free(self, field):
        if self.field[field] == 0:
            return True
        return False

    def check_winner(self):
        for line in range(3):
            # check horizontal
            if self.field[line*3] == self.field[line*3+1] == self.field[line*3+2] != 0:
                self.winner = self.field[line*3]
                return True, self.winner
            if self.field[line] == self.field[line+3] == self.field[line+6] != 0:
                self.winner = self.field[line]
                return True, self.winner
        if self.field[0] == self.field[4] == self.field[8] != 0:
            self.winner = self.field[0]
            return True, self.winner
        if self.field[2] == self.field[4] == self.field[6] != 0:
            self.winner = self.field[2]
            return True, self.winner
        return False

    def first_free(self):
        for index, value in enumerate(self.field):
            if value == 0:
                return index

class Player:
    def __init__(self, id, being, brain=None):
        self.id = id
        self.being = being
        self.brain = brain

class Graph:
    def __init__(self):
        self.gens = []
        self.maxs = []
        self.losts = []
        self.drawns = []
        self.wons = []
        self.average = []
        self.last_gens = 50
        self.vmax = None

    def add(self, gen, vmax_round, lost, drawn, won):
        self.gens.append(gen)
        self.maxs.append(vmax_round)
        self.losts.append(lost)
        self.drawns.append(drawn)
        self.wons.append(won)
        self.average.append(sum(self.maxs[-min(self.last_gens,gen):]) / min(self.last_gens,gen))
        self.vmax = max(self.maxs)

    def display(self):
        plt.figure(figsize=(10,6))
        plt.plot(self.gens, self.maxs, label="Best Fitness")
        plt.plot(self.gens, self.average, label="Average Fitness last " + str(self.last_gens) + " generations")
        plt.plot(self.gens, self.losts,  label="Lost")
        plt.plot(self.gens, self.drawns,  label="Drawn")
        plt.plot(self.gens, self.wons,  label="Won")
        plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
        plt.grid("on")
        plt.tight_layout()
        plt.show()

    def save(self):
        with open('gens.txt', 'w') as filehandle:
            json.dump(self.gens, filehandle)
        with open('maxs.txt', 'w') as filehandle:
            json.dump(self.maxs, filehandle)
        with open('average.txt', 'w') as filehandle:
            json.dump(self.average, filehandle)
        with open('losts.txt', 'w') as filehandle:
            json.dump(self.losts, filehandle)
        with open('drawns.txt', 'w') as filehandle:
            json.dump(self.drawns, filehandle)
        with open('wons.txt', 'w') as filehandle:
            json.dump(self.wons, filehandle)

    def load(self):
        with open('gens.txt', 'r') as filehandle:
            self.gens = json.load(filehandle)
        with open('maxs.txt', 'r') as filehandle:
            self.maxs = json.load(filehandle)
        with open('average.txt', 'r') as filehandle:
            self.average = json.load(filehandle)
        with open('losts.txt', 'r') as filehandle:
            self.losts = json.load(filehandle)
        with open('drawns.txt', 'r') as filehandle:
            self.drawns = json.load(filehandle)
        with open('wons.txt', 'r') as filehandle:
            self.wons = json.load(filehandle)

graph = Graph()
board = Field()

def place_piece(player, field):
    board.field[field] = player.id

def sound():
    winsound.Beep(440,200)

def train(genomes, config):
    global GEN
    GEN += 1
    best_fitness = 0
    players = [None, None]
    best_lost, best_drawn, best_won = 0,0,0

    for index, genome in genomes:
        index -= 1
        genome.fitness = 0
        net = neat.nn.FeedForwardNetwork.create(genome, config)

        players[0] = Player(1, "random")
        players[1] = Player(2, "ai")
        lost, drawn, won = 0,0,0

        for round in range(100):
            if round == 50:
                players[0] = Player(1, "ai")
                players[1] = Player(2, "random")

            field_to_go = -1
            placed = 0
            player = players[0]

            while True:
                if player.being == "random":
                    field_to_go = random.randint(0,8)
                elif player.being == "ai":
                    output = net.activate(board.field)
                    field_to_go = output.index(max(output))
                elif player.being == "human":
                    for event in pygame.event.get():
                        if event.type == pygame.QUIT:
                            pygame.quit()
                            break
                        elif event.type == pygame.MOUSEBUTTONUP:
                            field_to_go = board.pos_to_field(pygame.mouse.get_pos())

                if field_to_go > -1:
                    if board.field_is_free(field_to_go):
                        board.action(field_to_go, player.id)
                    else:
                        board.action(board.first_free(), player.id)

                    if player == players[0]:
                        player = players[1]
                    else:
                        player = players[0]
                    placed += 1

                if shown:
                    board.display()
                    time.sleep(1)

                if board.check_winner() or placed == 9:
                    if board.winner is None:
                        genome.fitness += 1
                        drawn += 1
                    elif players[board.winner-1].being == "ai":
                        genome.fitness += 2
                        won += 1
                    else:
                        genome.fitness -= 0
                        lost += 1
                    board.reset()
                    break
        if genome.fitness > best_fitness:
            best_fitness = genome.fitness
            best_lost = lost
            best_drawn = drawn
            best_won = won
    graph.add(GEN, best_fitness, best_lost, best_drawn, best_won)

def test(genome):
    result = [0,0,0]
    players = [None, None]
    for round in range(1000):
        placed = 0
        if round % 2 == 0:
            players[0] = Player(1, "ai")
            players[1] = Player(2, "human")
        else:
            players[0] = Player(1, "human")
            players[1] = Player(2, "ai")

        player = players[0]
        while True:
            field_to_go = -1
            if player.being == "random":
                field_to_go = random.randint(0,8)
            elif player.being == "ai":
                output = genome.activate(board.field)
                field_to_go = output.index(max(output))
            elif player.being == "human":
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        break
                    elif event.type == pygame.MOUSEBUTTONUP:
                        field_to_go = board.pos_to_field(pygame.mouse.get_pos())

            if field_to_go > -1:
                if board.field_is_free(field_to_go):
                    board.action(field_to_go, player.id)
                else:
                    board.action(board.first_free(), player.id)
                if player == players[0]:
                    player = players[1]
                else:
                    player = players[0]
                placed += 1

            if shown:
                pygame.event.get()
                board.display()
                time.sleep(0.75)

            if board.check_winner() or placed == 9:
                if board.winner is None:
                    result[1] += 1
                elif players[board.winner-1].being == "ai":
                    result[2] += 1
                else:
                    result[0] += 1
                if shown:
                    if board.winner is None:
                        print("None")
                    else:
                        print(players[board.winner-1].being + " " + str(player.id))
                board.reset()
                break
    print(result)

def run(config_path):
    global shown
    global GEN
    global screen
    config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
                                neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path)
    nc_name = "population"

    testing = False
    shown = False
    new = True

    if testing:
        if shown:
            screen = pygame.display.set_mode((300, 300))
            pygame.display.set_caption("Tic Tac Toe")
        test(neat.nn.FeedForwardNetwork.create(cloud.restore_checkpoint("population").population.best_genome, config))
        quit()

    if new:
        p = neat.Population(config)
        p.add_reporter(neat.StdOutReporter(True))
        p.add_reporter(neat.StatisticsReporter())
    else:
        p = cloud.restore_checkpoint(nc_name).population
        graph.load()
    GEN = p.generation
    p.run(train,250)
    print(time.strftime("%H:%M:%S", time.localtime()))
    cloud.save_checkpoint(config, p, p.species, GEN, nc_name)
    graph.save()
    graph.display()
    sound()

if __name__ == "__main__":
    local_dir = os.path.dirname(__file__)
    config_path = os.path.join(local_dir, "config_feedforward")
    run(config_path)
导入整洁
导入pygame
导入操作系统
导入json
随机输入
导入检查点
导入winsound
导入时间
将matplotlib.pyplot作为plt导入
pygame.init()
cloud=checkpoint.Checkpointer()
p=无
GEN=0
屏幕=无
pygame.display.set_标题(“Tic-Tac-Toe”)
o_icon=pygame.image.load(“o.png”)
x_icon=pygame.image.load(“x.png”)
类别字段:
定义初始化(自):
self.field=[0,0,0,0,0,0,0]
self.winner=无
def重置(自):
self.field=[0,0,0,0,0,0,0]
self.winner=无
def显示(自):
屏幕填充([0,0,0])
self.display_件()
自显示板()
pygame.display.update()
def显示部件(自身):
位置到像素={
0: (0,0),
1: (100,0),
2: (200,0),
3: (0,100),
4: (100,100),
5: (200,100),
6: (0, 200),
7: (100, 200),
8: (200, 200)
}
对于范围内的位置(len(self.field)):
如果自身字段[pos]==1:
屏幕.blit(x_图标,位置到pix[pos])
elif自身字段[pos]==2:
屏幕.blit(o_图标,位置到位置[pos])
@静力学方法
def pos_至_字段(pos):
x=位置[0]
y=位置[1]
如果x<100:
x=0
elif x<200:
x=1
其他:
x=2
如果y<100:
y=0
elif y<200:
y=1
其他:
y=2
返回x+y*3
@静力学方法
def显示板():
pygame.draw.rect(屏幕,“白色”[0,99300,2])
pygame.draw.rect(屏幕,“白色”[0199300,2])
pygame.draw.rect(屏幕,“白色”[99,02300])
pygame.draw.rect(屏幕,“白色”[199,02300])
def动作(自我、场号、球员号):
self.field[field\u id]=玩家\u id
def field_是自由的(自我,字段):
如果self.field[field]==0:
返回真值
返回错误
def检查优胜者(自我):
对于范围(3)中的行:
#水平检查
如果self.field[line*3]==self.field[line*3+1]==self.field[line*3+2]!=0:
self.winner=self.field[第*3行]
回归真实,自我胜利
如果self.field[line]==self.field[line+3]==self.field[line+6]!=0:
self.winner=self.field[行]
回归真实,自我胜利
如果self.field[0]==self.field[4]==self.field[8]!=0:
self.winner=self.field[0]
回归真实,自我胜利
如果self.field[2]==self.field[4]==self.field[6]!=0:
self.winner=self.field[2]
回归真实,自我胜利
返回错误
def第一自由(自我):
对于索引,枚举中的值(self.field):
如果值==0:
回报指数
职业球员:
定义初始(自我、身份、存在、大脑=无):
self.id=id
自我存在
self.brain=大脑
类图:
定义初始化(自):
self.gens=[]
self.maxs=[]
self.losts=[]
self.drawns=[]
self.wons=[]
self.average=[]
自身最后一个发电机组=50
self.vmax=None
def添加(自我、一般、最大轮、损失、平局、赢得):
self.gens.append(gen)
self.maxs.append(vmax\u轮)
self.losts.append(丢失)
self.drawns.append(已绘制)
self.wons.append(won)
self.average.append(总和(self.maxs[-min(self.last\u gens,gen):])/min(self.last\u gens,gen))
self.vmax=max(self.maxs)
def显示(自):
plt.图(figsize=(10,6))
plt.plot(self.gens、self.maxs、label=“最佳适合度”)
plt.plot(self.gens,self.average,label=“平均适合度最后一代”+str(self.last_gens)+“世代”)
plt.plot(self.gens,self.losts,label=“Lost”)
plt.绘图(self.gens,self.drawns,label=“Drawn”)
plt.plot(self.gens、self.wons、label=“Won”)
plt.图例(bbox_to_anchor=(1.05,1),loc=“左上”)
公共电网(“on”)
plt.紧_布局()
plt.show()
def保存(自我):
以open('gens.txt','w')作为文件句柄:
json.dump(self.gens,filehandle)
以open('maxs.txt','w')作为文件句柄:
json.dump(self.maxs,filehandle)
以open('average.txt','w')作为文件句柄:
json.dump(self.average,filehandle)
以open('losts.txt','w')作为文件句柄:
dump(self.losts,filehandle)
以open('drawns.txt','w')作为文件句柄:
dump(self.drawns,filehandle)
以open('wons.txt','w')作为文件句柄:
json.dump(self.wons,filehandle)
def加载(自):
以open('gens.txt','r')作为文件句柄:
self.gens=json.load(filehandle)
以open('maxs.txt','r')作为文件句柄:
self.maxs=json.load(文件句柄)
以open('average.txt','r')作为文件句柄:
self.average=json.load(filehandle)
以open('losts.txt','r')作为文件句柄:
self.losts=json.load(filehandle)
以open('drawns.txt','r')作为文件句柄:
self.drawns=json.load(filehandle)
以open('wons.txt','r')作为文件句柄:
self.wons=json.load(filehandle)
图=图()
board=字段()
def place_工件(球员、场地):
board.field[字段]=player.id
def sound():
winsound.Beep(440200)
def序列(基因组,配置):
全球发电机
发电机+=1
最佳适配度=0
玩家=[无,无]