【问题标题】:Skip unwanted returns in a recursion在递归中跳过不需要的返回
【发布时间】:2016-08-28 13:18:10
【问题描述】:

我对以下挑战有疑问:

两个玩家(编号为 1 和 2)正在玩 n 块石头的游戏。玩家 1 总是先玩,两个玩家轮流移动。游戏规则如下:

玩家一次可以从棋盘上移走 2,3 或 5 块石头。 如果玩家无法移动,则该玩家输掉游戏。 给定石头的数量,找到并在新行上打印获胜者的姓名(即第一或第二)。每个玩家都以最佳方式进行游戏,这意味着如果存在更好的获胜动作,他们将不会做出导致他们输掉比赛的动作。

(输出格式

如果第一个玩家是获胜者,则在每个测试用例的新行上打印“First”;否则,打印“第二”。)

例子:

数量 = 7,玩家 = 1。

调用 getWinner(7-5,-1)

数量 = 2,玩家 = -1

调用 getWinner(2-2,1)

数量= 0,玩家= 1

该函数不应在此处返回任何内容,因为它会中止搜索,但编译器强制我添加一个返回语句。

 public static String getWinner(int amount, int player){
    if (amount == 0 || amount == 1){
         if (player == -1) {
            return "First";                 
        }
    } else if (amount-5 >=0){
        return getWinner(amount-5,-player);
    } else if (amount-3 >=0) {
        return getWinner (amount-3,-player);
    } else if(amount-2 >= 0){
        return getWinner (amount -2 , -player);
    } else {
        return "Second";
    }
    return "failure";
}

【问题讨论】:

    标签: java recursion


    【解决方案1】:

    代码没有意义,因为您实际上从来没有选择任何东西,而是先做任何事情。同样,对于游戏的每一步,有些选择会让你松懈,有些选择会让你赢,所以你需要知道自己想要什么。

    你需要根据对手的输球来遵循 2、3 或 5。

    private static boolean wins(int amount){
        if (amount < 0 ) {
            return true;  // game already over, previous player lost
        } else if ( amount <= 1){
            return false; // you loose always
        } else {
            // we win if the opponent doesn't
            return  wins(amount-5) == false ||
                    wins(amount-3) == false ||
                    wins(amount-2) == false;
        }
    }
    

    如您所见,默认情况下执行或在递归之间。它在第一次递归变为假时停止,结果为真,否则为假。

    【讨论】:

      【解决方案2】:

      您的问题是,当第一个条件(amount == 0 || amount == 1)为真时,您并不总是返回(仅在player==-1 时返回),因此就编译器而言,并非@ 的所有分支987654323@-else if-...-else 语句返回一个值,这就是为什么你不得不添加一个返回语句作为方法的最后一个语句。

      你可以重写如下逻辑来消除return "failure"

       public static String getWinner(int amount, int player){
           if (amount == 0 || amount == 1){
               if (player == -1) {
                   return "First";                 
               } else {
                   return "Second";
               }
           } else if (amount-5 >=0){
               return getWinner(amount-5,-player);
           } else if (amount-3 >=0) {
               return getWinner (amount-3,-player);
           } else { // you no longer need the else if(amount-2 >= 0) condition
                    // since it must be satisfied at this point
               return getWinner (amount -2 , -player);
           }
       }
      

      另一种选择:

      public static String getWinner(int amount, int player){
          if ((amount == 0 || amount == 1) && player == -1) {
              return "First";
          } else if (amount-5 >=0) {
              return getWinner(amount-5,-player);
          } else if (amount-3 >=0) {
              return getWinner (amount-3,-player);
          } else if(amount-2 >= 0) {
              return getWinner (amount -2 , -player);
          } else {
              return "Second";
          }
      }
      

      【讨论】:

      • 如果我们在给定的示例中,这将返回“Second”,但在其他递归分支(amount-3 ; amount-2)中可能存在针对 Player1 的解决方案。通过返回“Second”,将不再搜索其他分支。
      • @ConradAshton 我不确定逻辑是什么。我假设一旦您到达10,获胜者将由player 的值决定。
      • @ConradAshton 您还可以将第一个条件更改为if ((amount == 0 || amount == 1)) &amp;&amp; player == -1),并保持其余逻辑(return "failure"; 除外)不变。
      • 感谢您的回答。我已更新问题描述以获取更多详细信息。
      猜你喜欢
      • 2016-02-13
      • 1970-01-01
      • 2019-01-22
      • 2018-09-18
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      • 2013-01-29
      相关资源
      最近更新 更多