2012-02-29 64 views
2

我应该创建在红宝石的方法,其将在结构化的,多维的阵列,诸如挣扎:红宝石:递归

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

此数组应该代表岩石的比赛,纸&剪刀,玩家的数量将永远是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_winnerDave的总是赢,而不是Richard,我一直没能找出我出错的地方。

泰阅读的文本/代码:)

+1

我建议你使用':本文:摇滚,: scissor'而不是字符串,它更容易阅读代码,并且对于解释器来说更快。 – farnoy 2012-02-29 17:44:49

+0

我提供的数组使用类似“R”“p”等字符串,我想我可以在内部使用符号吗?必须将它转换回所需结果格式的一个字符串(这就像['Richard','R']? – 2012-02-29 17:51:07

+0

你在哪里初始化游戏数组? – 2012-02-29 17:53:45

回答

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 
+0

有一个错误,我修好了,所以它应该现在工作,如果它之前没有...除非有另一个我错过了错字。 :o – robotcookies 2012-02-29 22:53:15

+0

非常感谢你,我是一个新手,对Ruby和新编码都很陌生,你的每一点都是宝石,我会把他们全部放在心上。至于球员的数量,它将永远是平等的(这就是我的方法应该接受比赛阵列)得到“Tie”逻辑将是容易的。再次感谢您解剖这些可怕的代码和无价的提示。最后一个问题,我如何“瘦”我的阵列?也许阵列#flatten – 2012-03-01 09:14:38

+0

嗨,我会编辑我的帖子,以显示稀疏你的原始数组的方式。注释字段并不容易显示代码。往上看。 – robotcookies 2012-03-01 17:49:44

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)

并在游戏戴夫击败阿曼多!

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

我建议你改写这个,试图让事情变得简单。

+0

TY,我觉得在'阿曼多'获胜后,'理查'和'迈克尔'在'理查'获胜并在下面的递归中击败'阿曼多'。 焦虑问题:你能否提出一些方法让我的代码更简单,更容易阅读和调试? – 2012-02-29 18:17:01

1

你只递归下降锦标赛[0]从来没有结束比赛前[1]。 你需要参加锦标赛[0]和锦标赛[1],然后相互对抗。

有点像。 (我把它给你写Ruby代码)

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

+0

是的 - 你是对的上面的例子产生了错误的结果,因为最初由Osama Husain描述的“括号内数组”的胜利者会导致Richard X获胜。需要注意的重要一点是联赛被括起来。 – 2012-10-07 03:17:24