改变变量直到它是正确的(如果,否则)

时间:2012-04-05 15:10:23

标签: ruby

我运行一个用ruby编写的irc bot,运行cinch irc框架。机器人回答有趣的事实,并通过这些事实循环,这样你就不会对它们感到厌倦。我已经冷静下来,所以他们无法显示6个小时。它不是显示它首先显示的事实,而是显示随机选择的事实,这可能是之前已经显示过的事实。

line = IO.readlines("facts.txt")
factnumber = rand(line.length)
    if fact_not_next_6_hours[factnumber] == true
    factnumber = rand(line.length)
    m.reply "fact #{factnumber}: #{line[factnumber]}"
    fact_not_next_6_hours[factnumber] = true

fact_not_next_6_hours[factnumber]是6小时冷却的变量;如果设置为true,则冷却处于活动状态。我需要这样做:

factnumber = rand(line.length) 

直到它得到一个没有将6小时冷却设置为真,然后执行

m.reply "fact #{factnumber}: #{line[factnumber]}"
fact_not_next_6_hours[factnumber] = true

我的第一个想法是做多个if,但它不起作用,我确信有更好的方法。

3 个答案:

答案 0 :(得分:1)

你可以这样做:

factnumber = rand(line.length)
while fact_not_next_6_hours[factnumber] == true
  factnumber = rand(line.length)
end
m.reply "fact #{factnumber}: #{line[factnumber]}"
fact_not_next_6_hours[factnumber] = true

或者:

nil while fact_not_next_6_hours[factnumber = rand(line.length)] == true
m.reply "fact #{factnumber}: #{line[factnumber]}"
fact_not_next_6_hours[factnumber] = true

答案 1 :(得分:1)

您应该将line重命名为lines,因为它实际上是一系列行。我在答案中这样做了。

这实际上是一个“do while”循环:

begin 
  factnumber = rand(lines.length)
end while fact_not_next_6_hours[factnumber]

但是根据您拥有的事实数量以及您希望“使用”的数量,过滤掉您先无法使用的事实可能会更有意义:

fact = (0...lines.length).zip(lines).reject do |k, v|
  fact_not_next_6_hours[k]
end.sample

m.reply "fact #{fact[0]}: #{fact[1]}"

第一位((0...lines.length).zip(lines))只是将每一行与一个数字相关联(例如[[0, "fact"], [1, "afact"], ...])。我建议单独运行方法链的每个部分,以便您可以完全了解正在发生的事情。

答案 2 :(得分:1)

首先,如果你只是设置一个布尔标志,你怎么知道何时“解冻”呢?我将保留对象中最后访问时间的“时间戳”。此外,我不再使用原始类型,而是采用更加面向对象的方式。

这是我的解决方案:

class Fact
  attr_reader :text

  def initialize(text)
    @text = text
    @last_accessed = Time.new(0) # a long time ago, not in cooldown
  end

  def in_cooldown?
    Time.now - @last_accessed < 60*60*6
  end

  def cooldown!
    @last_accessed = Time.now
  end
end

class Facts
  attr_reader :all

  def initialize(file_name)
    @all = IO.readlines("facts.txt").map{|line| Fact.new(line)} 
  end
end

class FactRandomizer
  def initialize(facts)
    @facts = facts
  end

  def get
    fact = not_in_cooldown.sample || all.sample # all can be in cooldown
    fact.cooldown!
    fact.text
  end

  private

  def not_in_cooldown
    @facts.select{|fact| !fact.in_cooldown?}
  end
end

用法:

facts = Facts.new("whatever").all
randomizer = FactRandomizer.new(facts)
randomizer.get

编辑:

我重构了代码,因此它不再使用类方法了。注意,现在测试这段代码要容易多少,以及交换它的部分是多么容易(比如替换从文件中读取事实的部分或者对于冷却事实的意义)。