我需要在ruby中创建一个程序来生成像KU765或NG274样式的机器人名称 并存储它们并检查它以避免重复。 我还需要制作一个“重置”方法来删除所有存储的名称并重新开始。 该程序由于某种原因不起作用。我希望有人帮助我找到错误。 非常感谢。
class Robot
attr_accessor :named , :stored_names , :rl
def self.name
new.name
end
@@rl = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def name
named = ""
named << @@rl[rand(26).to_i]
named << @@rl[rand(26).to_i]
named << rand(100..999).to_s
named.save_name
named.check_name
end
def save_name
stored_names = []
stored_names << named
end
def check_name
stored_names.uniq!
end
def reset
stored_names = Array.new
end
end
答案 0 :(得分:3)
这是构建您可能希望考虑的Robot
课程的另一种方法。 (我的回答通常不长或详细,但我写这部分是为了在我自己的脑海中澄清Ruby对象模型的各个方面。我希望它可以帮助其他人做同样的事情。)
<强>代码强>
PREFACE = ('A'..'Z').to_a << ?_
SUFFIX = ('0'..'9').to_a
PREFACE_SIZE = 2
SUFFIX_SIZE = 3
class Robot
def self.reset() @bots = [] end
reset
def self.new() (@bots << super).last end
def self.bots() @bots end
def self.delete(bot) @bots.delete(bot) end
def self.bot_names() @bots.map { |b| b.name } end
attr_reader :name
def initialize() @name = add_name end
private
def add_name
loop do
@name = gen_name
return @name unless self.class.bot_names.include?(@name)
end
end
def gen_name
PREFACE.sample(PREFACE_SIZE).join << SUFFIX.sample(SUFFIX_SIZE).join
end
end
示例强>
Robot.bots #=> []
robbie = Robot.new #=> #<Robot:0x000001019f4988 @name="AP436">
robbie.name #=> "AP436"
Robot.bots #=> [#<Robot:0x000001019f4988 @name="AP436">]
r2d2 = Robot.new #=> #<Robot:0x000001019cd450 @name="KL628">
r2d2.name #=> "KL628"
Robot.bots #=> [#<Robot:0x000001019f4988 @name="AP436">,
# #<Robot:0x000001019cd450 @name="KL628">]
Robot.bot_names #=> ["AP436", "KL628"]
Robot.delete(robbie) #=> #<Robot:0x000001019f4988 @name="AP436">
Robot.bots #=> [#<Robot:0x000001019cd450 @name="KL628">]
Robot.bot_names #=> ["KL628"]
Robot.reset #=> []
c3po = Robot.new #=> #<Robot:0x000001018ff8c0 @name="VO975">
Robot.bots #=> [#<Robot:0x000001018ff8c0 @name="VO975">]
<强>解释强>
解析类时,首先创建类方法reset
,然后执行行reset
。当self => Robot
发生时,执行类方法reset
,将@bots
初始化为空数组。
保存和修改Robot
实例列表的责任在于班级。此列表保存在类实例变量@bots
中。
Robot
的实例是通过调用Robot::new
创建的,initialize
分配内存然后调用(私有)实例方法new
。 Robot
在哪里?由于我们没有在Robot
中将其定义为类方法,因此有两种可能性:它是从Robot.ancestors => [Robot, Object, Kernel, BasicObject]
的祖先(Class
)中继承的,或者它是一个类Robot
的实例方法,因为Robot.class => Class
是一个实例的类(即Class.instance_method(:new) => #<UnboundMethod: Class#new>
)让我们找出哪个:Class.instance_methods.include?(:new) => true
(或Object.method(:new) => #<Method: Class#new>
),Class
。这两个都是!但这是有道理的,因为所有类都是Robot
的实例,包括Object
的超类#<Method: Class#new>
。 Object.method(:new)
new
返回的Class
已在Robot.method(:new).owner => Class
中定义(也可以new
显示。非常酷,嗯?如果你没有&#39}我已经知道了这一点,并且可以按照我在本段中所说的那样,了解了Ruby对象模型的本质!
假设我们将类方法Robot
添加到super
,如下所示。 Object::new
调用类方法Class#new
(实例方法new
),传递Object::new
的任何参数(这里没有任何参数)。 Robot::new
返回它创建的实例,def self.new
super
end
依次返回。因此,这种方法只是一种管道,对结果没有影响。
Object::new
我们可以对上述方法进行一些小改动,将@bots
创建的实例的副本添加到数组def self.new
instance = super
@bots << instance
instance
end
:
def self.new
(@bots << super).last
end
我写得更紧凑一点:
PREFACE_SIZE
我已使用方法Array#sample从PREFACE
中的SUFFIX_SIZE
和SUFFIX_SIZE
字符中随机抽取sample
个字符。 gen_name
示例无需替换,因此您无法获得,例如&#34; UU112&#34;。如果您想要替换样本,请将方法def gen_name
str = PREFACE_SIZE.times.with_object('') { |_,s| s << PREFACE.sample }
SUFFIX_SIZE.times { str << SUFFIX.sample }
str
end
替换为以下内容:
bots
我创建了一个类方法@bots
来返回类实例变量@bots
的值。也可以通过在Robots
&#39;上class << self
attr_reader :name
end
定义读访问器来完成此操作。单身人士课程:
Robot.reset
调用Robot
时,它所包含的C
的所有实例会发生什么?他们会离开森林,被拒绝和无家可归吗?在像{{1}}这样的语言中,你需要在将它们抛到一边之前释放它们的内存。在Ruby和许多其他现代语言中,这是不必要的(并且通常无法完成)。 Ruby&#34;垃圾收集&#34;跟踪所有对象,并在释放内存后终止任何其他对象不再引用的对象。很好,嗯?
答案 1 :(得分:2)
任务本身并不难,但我不喜欢你的代码组织方式。这是我在第一阶段要做的事情:
class Robot
class Name < String
class << self
def sign
"#{[*?A..?Z].sample}#{[*?A..?Z].sample}"
end
def number
"#{rand 1..9}#{rand 0..9}#{rand 0..9}"
end
def new
super << sign << number
end
end
end
end
然后:
Robot::Name.new
构建名称列表时,很容易检查它们是否唯一。这就是我要做的事情:
class Robot
class Names < Array
def self.generate n
new.tap { |array| n.times do array.add_random_name end }
end
def add_random_name
name = Name.new
include?( name ) ? add_random_name : self << name
end
end
end
然后:
Robot::Names.generate 7
答案 2 :(得分:1)
我知道这样做效率不高,但这样可行。
letters = [*'A'..'Z'] =>
numbers = [*100..999]
names = []
2.times{names.push(letters.shuffle.first)} => Randomizing array and choosing element
names.push(numbers.shuffle.first)
names.join => Creates a String object out of the array elements
这不太好,但它可以完成工作。
答案 3 :(得分:1)
这就是我使用y_support/name_magic
:
require 'y_support/all'
class Robot
★ NameMagic
def name_yourself
begin
self.name = "#{[*?A..?Z].sample( 2 ).join}#{rand 100..999}"
rescue NameError; retry end
end
end
3.times { Robot.new.name_yourself }
Robot.instances #=> [PR489, NS761, OE663]
Robot.forget "PR489"
Robot.instances #=> [NS761, OE663]
Robot.forget_all_instances
Robot.instances #=> []
Robot.new.name_yourself
Robot.instances #=> [IB573]
答案 4 :(得分:0)
def save_name
stored_names = []
stored_names << named
end
每次创建一个名称,并通过为save_name
指定一个空数组来调用stored_names
删除所有以前创建的名称
修改强> 还有一些错误,让我先发布一个有效的解决方案:
class Robot
attr_accessor :named , :stored_names , :rl
def initialize()
@stored_names = []
end
@@rl = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars.to_a
def name
@named = ""
@named << @@rl.sample
@named << @@rl.sample
@named << rand(100..999).to_s
save_name
check_name
end
def save_name
@stored_names << @named
end
def check_name
@stored_names.uniq!
end
def reset
@stored_names = Array.new
end
end
要访问对象的成员,您必须在其前面添加@
。
您在save_name
上拨打了check_name
和@named
,这是一个字符串,并没有提供这些方法
@stored_names
初始化为空数组,然后才能使用<<
将元素推入其中。这通常在课程的构造函数initialize()