人工智能第一次作业

作业题目:

  1. 你对人工智能定义的理解?

人工智能是智能科学中涉及研究、设计与应用智能机器和智能系统的一个分支,而智能科学是一门与计算机科学并行的学科。

人工智能是智能机器所执行的通常与人类智能有关的智能行为,这些智能行为涉及学习、感知、思考、理解、识别、判断、推理、证明、通信、设计、规划、行动和问题求解等活动。

  1. 解释什么是图灵测试?

图灵测试(The Turing test)由艾伦·麦席森·图灵发明,指测试者与被测试者(一个人和一台机器)隔开的情况下,通过一些装置(如键盘)向被测试者随意提问。进行多次测试后,如果机器让平均每个参与者做出超过30%的误判,那么这台机器就通过了测试,并被认为具有人类智能。图灵测试一词来源于计算机科学和密码学的先驱艾伦·麦席森·图灵写于1950年的一篇论文《计算机器与智能》,其中30%是图灵对2000年时的机器思考能力的一个预测,目前我们已远远落后于这个预测。

  1. 你希望人工智能帮你做些什么?

回答问题:回答关于各种领域的问题,对人所不知道的提供信息和解释概念。

写作和编辑:撰写文章、报告、邮件和其他文本。

编程和技术支持:解决编程问题、编写代码或提供技术支持。

语言翻译

根据用户的需求提供帮助和支持,使我们的生活更加便捷和高效。

4、8数码问题,如上图所示的过程,要求:空格按照左、上、右、下的顺序依次扩展。

分别用BFS、DFS(深度为5)、UCS、Greedy (启发函数h自拟) 、A*(启发函数h自拟)算法进行求解。

BFS:通过广度优先搜索从初始状态逐步向目标状态前进,记录每一步的移动操作,直到找到解决方案。

创建一个双端队列(deque),用于进行广度优先搜索。

队列中的元素是一个三元组 (当前状态, 移动序列, 步数),其中:

当前状态 表示当前的数码状态。

移动序列 用于记录达到当前状态的移动序列。

步数 表示从初始状态到当前状态的步数。

from collections import deque



# 定义初始状态和目标状态

initial_state = [[2, 8, 3], [1, 0, 4], [7, 6, 5]]

goal_state = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]



# 定义移动方向:左、上、右、下

directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]

direction_names = ['Left', 'Up', 'Right', 'Down']



# 创建一个队列,用于BFS

queue = deque([(initial_state, "", 0)])  # (当前状态,移动序列,步数)



# BFS算法

while queue:

    current_state, move_sequence, steps = queue.popleft()



    # 检查是否达到目标状态

    if current_state == goal_state:

        print("找到解决方案!")

        print("移动序列:", move_sequence)

        print("步数:", steps)

        break



    # 扩展当前状态

    empty_row, empty_col = None, None

    for row in range(3):

        for col in range(3):

            if current_state[row][col] == 0:

                empty_row, empty_col = row, col



    for i in range(4):

        new_row, new_col = empty_row + directions[i][0], empty_col + directions[i][1]

        if 0 <= new_row < 3 and 0 <= new_col < 3:

            # 创建新状态

            new_state = [list(row) for row in current_state]

            new_state[empty_row][empty_col], new_state[new_row][new_col] = new_state[new_row][new_col], \

                                                                           new_state[empty_row][empty_col]

            new_move_sequence = move_sequence + direction_names[i]



            # 将新状态加入队列

            queue.append((new_state, new_move_sequence, steps + 1))

DFS:通过深度优先搜索从初始状态开始,沿着一个分支一直深入到底,直到找到解决方案或达到深度限制。然后,它会回溯到前一个状态,继续搜索其他分支,直到找到解决方案为止。

创建一个堆栈(deque),用于进行深度优先搜索。

堆栈中的元素是一个三元组 (当前状态, 移动序列, 步数),其中:

当前状态 表示当前的数码状态。

移动序列 用于记录达到当前状态的移动序列。

步数 表示从初始状态到当前状态的步数。

from collections import deque



