ruby:挣扎着递归

时间:2012-02-29 17:26:27

标签: ruby methods recursion

我应该在ruby中创建一个方法,它将采用结构化的多维数组,例如:

my_arr = [
[ [['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] ],
[ [['Allen', 'S'], ['Omer', 'P']], [['David E.', 'R'], ['Richard X.', 'P']] ]
]

这个数组应该代表Rock,paper& amp;剪刀,玩家的数量总是2 ^ n,并且不会重复(玩家)。

我写的代码如下:

class WrongNumberOfPlayersError < StandardError ; end
class NoSuchStrategyError < StandardError ; end

def rps_game_winner(game)
  raise WrongNumberOfPlayersError unless game.length == 2
  valid = ["r","p","s"]
  a1=[(game[0][1]).downcase]
  a2=[(game[1][1]).downcase]
  raise NoSuchStrategyError unless (valid & a1) && (valid & a2)

  return (game[0]) if a1 === a2
  case (a1[0])
  when "r"
    case (a2[0])
    when "p"
      return (game[1])
    else 
      return (game[0])
    end
  when "p"
    case (a2[0])
    when "s"
      return (game[1])
    else
      return (game[0])
    end
  when "s"
    case (a2[0])
    when "r"
      return (game[1])
    else 
      return (game[0])
    end
  end
end

def rps_tournament_winner(tournament)
  if tournament[0][0].is_a?(Array)
    rps_tournament_winner(tournament[0])
  elsif tournament[1][0].is_a?(Array)
    rps_tournament_winner(tournament[1])
  else
    rps_game_winner(tournament)
  end
end

所以我的问题是,如果使用前面提到的数组我被传递给rps_tournament_winner Dave总是获胜而不是Richard而我无法计算我出错的地方。

Ty用于阅读文本/代码的墙:)

3 个答案:

答案 0 :(得分:3)

我注意到的一件事是你使用'有效'并没有做任何事情来检查你的输入是否真的有效。如果你试图检查a1和a2是“r”“p”还是“s”,你应该使用正则表达式:

valid = /[rps]/    # matches either "r" "p" or "s"
raise NoSuchStrategyError unless (a1 =~ valid) && (a2 =~ valid)

你的玩家阵列嵌套得非常深。你可以通过简化来简化你的生活:

my_arr = [['Armando', 'P'], ['Dave', 'S'], ['Richard', 'R'], ['Michael', 'S'],
        ['Allen', 'S'], ['Omer', 'P'], ['David E.', 'R'], ['Richard X.', 'P']]

通过将程序分解为多个部分,您可以更轻松地阅读和维护。例如,创建一个确定胜利的方法:

# This is incomplete as it doesn't deal with ties. I'll let you do that part
def win(first, second)
  if (first == "p" && second == "r") || (first == "r" && second == "s") || (first == "s" && second == "p")
    return true
  else
    return false
  end
end

现在使用上述方法编写和理解游戏本身更容易:

def rps_game_winner(player1, player2)
  first = player1[1].downcase
  second = player2[1].downcase
  win(first, second) ? player1 : player2  # ternary operator returns the winner
end

你现在有一个方法可以将所有这些放入其中(主要逻辑的类型),我们将在这里使用递归:

def rps_tournament_winner(player_list)
  round_winners = []    # place to hold the winners for each round

  if player_list.size == 1  # final condition to stop the recursion
    puts "The winner is #{player_list[0][0]}."
  else
    player_list.each_slice(2) do |l1, l2|  # take pairs from your list to play each other
      round_winners << rps_game_winner(l1, l2)
    end

    rps_tournament_winner(round_winners)  # use recursion to play the winners against each other
  end
end

# put it into play
puts test_array(my_arr)

就是这样。获胜者是理查德,而且总是理查德,因为这部戏是确定性的。

虽然这会运行,但你应该知道我遗漏了一些重要的事情,比如处理关系和奇数玩家。在这些条件下,该计划将无法正常运作。但我会由你来解决这些问题。

编辑:修改原始数组:

new_array = []
my_arr.flatten.each_slice(2) do |name, pick|
  new_array << [name, pick]
end

答案 1 :(得分:1)

你的递归只会在锦标赛[0]结束前结束,而不会结束锦标赛[1]。 你需要同时参加锦标赛[0]和锦标赛[1]然后互相比赛。

喜欢的东西。 (我留给你写红宝石代码)

rps_game_winner([rps_tournament_winner(锦标赛[0],rps_tournament_winner(锦标赛[1]])

答案 2 :(得分:0)

调试代码非常困难。

但我认为它存在根本缺陷。

当你致电rps_tournament_winner时,你会传入

[
  [ [['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] ],
  [ [['Allen', 'S'], ['Omer', 'P']], [['David E.', 'R'], ['Richard X.', 'P']] ]
]

它询问tournament[0][0].is_a?(Array)

[['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']]

是的。

它会调用rps_tournament_winner(tournament[0])

tournament = [ [['Armando', 'P'], ['Dave', 'S']], [['Richard', 'R'], ['Michael', 'S']] ]

它询问tournament[0][0].is_a?(Array)

['Armando', 'P']

是的。

它调用rps_tournament_winner(tournament[0])

tournament = [['Armando', 'P'], ['Dave', 'S']]

它询问tournament[0][0].is_a?(Array)

'Armando'

不,不是。

它会调用rps_game_winner(tournament)

在比赛中戴夫打败了阿曼多!

我认为这不是您想要的功能。

我建议你重写一下,试着保持简单。