【Gomoku Actual Combat】Chapter 3 Algorithm Packaged into a Third-Party Interface

  In the previous chapter, we implemented the game tree negative maximum alpha-beta pruning algorithm, that is, ai()the function, and got four return values: x, y coordinates, search times, and whether we won.

  Now we need to wrap this ai()function in two more shells:

  1. The first layer is the preprocessed shell. For the parameters passed in by the interface, we need to preprocess ai()the data structure required by the function; we also need to check whether the input is correct, if the input chessboard is not a square, or the input chessboard value has other values ​​besides 1, 0, -1, etc. Wait, wait, we're going to limit it.

  2. The second layer is the Python Flask library, which opens our functions as interfaces. Including the cross-domain configuration of some requests and the processing of request request data are all done here.


Use Flask to open the interface

## Define interface input

  The principle of interface input is to have as few parameters as possible and be universal. For example, the input of the chessboard takes the following form:

[
	[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],
]

  Just convert the two-dimensional chessboard into a two-dimensional array directly, so that it is convenient for everyone to customize their own front-end pages.

  So in summary, our interface has four parameters:

  ratio: Attack coefficient of ai. : The depth of algorithm traversal. : The length of the side length of the chessboard. : The variable obtained from the form, a two-dimensional array, representing the state of the chessboard, represented by a comma-separated string. Split a string into a list of integers by using a function.
  depth
  length
  boardsplit

## Open interface, cross-domain configuration, data analysis

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()

/api/next_stepThe above code is an API interface based on the Flask framework , which   creates a route that accepts POST requests and processes form data including ratio, depth, length, and board parameters. In the request, it first gets the values ​​of these parameters from the form data and converts the board into a two-dimensional array. It then calls the next_step function to process the request and returns the result as the interface's response. If an exception occurs during processing, it returns a dictionary containing the error message. Finally, start the service by running the application.

  If cross-domain is not added, we need to add some configurations to the access interface on the front-end side, which is troublesome.

  For the two-dimensional array passed from the front end, it is actually converted into a string form, so after receiving it, we need to manually convert it into a two-dimensional array. Then it can be handed over to preprocessing for execution.


data preprocessing

## Data inspection and exception capture

  For the value passed from the interface, we care about the following issues:

  1. Is the side length of the chessboard too small
  ? 2. Whether the chessboard is not square.
  3. The depth of traversal should be controlled within 1, 2, 3, 4, otherwise it will be too big, and the process will be blocked at once. If it is deployed on the server 4. Will
  the chessboard value exceed 1, 0, or -1
  ? 5. Will the chessboard be full?

	# 统计白子数
    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"输入的棋盘已满, 无法下棋.")

  Count the number of white pieces:
  Use np.count_nonzero()the function to count the number of elements with a value of 1 in the chessboard, and assign the result to a variable white_count.

  Count the number of sunspots:
  Use np.count_nonzero()the function to count the number of elements with a value of -1 in the chessboard, and assign the result to a variable black_count.

  Count the number of holes:
  Use np.count_nonzero()the function to count the number of elements with a value of 0 in the chessboard, and assign the result to a variable empty_count.

  Input check:
  - Check whether the side length of the chessboard is less than 12, and if so, throw ValueErroran exception, prompting that the minimum side length of the chessboard is 12.
  - Check if the input board is a square, if not, throw ValueErroran exception, indicating that the input board is not a square.
  - Check whether the traversal depth is 1, 2, 3 or 4, if not, throw ValueErroran exception, prompting that the entered traversal depth is wrong and should be 1, 2, 3 or 4.
  - Use an assertion statement to check whether the total number of elements in the chessboard is equal to the size of the chessboard. If not, an AssertionErrorexception will be thrown, prompting that the entered data of the chessboard is incorrect, which can only be 0, 1, -1, where 1 represents white chess, - 1 represents black chess, 0 represents empty chess.
  - Check whether the number of holes in the chessboard is 0, and if so, throw ValueErroran exception, prompting that the input chessboard is full and chess cannot be played.

## Preprocess data

	# 当前玩家
    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()

  Determine the current player based on the current number of black and white pieces. And calculate the backtracking algorithm execution time.

## Define interface output

  The defined output is as follows:

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:参数介绍】"
        }
    }

  The above code returns a dictionary of results, containing the following key-value pairs:

  - 'code':表示返回的状态码,这里设置为 200 表示成功。
  - 'msg':表示返回的消息,这里设置为 ‘成功’。
  - 'data':表示返回的数据,是一个包含多个键值对的字典。
   - 'x':表示横坐标。
   - 'y':表示纵坐标。
   - 'time':表示搜索时间,是结束时间减去开始时间的差值。
   - 'step':表示当前步数。
   - 'player':表示当前下棋的玩家,可以是 ‘black’ 或 ‘white’。
   - 'length':表示棋盘边长,即格子的个数加1。
   - 'search_count':表示搜索次数。
   - 'flag':表示是否赢了。
   - 'info':表示参数介绍的字符串,包含一些说明信息。

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


开启接口

  此时去运行编写的接口的py文件:

在这里插入图片描述
  如上图,表示开启成功,然后去写post请求调用就可以了。


继续学习下一篇实战!

  【五子棋实战】第4章 部署五子棋计算接口到Window、Linux上

Guess you like

Origin blog.csdn.net/qq_43592352/article/details/131342658