# 定义初始状态和目标状态

initial_state = [[2, 8, 3], [1, 0, 4], [7, 6, 5]]

goal_state = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]



# 定义移动方向:左、上、右、下

directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]

direction_names = ['Left', 'Up', 'Right', 'Down']



# 创建一个堆栈,用于DFS

stack = deque([(initial_state, "", 0)])  # (当前状态,移动序列,步数)



# DFS算法

while stack:

    current_state, move_sequence, steps = stack.pop()



    # 检查是否达到目标状态

    if current_state == goal_state:

        print("找到解决方案!")

        print("移动序列:", move_sequence)

        print("步数:", steps)

        break



    # 扩展当前状态

    empty_row, empty_col = None, None

    for row in range(3):

        for col in range(3):

            if current_state[row][col] == 0:

                empty_row, empty_col = row, col



    if steps < 5# 深度限制为5

        for i in range(4):

            new_row, new_col = empty_row + directions[i][0], empty_col + directions[i][1]

            if 0 <= new_row < 3 and 0 <= new_col < 3:

                # 创建新状态

                new_state = [list(row) for row in current_state]

                new_state[empty_row][empty_col], new_state[new_row][new_col] = new_state[new_row][new_col], \

                                                                               new_state[empty_row][empty_col]

                new_move_sequence = move_sequence + direction_names[i]



                # 将新状态加入堆栈

                stack.append((new_state, new_move_sequence, steps + 1))

UCS:通过 UCS 算法以最小代价的方式从初始状态开始,逐步扩展状态直到找到目标状态为止。

创建一个优先队列(priority_queue),用于进行UCS搜索。

优先队列中的元素是元组 (total_cost, current_state, move_sequence, steps),按照 total_cost 的大小进行优先级排序。

使用 UCS 算法进行搜索:

不断从优先队列中弹出具有最小 total_cost 的节点。

import heapq



# 定义初始状态和目标状态

initial_state = [[2, 8, 3], [1, 0, 4], [7, 6, 5]]

goal_state = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]



# 定义移动方向:左、上、右、下

directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]

direction_names = ['Left', 'Up', 'Right', 'Down']



# 定义初始节点

initial_node = (0, initial_state, "", 0# (总代价,当前状态,移动序列,步数)



# 创建一个优先队列,用于UCS

priority_queue = [initial_node]



# UCS算法

while priority_queue:

    total_cost, current_state, move_sequence, steps = heapq.heappop(priority_queue)



    # 检查是否达到目标状态

    if current_state == goal_state:

        print("找到解决方案!")

        print("移动序列:", move_sequence)

        print("步数:", steps)

        break



    # 扩展当前状态

    empty_row, empty_col = None, None

    for row in range(3):

        for col in range(3):

            if current_state[row][col] == 0:

                empty_row, empty_col = row, col



    for i in range(4):

        new_row, new_col = empty_row + directions[i][0], empty_col + directions[i][1]

        if 0 <= new_row < 3 and 0 <= new_col < 3:

            # 创建新状态

            new_state = [list(row) for row in current_state]

            new_state[empty_row][empty_col], new_state[new_row][new_col] = new_state[new_row][new_col], \

                                                                           new_state[empty_row][empty_col]

            new_move_sequence = move_sequence + direction_names[i]

            new_cost = steps + 1



            # 计算总代价

            new_total_cost = new_cost



            # 将新状态加入优先队列

            heapq.heappush(priority_queue, (new_total_cost, new_state, new_move_sequence, new_cost))

Greedy:Greedy算法是一种启发式搜索算法,它在每一步都选择具有最小启发函数值的状态,因此它可能会陷入局部最优解,但通常运行速度很快。我使用不匹配数量作为启发函数,以贪婪的方式尝试接近目标状态。

定义启发函数(heuristic function):

heuristic(state) 计算每个状态与目标状态的不匹配的数量,用于评估状态的优劣。这里的启发函数采用了"不匹配数量",即当前状态中与目标状态不相同的方格的数量,作为估计的代价。

创建一个优先队列(priority_queue),用于进行Greedy算法搜索。使用Greedy算法进行搜索:

不断从优先队列中弹出具有最小 heuristic_value 的节点。

from collections import deque



# 定义初始状态和目标状态

initial_state = [[2, 8, 3], [1, 0, 4], [7, 6, 5]]

goal_state = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]



