我正在解决“摇滚,纸张,剪刀”游戏。输入数组并递归输出获胜者。这是我的代码:
class RockPaperScissors
# Exceptions this class can raise:
class NoSuchStrategyError < StandardError; end
def self.winner(player1, player2)
strategy = player1[1]+player2[1]
raise NoSuchStrategyError.new("Strategy must be one of R,P,S") if strategy !~ /(R|P|S){2}/
strategy =~ /rs|sp|pr|rr|ss|pp/i ? player1 : player2
end
def self.tournament_winner(tournament)
if tournament.length==2 && tournament.first[0].is_a?(String)
winner(tournament[0],tournament[1])
else
#keep slice the array in half
***winner(tournament_winner(tournament[0,tournament.length/2]), tournament_winner(tournament[tournament.length/2]))***
end
end
end
我的堆栈级别太深,因为该代码以粗体显示。是因为tournament.length正在改变所以我不应该把它放在递归中?有人能详细解释一下这是怎么发生的吗?
我搜索了答案,有人使用下面的代码并且工作了。我想知道为什么对锦标赛的引用不会导致相同的递归问题。
winner(tournament_winner(tournament[0]), tournament_winner(tournament[1]))
感谢您的帮助!
示例输入:
[
[
[ ["Armando", "P"], ["Dave", "S"] ],
[ ["Richard", "R"], ["Michael", "S"] ],
],
[
[ ["Allen", "S"], ["Omer", "P"] ],
[ ["David E.", "R"], ["Richard X.", "P"] ]
]
]
答案 0 :(得分:1)
你的代码没有把锦标赛分成两半 - tournament[tournament.length/2]
没有返回数组的后半部分 - 它只返回位置tournament.length/2
的项目,而是你应该这样做:
winner(tournament_winner(tournament[0...tournament.length/2]), tournament_winner(tournament[tournament.length/2..-1]))
此外,您不会考虑长度为1
的数组,从而导致无休止的递归。
以下是您的代码的工作版本:
def tournament_winner(tournament)
if tournament.length == 1
tournament_winner(tournament[0])
elsif tournament.length==2 && tournament.first[0].is_a?(String)
winner(tournament[0],tournament[1])
else
winner(tournament_winner(tournament[0...tournament.length/2]),
tournament_winner(tournament[tournament.length/2..-1]))
end
end
答案 1 :(得分:0)
有很多更好的处理方式,比杂乱的正则表达式,令人困惑的缩写和字符串遍布整个地方。
例如,您可以使用更面向对象的方法:
module RockPaperScissors
class NoSuchStrategyError < StandardError; end
class Move
include Comparable
attr_reader :strategy
def initialize(strategy)
raise NoSuchStrategyError unless strategies.include?(strategy)
@strategy = strategy
end
def <=>(opposing_move)
if strengths[strategy] == opposing_move.strategy
1
elsif strengths[opposing_move.strategy] == strategy
-1
else
0
end
end
protected
def strengths
{
rock: :scissors,
scissors: :paper,
paper: :rock
}
end
def strategies
strengths.keys
end
end
class Player
attr_reader :name, :move
def initialize(name, move)
@name, @move = name, move
end
end
class Tournament
def initialize(*players)
@player_1, @player_2, _ = *players
end
def results
p1move = @player_1.move
p2move = @player_2.move
if p1move > p2move
"#{@player_1.name} wins."
elsif p2move > p1move
"#{@player_2.name} wins."
else
"Tie."
end
end
end
end
使用示例:
rock = RockPaperScissors::Move.new(:rock)
paper = RockPaperScissors::Move.new(:paper)
player_1 = RockPaperScissors::Player.new('John Smith', rock)
player_2 = RockPaperScissors::Player.new('Corey', paper)
tournament = RockPaperScissors::Tournament.new(player_1, player_2)
tournament.results #=> "Corey wins."