【五子棋实战】第3章 算法包装成第三方接口

简介: 【五子棋实战】第3章 算法包装成第三方接口

我们在上一章实现了博弈树负值极大alpha-beta剪枝算法,即ai()函数,拿到了四个返回值:x、y坐标,搜索次数、是否赢了。


 现在我们需要把这个ai()函数再套两层壳:


 1、第一层是预处理的壳。对于接口传入的参数,我们需要预处理成为ai()函数需要的数据结构;还需要检查输入对不对,如果输入的棋盘不是正方形的,或者输入的棋盘值除了1、0、-1还有其他值等等等等,我们要加以限制。


 2、第二层是套python的Flask库,把我们的函数开放为接口。包括一些请求的跨域配置、request请求数据的处理都在这完成。



使用Flask开放接口


## 定义接口输入


  接口输入的原则是,参数尽量少,要能够有通用性,比如对棋盘的输入,采取如下的形式:


[
  [0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0],
  [0,0,0,1,-1,0,0,0,0],
  [0,0,0,0,-1,0,0,0,0],
  [0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0],
]


 直接把二维棋盘转化为二维数组就行,这样方便大家自定义自己的前端页面。


 所以综上原则,我们的接口有四个参数:


 ratio:ai的攻击系数。

 depth:算法遍历的深度。

 length:棋盘边长长度。

 board:从表单中获取的变量,二维数组,表示棋盘状态,通过逗号分隔的字符串形式表示。通过使用split函数将字符串拆分为整数列表。


## 开放接口、跨域配置、数据解析


app = Flask(__name__)
CORS(app, supports_credentials=True)
@app.route('/api/next_step', methods=['POST'])
@cross_origin(supports_credentials=True)
def api():
    try:
        ratio = int(request.form.get('ratio'))
        depth = int(request.form.get('depth'))
        length = int(request.form.get('length'))
        board = [int(_) for _ in request.form.get('board').split(',')]
        board = np.array(board).reshape(-1, length)
        return next_step(board, length, depth, ratio )  # 返回接口响应
    except Exception as e:
        return {
            'code': 300,
            'msg': str(e)
        }
if __name__ == '__main__':
    app.run()


 上面的代码是一个基于Flask框架的API接口,创建了路由 /api/next_step,该接口接受POST请求,并处理包含 ratio、depth、length 和 board 参数的表单数据。在请求中,它首先从表单数据中获取这些参数的值,并将 board 转换为二维数组。然后,它调用 next_step 函数来处理请求,并将返回的结果作为接口的响应返回。如果在处理过程中发生异常,它会返回一个包含错误信息的字典。最后,通过运行应用程序来启动服务。


 如果不加跨域的话,我们在前端侧访问接口要加一些配置,比较麻烦。


 对于前端侧传过来的二维数组,它其实是转化成了字符串形式的,所以接收之后,我们要手动转化成二维数组。然后就可以去交给预处理去执行了。



数据预处理


## 数据检查与异常捕获


 对于接口传过来的值,我们关心这样几个问题:


 1、棋盘边长会不会太小了


 2、棋盘是否不是正方形的


 3、遍历的深度要控制在1,2,3,4以内,不然太大了,进程一下就阻塞了,要是部署在服务器上,可能一下服务器就瘫痪了


 4、棋盘值会不会有超出1、0、-1以外的值


 5、棋盘会不会满了


  # 统计白子数
    white_count = np.count_nonzero(board == 1)
    # 统计黑子数
    black_count = np.count_nonzero(board == -1)
    # 统计空子数
    empty_count = np.count_nonzero(board == 0)
    """输入检查"""
    # TODO 修改最低大小
    if length < 12:
        raise ValueError(f"棋盘边长最低为12.")
    if board.shape[1] != length:
        raise ValueError(f"输入棋盘不是正方形.")
    if depth not in [1,2,3,4]:
        raise ValueError(f"输入的遍历深度有误, 应该为1,2,3或4.")
    assert (white_count + black_count + empty_count) == board.size,\
        "输入的棋盘数据有误.只能为0,1,-1.其中1代表白棋,-1代表黑棋,0代表空棋."
    if empty_count == 0:
        raise ValueError(f"输入的棋盘已满, 无法下棋.")


 统计白子数:


 使用 np.count_nonzero() 函数统计棋盘中值为1的元素个数,并将结果赋值给变量 white_count。


 统计黑子数:


 使用 np.count_nonzero() 函数统计棋盘中值为-1的元素个数,并将结果赋值给变量 black_count。


 统计空子数:


 使用 np.count_nonzero() 函数统计棋盘中值为0的元素个数,并将结果赋值给变量 empty_count。


 输入检查:

 - 检查棋盘边长是否小于12,如果是,则抛出 ValueError 异常,提示棋盘边长最低为12。


 - 检查输入的棋盘是否为正方形,如果不是,则抛出 ValueError 异常,提示输入棋盘不是正方形。


 - 检查遍历深度是否为1、2、3或4,如果不是,则抛出 ValueError 异常,提示输入的遍历深度有误,应为1、2、3或4。


 - 使用断言语句检查棋盘中的元素总数是否与棋盘大小相等,如果不相等,则抛出 AssertionError 异常,提示输入的棋盘数据有误,只能为0、1、-1,其中1代表白棋,-1代表黑棋,0代表空棋。


 - 检查棋盘中空子的个数是否为0,如果是,则抛出 ValueError 异常,提示输入的棋盘已满,无法下棋。