# 定义移动方向:左、上、右、下

directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]

direction_names = ['Left', 'Up', 'Right', 'Down']



# 定义启发函数:计算每个状态与目标状态的不匹配的数量

def heuristic(state):

    mismatch_count = 0

    for row in range(3):

        for col in range(3):

            if state[row][col] != goal_state[row][col]:

                mismatch_count += 1

    return mismatch_count



# 创建一个优先队列,用于Greedy 算法

priority_queue = deque([(initial_state, "", 0, 0)])  # (当前状态,移动序列,启发函数值,步数)



# Greedy 算法

while priority_queue:

    current_state, move_sequence, heuristic_value, steps = priority_queue.popleft()



    # 检查是否达到目标状态

    if current_state == goal_state:

        print("找到解决方案!")

        print("移动序列:", move_sequence)

        print("步数:", steps)

        break



    # 扩展当前状态

    empty_row, empty_col = None, None

    for row in range(3):

        for col in range(3):

            if current_state[row][col] == 0:

                empty_row, empty_col = row, col



    for i in range(4):

        new_row, new_col = empty_row + directions[i][0], empty_col + directions[i][1]

        if 0 <= new_row < 3 and 0 <= new_col < 3:

            # 创建新状态

            new_state = [list(row) for row in current_state]

            new_state[empty_row][empty_col], new_state[new_row][new_col] = new_state[new_row][new_col], \

                                                                           new_state[empty_row][empty_col]

            new_move_sequence = move_sequence + direction_names[i]

            new_heuristic_value = heuristic(new_state)

            new_steps = steps + 1



            # 将新状态加入优先队列,按照启发函数值排序

            priority_queue.append((new_state, new_move_sequence, new_heuristic_value, new_steps))

            priority_queue = deque(sorted(priority_queue, key=lambda x: x[2]))

A*算法:A*算法是一种启发式搜索算法,它综合考虑了每个状态的启发函数值和已经花费的代价(步数),以找到最优的路径。我利用不匹配数量作为启发函数,并按照总代价(启发函数值 + 步数)的大小进行搜索,以确保在估计代价和实际代价之间取得平衡,找到最优的解决方案。

使用A*算法进行搜索:

不断从优先队列中弹出具有最小 total_cost 的节点。

检查当前状态是否达到目标状态,如果是,输出解决方案并结束搜索。

如果当前状态不是目标状态,则扩展当前状态,生成新的可能状态,并将它们加入优先队列中继续搜索。

扩展状态的过程:

找到当前状态中的空格的位置 (empty_row, empty_col)

针对空格的四个移动方向,尝试生成新的状态,即将空格与相邻方格进行交换,生成一个新的数码状态。

计算新的 heuristic_value,这里使用启发函数计算。

计算新的 steps,即步数。

计算新的 total_cost,即启发函数值与步数之和。

将新状态加入优先队列,并按照 total_cost 的大小重新排序队列,以确保按照总代价的A*策略进行搜索。

from collections import deque



# 定义初始状态和目标状态

initial_state = [[2, 8, 3], [1, 0, 4], [7, 6, 5]]

goal_state = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]



# 定义移动方向:左、上、右、下

directions = [(0, -1), (-1, 0), (0, 1), (1, 0)]

direction_names = ['Left', 'Up', 'Right', 'Down']



# 创建一个优先队列,用于A*算法

priority_queue = deque([(initial_state, "", 0, 0)])  # (当前状态,移动序列,启发函数值,步数)



# 定义启发函数:计算每个状态与目标状态的不匹配的数量

def heuristic(state):

    mismatch_count = 0

    for row in range(3):

        for col in range(3):

            if state[row][col] != goal_state[row][col]:

                mismatch_count += 1

    return mismatch_count



