在最佳玩的 2 人游戏中决定获胜者

Deciding winner in an optimally played 2-player game

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

‘samu’ and ‘vibhu’ are playing a game where there are N integers from 1 to N lying on the table. In each turn, the player gets to pick one integer to mark as visited from among the previously unvisited ones. If in a turn, the player picks a number which completes the picking of three consecutive numbers, he wins. i.e., say at some stage in the game 2 and 4 are already picked(visited) if the player now picks 3, he wins. Assuming samu starts first and both the players play perfectly optimally, who is the winner.

我尝试应用 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算法后):[​​=16=]

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 打印 "first one wins"。在 this discussion 线程中,op 表示对于 n=6,第二个应该获胜。我不知道他是不是错了,或者我的代码是否遗漏了什么。感谢任何帮助。

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

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 是错误的,因为它被调用者(获胜玩家)否定了).因此,当最后一名球员达到三分球时,停止标准现在为真,因此返回真这里是正确的。
  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都可以保证获胜。