我是Ruby的初学者。我正在学习目前正在学习Ruby的艰辛之路的第45课,我正在创建一个类似于Zork和Adventure的游戏。
我创建了一个结构,我在不同的文件中创建'场景'并要求所有场景都在一个文件中,我有一个引擎/地图,确保当前场景不等于'完成'它运行'X '场景''输入'方法。
但是我有两个问题: 1)我一直收到错误提示“警告类变量从顶层访问” 2)即使脚本正在运行,我也得到了
ex45.rb:30:in `play': undefined method `enter' for nil:NilClass (NoMethodError) from ex45.rb:59:in
以下是我每个文件的所有代码。我很抱歉,如果这是一个很长的阅读,但我很想知道为什么我得到这两个错误以及我可以做些什么来解决它们。
Ex45.rb:
require "./scene_one.rb"
require "./scene_two.rb"
require "./scene_three.rb"
@@action = SceneOne.new
@@action_two = SceneTwo.new
@@action_three = SceneThree.new
class Engine
def initialize(scene_map)
@scene_map = scene_map
end
def play()
current_scene = @scene_map.opening_scene()
last_scene = @scene_map.next_scene('finished')
while current_scene != last_scene
next_scene_name = current_scene.enter()
current_scene = @scene_map.next_scene(next_scene_name)
end
current_scene.enter()
end
end
class Map
@@scenes = {
'scene_one' => @@action,
'scene_two' => @@action_two,
'scene_three' => @@action_three
}
def initialize(start_scene)
@start_scene = start_scene
end
def next_scene(scene_name)
val = @@scenes[scene_name]
return val
end
def opening_scene()
return next_scene(@start_scene)
end
end
a_map = Map.new('scene_one')
a_game = Engine.new(a_map)
a_game.play()
scene_one.rb:
类SceneOne
def enter
puts "What is 1 + 2?"
print "> "
answer = $stdin.gets.chomp
if answer == "3"
puts "Good job"
return 'scene_two'
else
puts "try again"
test
end
end
end
scene_two.rb
class SceneTwo
def enter
puts "1 + 3?"
print "> "
action = $stdin.gets.chomp
if action == "4"
return 'scene_three'
else
puts "CANNOT COMPUTE"
end
end
end
scene_three.rb
class SceneThree
def enter
puts "This is scene three"
end
end
提前致谢!
答案 0 :(得分:3)
回答您的第一个问题:
您需要在Map
类中移动类变量定义以消除这些警告:
Ex45.rb:5: warning: class variable access from toplevel
Ex45.rb:6: warning: class variable access from toplevel
Ex45.rb:7: warning: class variable access from toplevel
所以,你的Map
类看起来像这样:
class Map
@@action = SceneOne.new
@@action_two = SceneTwo.new
@@action_three = SceneThree.new
@@scenes = {
'scene_one' => @@action,
'scene_two' => @@action_two,
'scene_three' => @@action_three
}
def initialize(start_scene)
@start_scene = start_scene
end
def next_scene(scene_name)
val = @@scenes[scene_name]
return val
end
def opening_scene()
return next_scene(@start_scene)
end
end
回答第二个问题:
您收到undefined method 'enter' for nil:NilClass (NoMethodError)
,因为您的current_scene
在某个时候变为nil
,然后您尝试致电:current_scene.enter()
即nil.enter
,但它失败了错误信息。
要解决此问题,您必须确保current_scene
中始终有一些价值,即确保它不是nil
。
我认为,您可以从current_scene.enter()
课程中的play
方法的末尾删除Engine
行。因此,您的Engine
课程将如下所示:
class Engine
def initialize(scene_map)
@scene_map = scene_map
end
def play()
current_scene = @scene_map.opening_scene()
last_scene = @scene_map.next_scene('finished')
while current_scene != last_scene
next_scene_name = current_scene.enter()
current_scene = @scene_map.next_scene(next_scene_name)
end
# current_scene.enter()
end
end
而且,你不会再犯这个错误了。
答案 1 :(得分:0)
你知道吗:
@@y = 20
p Object.class_variables
--output:--
1.rb:1: warning: class variable access from toplevel
[:@@y]
和
class Object
def self.y
@@y
end
end
puts Object.y
--output:--
20
可是:
class Dog
@@y = "hello"
def self.y
@@y
end
end
puts Dog.y #=>hello
puts Object.y #=>What do you think?
最后一行的输出是ruby中不使用类变量的原因。您应该使用所谓的 类实例变量 ,而不是类变量:
class Object
@y = 10 #class instance variable
def self.y
@y
end
end
puts Object.y
class Dog
@y = "hello"
def self.y
@y
end
end
puts Dog.y #=> hello
puts Object.y #=> 10
一个类实例变量只是一个@variable,它位于类中,但在任何def之外。而不是所有子类共享一个 @@ variable ,而每个子类都有自己的 @variable 。