# A*算法

while priority_queue:

    current_state, move_sequence, heuristic_value, steps = priority_queue.popleft()



    # 检查是否达到目标状态

    if current_state == goal_state:

        print("找到解决方案!")

        print("移动序列:", move_sequence)

        print("步数:", steps)

        break



    # 扩展当前状态

    empty_row, empty_col = None, None

    for row in range(3):

        for col in range(3):

            if current_state[row][col] == 0:

                empty_row, empty_col = row, col



    for i in range(4):

        new_row, new_col = empty_row + directions[i][0], empty_col + directions[i][1]

        if 0 <= new_row < 3 and 0 <= new_col < 3:

            # 创建新状态

            new_state = [list(row) for row in current_state]

            new_state[empty_row][empty_col], new_state[new_row][new_col] = new_state[new_row][new_col], \

                                                                           new_state[empty_row][empty_col]

            new_move_sequence = move_sequence + direction_names[i]

            new_heuristic_value = heuristic(new_state)

            new_steps = steps + 1



            # 计算总代价(启发函数值 + 步数)

            new_total_cost = new_heuristic_value + new_steps



            # 将新状态加入优先队列,按照总代价排序

            priority_queue.append((new_state, new_move_sequence, new_heuristic_value, new_steps))

            priority_queue = deque(sorted(priority_queue, key=lambda x: x[2] + x[3]))

alpha-beta-large.png

  1. 请分别用极小化极大算法和α-β剪枝算法计算博弈树

 极小化极大算法: minimax 函数是算法的核心,它采用了递归的方式来搜索博弈树,同时应用了极小化极大策略。这个函数的参数包括当前轮到哪个玩家(player)和当前博弈树节点(node)。

如果轮到玩家1(player == 1),则选择子节点中的最大值作为当前节点的值;如果轮到玩家0,则选择子节点中的最小值作为当前节点的值。这是博弈树中玩家1追求最大化结果,而玩家0追求最小化结果的基本原则。

递归结束后,将当前节点的值设置为计算出的最大值或最小值,并返回该值。   

# 极小化极大算法

def minimax(player, node):

    if not node["value"]:

        values = []

        for child in node["children"]:

            values.append(minimax(player ^ 1, child))



        if player == 1:

            node["value"] = max(values)

        else:

            node["value"] = min(values)



    return node["value"]



# 构建完全二叉树

tree1 = {

    "value": None,

    "children": [

        {

            "value": None,

            "children": [

                {

                    "value": None,

                    "children": [

                        {

                            "value": 10,

                            "children": [],

                        },

                        {

                            "value": 6,

                            "children": [],

                        },

                    ],

                },

                {

                    "value": None,

                    "children": [

                        {

                            "value": 100,

                            "children": [],

                        },

{

                            "value": 8,

                            "children": [],

                        },

                    ],

                },

            ],

        },

        {

            "value": None,

            "children": [

                {

                    "value": None,

                    "children": [

                        {

                            "value": 1,

                            "children": [],

                        },

                        {

                            "value": 2,

                            "children": [],

                        },

                    ],

                },

                {

                    "value": None,

                    "children": [

                        {

                            "value": 20,

                            "children": [],

                        },

                        {

                            "value": 4,

                            "children": [],

                        },

                    ],

                },

            ],

        },

    ],

}



def main(tree):

    res = minimax(1, tree)

    print("最佳值:", res)

    print(tree)



main(tree1)

α-β剪枝算法:在极小化极大算法中应用α-β剪枝,以加速博弈树的搜索过程。这种技术可以显著减少搜索的分支数,提高算法的效率,特别是在博弈树很大的情况下。

根据α-β剪枝的原则来更新 alpha 和 beta。如果在搜索过程中发现某个子节点的值已经超出了当前玩家的上界 beta(对于玩家0)或下界 alpha(对于玩家1),则可以剪枝,停止继续搜索该分支,因为已经找到更好的选择。

# 极小化极大算法 + α-β剪枝

