首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ruby递归-堆栈级别太深错误

Ruby递归-堆栈级别太深错误
EN

Stack Overflow用户
提问于 2014-06-13 19:41:18
回答 2查看 220关注 0票数 0

我在解决“石头,纸,剪刀”的游戏。输入数组并递归地输出优胜者。这是我的代码:

代码语言:javascript
复制
   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
  1. 我的堆栈级别太深了,因为代码是粗体的。是因为tournament.length在改变,所以我不应该把它放在递归中吗?有人能详细解释一下这是怎么发生的吗?
  2. 我搜索了答案,有人使用了下面的代码并开始工作。我想知道为什么对锦标赛的引用不会引起同样的递归问题。 获胜者(tournament_winner(锦标赛),tournament_winner(tournament1))

谢谢你的帮助!

样本输入:

代码语言:javascript
复制
[
    [
        [ ["Armando", "P"], ["Dave", "S"] ],
        [ ["Richard", "R"],  ["Michael", "S"] ],
    ],
    [
        [ ["Allen", "S"], ["Omer", "P"] ],
        [ ["David E.", "R"], ["Richard X.", "P"] ]
    ]
]
EN

回答 2

Stack Overflow用户

发布于 2014-06-13 19:48:23

您的代码不会将比赛分割成一半-- tournament[tournament.length/2]不返回数组的后半部分--它只返回位于tournament.length/2位置的项,相反,您应该这样做:

代码语言:javascript
复制
winner(tournament_winner(tournament[0...tournament.length/2]), tournament_winner(tournament[tournament.length/2..-1]))

此外,您也不考虑长度为1的数组,这会导致无休止的递归。

下面是代码的工作版本:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2014-06-13 20:20:51

有很多更好的方法来处理这个问题,而不是杂乱无章的正则表达式、混乱的缩写和字符串。

例如,您可以使用更面向对象的方法:

代码语言:javascript
复制
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

示例用法:

代码语言:javascript
复制
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."
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24212779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档