示例#1
0
def alpha_beta_dp(game: ConnectNGame, status, alpha=None, beta=None) -> int:
    assert not game.gameOver
    if game.currentPlayer == ConnectNGame.PLAYER_A:
        ret = -math.inf
        for pos in game.getAvailablePositions():
            result = game.move(*pos)
            if result is None:
                assert not game.gameOver
                result = alpha_beta_dp(game, game.getStatus(), alpha, beta)
            game.undo()
            alpha = max(alpha, result)
            ret = max(ret, result)
            if alpha >= beta or ret == 1:
                return ret
        return ret
    else:
        ret = math.inf
        for pos in game.getAvailablePositions():
            result = game.move(*pos)
            if result is None:
                assert not game.gameOver
                result = alpha_beta_dp(game, game.getStatus(), alpha, beta)
            game.undo()
            beta = min(beta, result)
            ret = min(ret, result)
            if alpha >= beta or ret == -1:
                return ret
        return ret
示例#2
0
def minimax_dp(game: ConnectNGame, gameState) -> int:
    """

    :param game:
    :param isMaxPlayer:
    :return: 1, 0, -1
    """
    assert not game.gameOver
    if game.currentPlayer == ConnectNGame.PLAYER_A:
        ret = -math.inf
        for pos in game.getAvailablePositions():
            result = game.move(*pos)
            if result is None:
                assert not game.gameOver
                result = minimax_dp(game, game.getStatus())
            game.undo()
            ret = max(ret, result)
            if ret == 1:
                return 1
        return ret
    else:
        ret = math.inf
        for pos in game.getAvailablePositions():
            result = game.move(*pos)
            if result is None:
                assert not game.gameOver
                result = minimax_dp(game, game.getStatus())
            game.undo()
            ret = min(ret, result)
            if ret == -1:
                return -1
        return ret
示例#3
0
def minimax(game: ConnectNGame, isMaxPlayer: bool) -> int:
    """

    :param game:
    :param isMaxPlayer:
    :return: 1, 0, -1
    """
    assert not game.gameOver
    if isMaxPlayer:
        ret = -math.inf
        for pos in game.getAvailablePositions():
            result = game.move(*pos)
            if result is None:
                assert not game.gameOver
                result = minimax(game, not isMaxPlayer)
            game.undo()
            ret = max(ret, result)
            if ret == 1:
                return 1
        return ret
    else:
        ret = math.inf
        for pos in game.getAvailablePositions():
            result = game.move(*pos)
            if result is None:
                assert not game.gameOver
                result = minimax(game, not isMaxPlayer)
            game.undo()
            ret = min(ret, result)
            if ret == -1:
                return -1
        return ret
示例#4
0
    def __init__(self, board_size=3, connect_num=3):
        self.grid_size = 10
        self.start_x, self.start_y = 30, 50
        self.edge_size = self.grid_size / 2
        self.board_size = board_size
        self.connectNGame = ConnectNGame(N=connect_num, board_size=board_size)
        self.action = None

        pygame.init()

        self.screen = pygame.display.set_mode((800, 600))
        pygame.display.set_caption("TTT")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(pygame.font.get_default_font(), 24)
        self.going = True