def alpha_beta(player, node, alpha, beta):

    if not node["value"]:

        values = []



        for child in node["children"]:

            val = alpha_beta(player ^ 1, child, alpha, beta)

            values.append(val)



            if player == 1:

                # max层 子元素的值大于当前下界的值 更新下界

                alpha = max(alpha, val)

                # max层 下界大于等于上界直接返回下界(返回较大者)

                if alpha >= beta:

                    return alpha

            else:

                # min层 子元素的值小于当前上界的值 更新上界

                beta = min(beta, val)

                # min层 下界大于等于上界直接返回上界(返回较小者)

                if alpha >= beta:

                    return beta



        # 返回当前层节点的极值,便于父元素进行剪枝(并不是返回alpha或者beta)

        if player == 1:

            node["value"] = max(values)

        else:

            node["value"] = min(values)



    return node["value"]

(二叉树构建部分与上面相同)

8a91b34d4ed958911499ebd857bca16

  1. 课程设计作业:井字棋

在3*3格子上进行的连珠游戏,和五子棋比较类似,由于棋盘一般不画边框,格线排成井字故得名。游戏由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X)。由最先在任意一条直线上成功连接三个标记的一方获胜。

使用深度优先搜索结合极小化极大搜索结合α-β剪枝算法分别设计出井字棋游戏。

编程语言不限。

输入用鼠标或键盘操作:(三选一)

①可以用鼠标选择人类的着棋位置

②也可以用上下左右键选择位置按Enter键着子

③也可以通过输入坐标(0,1)来输入着棋位置

输出

①可以通过图形界面实时输出

②也可以通过在控制台打印3*3数组的形式输出没步任何电脑着棋后的状态例如:print(“XOO\nOXX\nOOX\n”)

设计思路:

输入操作:通过输入坐标(0,1)来输入着棋位置

输出:在控制台打印3*3数组的形式输出每步电脑着棋后的状态

check_win(board, player) 函数:检查是否有获胜者。它会检查每一行、每一列以及两个对角线上是否有连续的三个相同符号("X"或"O"),如果有,就返回True

check_tie(board) 函数:检查游戏是否平局。如果棋盘上没有空格(" "),则返回True

get_player_move(board) 函数:获取玩家的落子位置。通过输入行数和列数,然后检查该位置是否为空,如果为空,则返回选择的位置。

minimax(board, depth, alpha, beta, maximizing) 函数:在深度优先搜索的基础上实现极小化极大算法(Minimax)结合α-β剪枝。这是一个递归函数,用于模拟玩家和电脑的决策过程,以确定最佳落子位置。如果当前局面有玩家获胜("X"胜利)返回-10,如果电脑获胜("O"胜利)返回10,如果平局返回0

如果当前是最大化玩家(电脑)的回合(maximizing为True),则尝试所有可能的落子位置,对每个位置递归调用minimax来计算分数。同时,使用α-β剪枝来减少搜索空间,如果发现某个分支已经比β大,就可以剪枝不再搜索,因为这个分支对最终结果不会有影响。最终返回最高分数。

如果当前是最小化玩家(玩家)的回合(maximizing为False),同样尝试所有可能的落子位置,对每个位置递归调用minimax来计算分数。同时,使用α-β剪枝来减少搜索空间,如果发现某个分支已经比α小,就可以剪枝不再搜索,因为这个分支对最终结果不会有影响。最终返回最低分数。

play_game() 函数:这是游戏的主函数,包括玩家选择先后手、游戏主循环。在游戏主循环中,根据玩家选择的先后手,交替进行玩家和电脑的回合。玩家的回合通过输入来获取落子位置,电脑的回合通过minimax函数来计算最佳落子位置。

游戏开始后,玩家可以选择先手("X")或者电脑先手("O"),然后游戏会交替进行,直到有一方获胜或者游戏平局。

设计的关键在于minimax函数,它通过递归搜索棋盘状态树来找到最佳落子位置,同时通过α-β剪枝来减少搜索时间,从而提高了计算效率。我把minimax算法的搜索深度(depth)设置为9,表示电脑将考虑9步后的棋盘状态来做出决策。增加搜索深度会使电脑更聪明,但也会增加计算时间。根据我的测试,9步时的电脑我已经无法战胜,且运行时间较快,可以很好的满足要求。