## 预处理数据


  # 当前玩家
    player = 'black' if black_count == white_count else 'white'
    # 当前步数
    step = black_count + white_count + 1
    # 开始计时
    start_time = time.time()
    # 电脑计算
    x, y, search_count, flag = ai(player, ratio, length, board, depth)
    # 结束计时
    end_time = time.time()


  根据当前的黑子和白子个数,确定当前的玩家。并计算回溯算法执行时间。


## 定义接口输出


  定义的输出如下:


return {
        'code': 200,
        'msg': '成功',
        'data': {
            'x': x,
            'y': y,
            'time': end_time - start_time,
            'step': step,
            'player': player,
            'length': length,
            'search_count': search_count,
            'flag': flag,
            'info': "【默认黑子先行】"
                    "【黑子存-1,白子存1,空子存0】"
                    "【x:横坐标,从0开始,length结束】"
                    "【y:纵坐标,从0开始,length结束】"
                    "【time:搜索时间】"
                    "【step:这是第几步棋】"
                    "【player:当前下棋的玩家'black'/'white'】"
                    "【length:棋盘边长,线的个数,即格子的个数+1】"
                    "【search_count:搜索次数】"
                    "【flag:是否赢了】"
                    "【info:参数介绍】"
        }
    }


 上述代码是一个返回结果的字典,包含以下键值对:


 - 'code':表示返回的状态码,这里设置为 200 表示成功。


 - 'msg':表示返回的消息,这里设置为 ‘成功’。


 - 'data':表示返回的数据,是一个包含多个键值对的字典。


  - 'x':表示横坐标。


  - 'y':表示纵坐标。


  - 'time':表示搜索时间,是结束时间减去开始时间的差值。


  - 'step':表示当前步数。


  - 'player':表示当前下棋的玩家,可以是 ‘black’ 或 ‘white’。


  - 'length':表示棋盘边长,即格子的个数加1。


  - 'search_count':表示搜索次数。


  - 'flag':表示是否赢了。


  - 'info':表示参数介绍的字符串,包含一些说明信息。


 这段代码用于构建一个包含返回结果的字典,并将其作为函数的返回值。返回结果中包含了搜索结果的相关信息。



相关文章
|
4月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
28天前
|
机器学习/深度学习 算法 文件存储
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
神经架构搜索(NAS)正被广泛应用于大模型及语言/视觉模型设计,如LangVision-LoRA-NAS、Jet-Nemotron等。本文回顾NAS核心技术,解析其自动化设计原理,探讨强化学习、进化算法与梯度方法的应用与差异,揭示NAS在大模型时代的潜力与挑战。
252 6
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
|
10天前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
52 7
|
10天前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
36 0
粒子群算法模型深度解析与实战应用
|
7月前
|
人工智能 编解码 算法
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
本文介绍了通义灵码2.0 AI程序员在嵌入式开发中的实战应用。通过安装VS Code插件并登录阿里云账号,用户可切换至DeepSeek V3模型,利用其强大的代码生成能力。实战案例中,AI程序员根据自然语言描述快速生成了C语言的base64编解码算法,包括源代码、头文件、测试代码和CMake编译脚本。即使在编译错误和需求迭代的情况下,AI程序员也能迅速分析问题并修复代码,最终成功实现功能。作者认为,通义灵码2.0显著提升了开发效率,打破了编程语言限制,是AI编程从辅助工具向工程级协同开发转变的重要标志,值得开发者广泛使用。
8510 71
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
|
11月前
|
存储 缓存 算法
前端算法:优化与实战技巧的深度探索
【10月更文挑战第21天】前端算法:优化与实战技巧的深度探索
160 1
|
大数据 UED 开发者
实战演练:利用Python的Trie树优化搜索算法,性能飙升不是梦!
在数据密集型应用中,高效搜索算法至关重要。Trie树(前缀树/字典树)通过优化字符串处理和搜索效率成为理想选择。本文通过Python实战演示Trie树构建与应用,显著提升搜索性能。Trie树利用公共前缀减少查询时间,支持快速插入、删除和搜索。以下为简单示例代码,展示如何构建及使用Trie树进行搜索与前缀匹配,适用于自动补全、拼写检查等场景,助力提升应用性能与用户体验。
229 2
|
4天前
|
传感器 机器学习/深度学习 算法
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)
|
5天前
|
传感器 算法 数据挖掘
基于协方差交叉(CI)的多传感器融合算法matlab仿真,对比单传感器和SCC融合
基于协方差交叉(CI)的多传感器融合算法,通过MATLAB仿真对比单传感器、SCC与CI融合在位置/速度估计误差(RMSE)及等概率椭圆上的性能。采用MATLAB2022A实现,结果表明CI融合在未知相关性下仍具鲁棒性,有效降低估计误差。
|
7天前
|
负载均衡 算法 调度
基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)
基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)
75 11

热门文章

最新文章