【问题标题】:Deciding winner in an optimally played 2-player game在最佳玩的 2 人游戏中决定获胜者
【发布时间】:2017-11-06 11:09:26
【问题描述】:

我遇到了this question。根据问题:

‘samu’和‘vibhu’正在玩一个游戏,桌子上有从 1 到 N 的 N 个整数。在每一轮中,玩家可以从之前未访问的整数中选择一个整数来标记为已访问。如果在一个回合中,玩家选择一个完成三个连续数字的选择的数字,他就赢了。即,假设在游戏的某个阶段,如果玩家现在选择 3,则已经选择(访问)了 2 和 4,则他获胜。假设 samu 首先开始,并且两个玩家都发挥得非常好,那么谁是赢家。

我尝试应用 WL 算法(正确理解后)described here 即:

boolean isWinning(position pos) {
    moves[] = possible positions to which I can move from the position pos;
    for (all x in moves) 
        if (!isWinning(x)) return true;
    return false; 
}

所以,我的代码是(在适当修改 WL 算法之后):

public class HelloWorld{

    public static boolean[] visited;
    public static int n;
    public static void main(String []args){

        n=12;
        visited=new boolean[n];
        java.util.Arrays.fill(visited,false);
        for(int i=0; i<n; i++){
            visited[i]=true;
            if(isWinning(i)){
                System.out.println("first one wins");
                System.exit(0);
            }
            visited[i]=false;
        }
        System.out.println("second one wins");
    }

    public static boolean isWinning(int x){
        if(threeStrikes()){
            return true;
        }
        for(int i=0; i<n; i++){
            if(!visited[i]){
                visited[i]=true;
                if(!isWinning(i)){
                    return true;
                }
                visited[i]=false;
            }
        }
        return false;
    }
    public static boolean threeStrikes(){
        for(int i=0; i<n-2; i++){
            if(visited[i]&&visited[i+1]&&visited[i+2]){
                return true;
            }
        }
        return false;
    }
}

问题在于它会在 n=6 时打印“第一个获胜”。在this discussion 线程中,操作员说对于 n=6,第二个应该获胜。我不知道他是否错了,或者我的代码是否遗漏了什么。任何帮助表示赞赏。

【问题讨论】:

    标签: algorithm recursion game-theory minmax


    【解决方案1】:

    首先,这是您的代码的修改版本:

    public class HelloWorld {
    
        public static boolean[] visited;
        public static int n;
        public static void main(String []args){
    
            n=12;
            visited=new boolean[n];
            java.util.Arrays.fill(visited,false);
            for(int i=0; i<n; i++){
                visited[i]=true;
                if(!isOpponentWinning()){
                    System.out.println("first one wins");
                    System.exit(0);
                }
                visited[i]=false;
            }
            System.out.println("second one wins");
        }
    
        public static boolean isOpponentWinning(){
            for(int i=0; i<n; i++){
                if(!visited[i]){
                    visited[i]=true;
                    if(threeStrikes() || !isOpponentWinning()){
                        visited[i]=false;
                        return true;
                    }
                    visited[i]=false;
                }
            }
            return false;
        }
        public static boolean threeStrikes(){
            for(int i=0; i<n-2; i++){
                if(visited[i]&&visited[i+1]&&visited[i+2]){
                    return true;
                }
            }
            return false;
        }
    }
    

    修改如下:

    1. isWinning() 实际上是在检查当前玩家的对手是否获胜,所以为了清楚起见,我将其更改为 isOpponentWinning()
    2. 当对手有 threeStrikes() 时返回 true 是错误的,因为它被调用者(谁是获胜玩家)否定了。因此,当最后一名玩家达到三击时,停止标准现在为真,因此 here 返回 true 是正确的。
    3. 由于我们正在检查对手是否获胜(而不是当前玩家),因此在第一次调用 isOpponentWinning() 时也应添加否定(在主函数中)。李>
    4. 为了正确回溯,我在isOpponentWinning() 中返回true 之前添加了visited[i]=false

    关于你关于 n=6 的问题,确实第二个应该赢。 假设玩家A先玩,B玩第二。

    • 如果A选择1,B可以选择4,然后无论A选择下一个B都可以获胜下一回合。
    • 如果A选择2,B可以选择5,然后无论A选择下一个B都可以获胜下一回合。
    • 如果A选择3,B可以选择6,然后无论A选择下一个B都可以获胜下一回合。

    其余选项是对称的。 我们知道无论A选择什么作为它的第一步,B都可以保证胜利。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多