示例#5
0
class PyGameBoard:
    def __init__(self, board_size=3, connect_num=3):
        self.grid_size = 10
        self.start_x, self.start_y = 30, 50
        self.edge_size = self.grid_size / 2
        self.board_size = board_size
        self.connectNGame = ConnectNGame(N=connect_num, board_size=board_size)
        self.action = None

        pygame.init()

        self.screen = pygame.display.set_mode((800, 600))
        pygame.display.set_caption("TTT")
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font(pygame.font.get_default_font(), 24)
        self.going = True

    def next_step(self):
        self.action = None
        while not self.action:
            self.update()
            self.render()
            self.clock.tick(60)
        return self.action

    def update(self):
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                self.going = False
            elif e.type == pygame.MOUSEBUTTONDOWN:
                self.handle_key_event(e)

    def next_user_input(self):
        self.action = None
        while not self.action:
            self.wait_user_input()
            self.render()
            self.clock.tick(60)
        return self.action

    def wait_user_input(self):
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                self.going = False
            elif e.type == pygame.MOUSEBUTTONDOWN:
                self.handle_user_input(e)

    # proxy methods
    def move(self, r: int, c: int):
        return self.connectNGame.move(r, c)

    def isGameOver(self):
        return self.connectNGame.gameOver

    def getAvailablePositions(self) -> List[Tuple[int, int]]:
        return self.connectNGame.getAvailablePositions()

    def getCurrentPlayer(self):
        return self.connectNGame.currentPlayer

    def getStatus(self):
        return self.connectNGame.getStatus()

    def render(self):
        self.screen.fill((255, 255, 255))
        self.screen.blit(
            self.font.render("FPS: {0:.2F}".format(self.clock.get_fps()), True,
                             (0, 0, 0)), (10, 10))

        self.draw(self.screen)
        if self.connectNGame.gameOver:
            self.screen.blit(
                self.font.render(
                    "{0} Win".format("Black" if self.connectNGame.gameResult ==
                                     ConnectNGame.PLAYER_A else "White"), True,
                    (0, 0, 0)), (500, 10))

        pygame.display.update()

    def handle_key_event(self, e):
        origin_x = self.start_x - self.edge_size
        origin_y = self.start_y - self.edge_size
        size = (self.board_size - 1) * self.grid_size + self.edge_size * 2
        pos = e.pos
        if origin_x <= pos[0] <= origin_x + size and origin_y <= pos[
                1] <= origin_y + size:
            if not self.connectNGame.gameOver:
                x = pos[0] - origin_x
                y = pos[1] - origin_y
                r = int(y // self.grid_size)
                c = int(x // self.grid_size)
                if self.connectNGame.move(r, c):
                    pass

    def handle_user_input(self, e):
        origin_x = self.start_x - self.edge_size
        origin_y = self.start_y - self.edge_size
        size = (self.board_size - 1) * self.grid_size + self.edge_size * 2
        pos = e.pos
        if origin_x <= pos[0] <= origin_x + size and origin_y <= pos[
                1] <= origin_y + size:
            if not self.connectNGame.gameOver:
                x = pos[0] - origin_x
                y = pos[1] - origin_y
                r = int(y // self.grid_size)
                c = int(x // self.grid_size)
                valid = self.connectNGame.checkAction(r, c)
                if valid:
                    self.action = (r, c)
                    return self.action

    def draw(self, screen):
        pygame.draw.rect(screen, (185, 122, 87), [
            self.start_x - self.edge_size, self.start_y - self.edge_size,
            (self.board_size - 1) * self.grid_size + self.edge_size * 2,
            (self.board_size - 1) * self.grid_size + self.edge_size * 2
        ], 0)

        for r in range(self.board_size):
            y = self.start_y + r * self.grid_size
            pygame.draw.line(
                screen, (0, 0, 0), [self.start_x, y],
                [self.start_x + self.grid_size * (self.board_size - 1), y], 2)

        for c in range(self.board_size):
            x = self.start_x + c * self.grid_size
            pygame.draw.line(
                screen, (0, 0, 0), [x, self.start_y],
                [x, self.start_y + self.grid_size * (self.board_size - 1)], 2)

        for r in range(self.board_size):
            for c in range(self.board_size):
                piece = self.connectNGame.board[r][c]
                if piece != ConnectNGame.AVAILABLE:
                    if piece == ConnectNGame.PLAYER_A:
                        color = (0, 0, 0)
                    else:
                        color = (255, 255, 255)

                    x = self.start_x + c * self.grid_size
                    y = self.start_y + r * self.grid_size
                    pygame.draw.circle(screen, color, [x, y],
                                       self.grid_size // 2)
示例#6
0
                    result, oppMove = self.minimax_dp(game.getStatus())
                else:
                    self.dp[game.getStatus()] = ret, bestMove
                game.undo()
                ret = max(ret, result)
                bestMove = move if ret == result else bestMove
            self.dp[gameState] = ret, bestMove
            return ret, bestMove
        else:
            ret = math.inf
            for pos in game.getAvailablePositions():
                move = pos
                result = game.move(*pos)
                if result is None:
                    assert not game.gameOver
                    result, oppMove = self.minimax_dp(game.getStatus())
                else:
                    self.dp[game.getStatus()] = ret, bestMove
                game.undo()
                ret = min(ret, result)
                bestMove = move if ret == result else bestMove
            self.dp[gameState] = ret, bestMove
            return ret, bestMove


if __name__ == '__main__':
    tic_tac_toe = ConnectNGame(N=3, board_size=3)
    strategy = CountMinimaxDPStrategy()
    print(strategy.action(tic_tac_toe))
    print(len(strategy.dp))
示例#7
0
                    return -1
            self.updateDP(thisState, ret)
            return ret


    def similarStatus(self, status):
        ret = []
        rotatedS = status
        for _ in range(4):
            rotatedS = self.rotate(rotatedS)
            ret.append(rotatedS)

        return ret


    def rotate(self, s):
        N = len(s)
        board = [[ConnectNGame.AVAILABLE] * N for _ in range(N)]

        for r in range(N):
            for c in range(N):
                board[c][N-1-r] = s[r][c]

        return tuple([tuple(board[i]) for i in range(N)])


if __name__ == '__main__':
    connectNGame = ConnectNGame(N=4, board_size=4)

    strategy = PlannedMinimaxStrategy(connectNGame)
示例#8
0
            for pos in game.getAvailablePositions():
                move = pos
                result = game.move(*pos)
                if result is None:
                    assert not game.gameOver
                    self.alphaBetaStack.append((alpha, beta))
                    result, oppMove = self.alpha_beta_dp(game.getStatus())
                    self.alphaBetaStack.pop()
                game.undo()
                beta = min(beta, result)
                ret = min(ret, result)
                bestMove = move if ret == result else bestMove
                if alpha >= beta or ret == -1:
                    return ret, move
            return ret, bestMove


if __name__ == '__main__':
    tic_tac_toe = ConnectNGame(N=3, board_size=3)
    # strategy1 = MinimaxDPStrategy(tic_tac_toe)
    # strategy2 = AlphaBetaStrategy(tic_tac_toe)
    # strategy3 = AlphaBetaDPStrategy(tic_tac_toe)

    while not tic_tac_toe.gameOver:
        strategy = MinimaxStrategy()
        r, action = strategy.action(tic_tac_toe)
        # print(f'{tic_tac_toe.getStatus()} [{r}] : {action}')
        tic_tac_toe.move(action[0], action[1])
        tic_tac_toe.drawText()
        # print('------------------------------------------------------------')