在Ruby中构建事件循环时,如何避免无限递归?

时间:2015-12-16 01:14:19

标签: ruby loops runtime-error

我想在Ruby中实现一个游戏循环,但是我目前的实现收到的堆栈级别太深了' (SystemStackError)。

这就是我在我的俄罗斯方块般的下滑式游戏中取得的成就:

# falling block game
class Tetris
  class EndGame < StandardError; end

  def start
    @canvas = Canvas.new
    @canvas.banner = "New game"
    @canvas.draw
    update
  end

  def update
    step
    update
  rescue EndGame
    puts "Game over!"
  end

  def step
    puts "Take one step..."
    # TODO: do stuff here
  end

  # draws our game board
  class Canvas
    SIZE = 10

    attr_accessor :banner, :board

    def initialize
      @board = SIZE.times.map { Array.new(SIZE) }
    end

    def update(point, marker)
      x, y = point
      @board[x, y] = marker
    end

    alias_method :draw, :to_s
    def draw
      [banner, separator, body, separator].join("\n")
    end

    private

    def separator
      "=" * SIZE
    end

    def body
      @board.map do |row|
        row.map { |e| e || " " }.join
      end.join("\n")
    end
  end
end

game = Tetris.new
game.start

产生此错误:

Take one step...
Take one step...
Take one step...
Take one step...
Take one step...
Take one step...
Take one step...
Take one step...
Take one step...
Take one step...
gameloop.rb:20:in `puts': stack level too deep (SystemStackError)
    from gameloop.rb:20:in `puts'
    from gameloop.rb:20:in `step'
    from gameloop.rb:13:in `update'
    from gameloop.rb:14:in `update'
    from gameloop.rb:14:in `update'
    from gameloop.rb:14:in `update'
    from gameloop.rb:14:in `update'
    from gameloop.rb:14:in `update'
     ... 10067 levels...
    from gameloop.rb:14:in `update'
    from gameloop.rb:14:in `update'
    from gameloop.rb:9:in `start'
    from gameloop.rb:59:in `<main>'

更新

Ruby默认情况下不启用Tail Call Optimizations,但可以在Ruby VM中启用它。

RubyVM::InstructionSequence.compile_option = {
  tailcall_optimization: true,
  trace_instruction: false
}

1 个答案:

答案 0 :(得分:3)

使用while true ...循环而不是递归。您还可以添加一个简短的sleep,以避免更新所需的更新。