Java 有时间限制的递归转义

Java 有时间限制的递归转义,java,recursion,Java,Recursion,我正在写一个程序来玩跳棋,每个动作都是定时的。我正在使用alpha-beta修剪来寻找最佳移动。我只能深入决策树,因为: 决策树对于跳棋者来说是巨大的 有一个时间限制,我必须决定搬家 当我的时间用完时,有没有一种方法可以立即从调用堆栈中退出,即使堆栈上有很多帧?我想抛出一个例外,但这似乎是一个糟糕的决定 这就是我现在正在做的,但还不够快 public Board play(Board board) { ArrayList<Board> actions = board.find

我正在写一个程序来玩跳棋,每个动作都是定时的。我正在使用alpha-beta修剪来寻找最佳移动。我只能深入决策树,因为:

  • 决策树对于跳棋者来说是巨大的
  • 有一个时间限制,我必须决定搬家
  • 当我的时间用完时,有没有一种方法可以立即从调用堆栈中退出,即使堆栈上有很多帧?我想抛出一个例外,但这似乎是一个糟糕的决定

    这就是我现在正在做的,但还不够快

    public Board play(Board board) {
        ArrayList<Board> actions = board.findPossibleMoves();
    
        if (actions.size() == 0) {
            return new Board();
        } 
    
        int depth = 3;
        // Each move has 1 second (1000ms)
        TimeLimit tl = new TimeLimit(1000);
        double alpha = Double.NEGATIVE_INFINITY;
        double beta = Double.POSITIVE_INFINITY;
    
        Board bestSoFar = actions.get(0);
    
        double v = Double.NEGATIVE_INFINITY;
        for (Board b : actions) {
            if (tl.isTimeUp())
              return bestSoFar;
    
            double result = minValue(b, depth, alpha, beta, tl);
            if (result >= v) {
                bestSoFar = b;
                v = result;
            }
            if (v >= beta) return b;
            alpha = Math.max(alpha, v);
        }
        return bestSoFar;
    }
    
    private double maxValue(Board board, int depth, double alpha, double beta, TimeLimit tl) {
        if (tl.isTimeUp())
            return score(board);
        ...
    }
    
    private double minValue(Board board, int depth, double alpha, double beta, TimeLimit tl) {
        if (tl.isTimeUp())
            return score(board);
        ...
    }
    
    公共棋盘游戏(棋盘游戏){
    ArrayList actions=board.findPossibleMoves();
    如果(actions.size()==0){
    返回新板();
    } 
    int深度=3;
    //每次移动有1秒(1000毫秒)
    时间限制tl=新的时间限制(1000);
    double alpha=double.NEGATIVE_无穷大;
    双β=双正_∞;
    Board bestSoFar=操作。获取(0);
    双v=双负无穷大;
    针对(董事会b:行动){
    if(tl.isTimeUp())
    回归最佳状态;
    双结果=最小值(b,深度,α,β,tl);
    如果(结果>=v){
    bestSoFar=b;
    v=结果;
    }
    如果(v>=beta)返回b;
    alpha=数学最大值(alpha,v);
    }
    回归最佳状态;
    }
    专用双maxValue(单板、整数深度、双alpha、双beta、TimeLimit tl){
    if(tl.isTimeUp())
    返回分数(板);
    ...
    }
    私有双最小值(Board、int深度、双alpha、双beta、TimeLimit tl){
    if(tl.isTimeUp())
    返回分数(板);
    ...
    }
    
    考虑到递归将在严格计时的环境中使用,有几个选项可以考虑。这些措施如下:

    选项1:

    在整个方法体中添加更多的if语句,尤其是在可以阻塞的代码段之前,以确保代码执行在时间到期后立即停止。必须实现一个特定的缓冲时间间隔,以便返回语句有时间传播回堆栈

    优点:

    • 易于实现
    • 相对简单有效
    缺点:

    • 降低代码的可读性
    • 不保证在规定的时间内执行

    选项2:

    将执行代码移植到辅助线程,该线程在对象执行时逐步写入对象。然后,主线程可以在触发该线程的同时启动计时器。当计时器过期时,主线程只需检索此对象并通知工作线程终止

    优点:

    • 非常准确(由于同步,结果几乎在点上检索,延迟)
    • 不需要缓冲时间间隔-递归函数可以在不受限制的情况下,通过尝试在计时器中拟合返回传播,达到它想要的深度
    • 允许优雅地关闭执行代码,因为它不再受时间限制(执行结果被获取,线程可以按自己的速度消亡)
    缺点:

    • 多线程-由于此解决方案是多线程的,因此它可能不适用于所有场景
    • 需要大量额外的代码,并且可能需要对某些现有代码进行更改才能实现

    您试图限制什么循环?构造函数中的for循环?我假设最密集/最耗时的部分在maxValue/minValue段中?我看到您限制了maxValue()和minValue()方法的执行时间,但没有限制for循环的执行时间。这就是你打算做的吗?换句话说,您是要仅限制maxValue()/minValue()的执行时间,还是要限制整个Play()方法的执行时间?@CPUTerminator我需要限制整个Play()方法的执行时间。从调用play()开始,我还有1秒。@MystikSpiral我需要限制整个play()方法的执行时间。从调用play()开始,我有1秒的时间。嗯。。。什么代码执行时间最长?minValue()/maxValue()是否完全阻塞?您需要在for循环中添加if(tl.isTimeUp()){//code here…}else{return bestSoFar;}。我倾向于同意这是一个很好的答案,除非我会让辅助线程在其他玩家移动期间继续扩展树。当然,除非这违反了形势的规则。现在大多数系统都是多核的,所以它不应该影响其他代码或用户界面的性能。当然,这很难实现,但应该尽可能多地进行处理。这可能有助于将算法转换为迭代方法,我发现这通常更快。您还可以找到其他与android代码相关的java性能提示。@user1855149在本例中,整个时间限制是阻止树扩展。此外,一旦移动完成,则由人类玩家进行另一个移动,这将使之前所做的所有计算无效。OP告诉我,无论出于何种原因,他/她都不能接受多线程解决方案,这就是为什么我将“可能不适用于所有场景”。