예제 #1
0
class Ai:
    def __init__(self):

        self.manager = GameManager()

    def minimax(self, board, OPlayer, alpha, beta, depth=float('inf')):
        # return the static evaluation of the final possible game
        # X wins: -1
        # O wins: +1
        # tie: 0

        if depth == 0 or self.manager.checkWin(board) or self.manager.checkTie(
                board):
            if self.manager.checkWin(board, True) == 'X':
                return -1
            elif self.manager.checkWin(board, True) == 'O':
                return 1
            elif self.manager.checkTie(board):
                return 0
            else:
                # depth not working properly
                return 0

        if OPlayer:
            maxValue = float('-inf')
            for cell in board:
                if cell.state == '':
                    cell.state = 'O'
                    value = self.minimax(board,
                                         False,
                                         alpha,
                                         beta,
                                         depth=depth - 1)
                    cell.state = ''
                    maxValue = max(maxValue, value)
                    alpha = max(alpha, value)
                    if beta <= alpha:
                        break

            return maxValue

        if OPlayer == False:
            minValue = float('inf')
            for cell in board:
                if cell.state == '':
                    cell.state = 'X'
                    value = self.minimax(board,
                                         True,
                                         alpha,
                                         beta,
                                         depth=depth - 1)
                    cell.state = ''
                    minValue = min(minValue, value)
                    beta = min(beta, value)
                    if beta <= alpha:
                        break
            return minValue

    def play(self, board):
        # choose a cell to play

        # initializing move to store the best cell to move
        bestCell = None
        bestScore = float('-inf')

        for cell in board:
            if cell.state == '':
                cell.state = 'O'
                score = self.minimax(board, False, float('-inf'), float('inf'))
                cell.state = ''

                if score > bestScore:
                    bestScore = score
                    bestCell = cell

        bestCell.changeState('O')
예제 #2
0
class MainGUI:
    def __init__(self):
        pygame.init()

        self.manager = GameManager()
        self.enemy = Ai()

        pygame.display.set_caption("Tic Tac Toe")

        self.WIDTH = 540
        self.HEIGHT = 540
        self.screen = pygame.display.set_mode((self.WIDTH, self.HEIGHT))

        self.background = pygame.Surface((self.WIDTH, self.HEIGHT))
        self.background.fill(pygame.Color('#E3E3E3'))

        # FONTS
        self.playerFont = pygame.font.SysFont('arial', 70)
        self.resultFont = pygame.font.SysFont('arial', 60, bold=True)
        self.infoFont = pygame.font.SysFont('arial', 30, italic=True)

        # define cell dimensions
        self.cellWidth = self.WIDTH / 3
        self.cellHeight = self.HEIGHT / 3
        self.board = []

        # to create the 3x3 grid
        for i in range(3):
            for j in range(3):
                self.board.append(
                    Cell(self.cellWidth * i, self.cellHeight * j, self.cellWidth, self.cellHeight))

        self.manager.gameState = 'progress'

        self.running = True

    def displayGrids(self):

        # horizontal lines
        for i in range(2):
            # pygame.draw.line(surface, color, start_pos, end_pos, width = 1)
            start_pos = (0, int(self.cellHeight * (i + 1)))
            end_pos = (self.WIDTH, int(self.cellHeight * (i + 1)))
            pygame.draw.line(self.background, (0, 0, 0),
                             start_pos, end_pos, 2)

        # vertical lines
        for i in range(2):
            # pygame.draw.line(surface, color, start_pos, end_pos, width = 1)
            start_pos = (int(self.cellWidth * (i + 1)), 0)
            end_pos = (int(self.cellWidth * (i + 1)), self.HEIGHT)
            pygame.draw.line(self.background, (0, 0, 0),
                             start_pos, end_pos, 2)

        for cell in self.board:
            player = self.playerFont.render(cell.state, True, (0, 0, 0))
            x, y = self.playerFont.size(cell.state)
            self.screen.blit(
                player, (int((cell.x + cell.w / 2) - x / 2), int((cell.y + cell.h / 2) - y / 2)))

    def endGameMsg(self, result):
        # rectangle that the message will be drawn
        w = self.WIDTH
        h = 150
        x = 0
        y = int(self.HEIGHT / 2 - h / 2)

        pygame.draw.rect(self.screen, pygame.Color(
            '#4D4D4D'), pygame.Rect(x, y, w, h))

        # result text
        if self.manager.result == 'tie':
            resultText = "It's a tie!"
            result = self.resultFont.render(resultText, True, (0, 0, 0))
        else:
            resultText = f"{self.manager.result} won!"
            result = self.resultFont.render(resultText, True, (0, 0, 0))

        x, y_txt = self.resultFont.size(resultText)

        self.screen.blit(result, (int(w / 2 - x / 2), int(y + 5)))

        # info text
        infoText = "Press R to restart the game!"
        info = self.infoFont.render(infoText, True, (0, 0, 0))

        x, y_txt = self.infoFont.size(infoText)

        self.screen.blit(info, (int(w / 2 - x / 2), int(y + 100)))

    def run(self):
        while self.running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False

                # check mouse down
                if event.type == pygame.MOUSEBUTTONDOWN:
                    if self.manager.gameState == 'progress':
                        for cell in self.board:
                            if self.manager.currentPlayer == 'X' and cell.checkUserCLicked(pygame.mouse.get_pos()) and cell.state == '':
                                # cause the O player is the AI
                                cell.changeState('X')
                                self.manager.changeTurn()

                # check keys pressed
                if event.type == pygame.KEYDOWN:
                    # restart the game
                    if event.key == pygame.K_r and self.manager.gameState == 'over':
                        self.manager.currentPlayer = 'X'
                        for cell in self.board:
                            cell.state = ''
                        self.manager.gameState = 'progress'

                    # recolorize the background
                    self.background.fill(pygame.Color('#ffffff'))

            # to check if there's a win
            if self.manager.checkWin(self.board):
                self.manager.currentPlayer = ''
                self.manager.gameState = 'over'
                self.manager.result = self.manager.checkWin(self.board, True)

            # to check if there's a tie
            if self.manager.checkTie(self.board):
                self.manager.currentPlayer = ''
                self.manager.gameState = 'over'
                self.manager.result = 'tie'

            # check if it's AI turn
            if self.manager.currentPlayer == 'O' and self.manager.gameState == 'progress':
                self.enemy.play(self.board)
                self.manager.changeTurn()

            # UI
            self.screen.blit(self.background, (0, 0))

            if self.manager.gameState == 'over':
                # if tie, paint te background gray
                if self.manager.result == 'tie':
                    self.background.fill(pygame.Color('#9DA897'))
                elif self.manager.result == 'X':
                    self.background.fill(pygame.Color('#7AFF77'))
                elif self.manager.result == 'O':
                    self.background.fill(pygame.Color('#F53920'))

                self.displayGrids()
                self.endGameMsg(self.manager.result)

            if self.manager.gameState != 'over':
                self.displayGrids()

            pygame.display.update()