源码:

import math





def print_board(board):

    # 打印游戏棋盘

    for row in board:

        print(" | ".join(row))

    print()





def check_win(board, player):

    # 检查是否有获胜者

    for i in range(3):

        if all(board[i][j] == player for j in range(3)):

            return True

        if all(board[j][i] == player for j in range(3)):

            return True

    if all(board[i][i] == player for i in range(3)):

        return True

    if all(board[i][2 - i] == player for i in range(3)):

        return True

    return False





def check_tie(board):

    # 检查是否平局

    for row in board:

        for cell in row:

            if cell == " ":

                return False

    return True





def get_player_move(board):

    # 获取玩家落子位置

    while True:

        try:

            row = int(input("输入行数 (1-3): ")) - 1

            col = int(input("输入列数 (1-3): ")) - 1

            if board[row][col] == " ":

                return row, col

            else:

                print("这个位置已经被占,请重新输入.")

        except ValueError:

            print("请输入1-3之间的数.")





def minimax(board, depth, alpha, beta, maximizing):

    # 极大极小/α-β剪枝算法

    if check_win(board, "X"):

        return -10, None

    if check_win(board, "O"):

        return 10, None

    if check_tie(board):

        return 0, None

    if maximizing:

        best_score = -math.inf

        best_move = None

        for row in range(3):

            for col in range(3):

                if board[row][col] == " ":

                    board[row][col] = "O"

                    score, _ = minimax(board, depth - 1, alpha, beta, False)

                    board[row][col] = " "

                    if score > best_score:

                        best_score = score

                        best_move = (row, col)

                    alpha = max(alpha, best_score)

                    if beta <= alpha:

                        break

        return best_score, best_move

    else:

        best_score = math.inf

        best_move = None

        for row in range(3):

            for col in range(3):

                if board[row][col] == " ":

                    board[row][col] = "X"

                    score, _ = minimax(board, depth - 1, alpha, beta, True)

                    board[row][col] = " "

                    if score < best_score:

                        best_score = score

                        best_move = (row, col)

                    beta = min(beta, best_score)

                    if beta <= alpha:

                        break

        return best_score, best_move





def play_game():

    board = [[" " for j in range(3)] for i in range(3)]

    print_board(board)



    # 玩家选择先后手

    while True:

        user_choice = input("选择X或者OX先手): ")

        if user_choice.lower() == "x":

            player = "X"

            break

        elif user_choice.lower() == "o":

            player = "O"

            break

        else:

            print("请输入XO.")



    # 游戏主循环

    while True:

        if player == "X":

            # 玩家先手

            while not check_win(board, "X") and not check_tie(board):

                row, col = get_player_move(board)

                board[row][col] = "X"

                print_board(board)

                if check_win(board, "X"):

                    print("玩家获胜!")

                    return

                if check_tie(board):

                    print("平局!")

                    return

                _, (row, col) = minimax(board, 9, -math.inf, math.inf, True)

                print("电脑思考后落子", (row + 1, col + 1))

                board[row][col] = "O"

                print_board(board)

                if check_win(board, "O"):

                    print("玩家失败!")

                    return

                if check_tie(board):

                    print("平局!")

                    return

        else:

            # 电脑先手

            while not check_win(board, "O") and not check_tie(board):

                _, (row, col) = minimax(board, 9, -math.inf, math.inf, True)

                print("电脑思考后落子", (row + 1, col + 1))

                board[row][col] = "X"

                print_board(board)

                if check_win(board, "X"):

                    print("玩家失败!")

                    return

                if check_tie(board):

                    print("平局!")

                    return

                row, col = get_player_move(board)

                board[row][col] = "O"

                print_board(board)

                if check_win(board, "O"):

                    print("玩家获胜!")

                    return

                if check_tie(board):

                    print("平局!")

                    return





if __name__ == '__main__':

    play_game()

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐果然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值