Trouble with array of dictionaries, ruby
I am getting the following error.
game.rb:46:in `play': undefined method `[]' for nil:NilClass (NoMethodError) from game.rb:45:in `each' from game.rb:45:in `play' from game.rb:56
with this code,
def play()
currentTile = nil
@tiles.each do |tile|
if(tile['Name'] == 'Starting Square')
currentTile = tile
end
puts("#{currentTile['Desciption']}")
end
end
This is part of a text adventure开发者_如何转开发 game, I am playing with @tiles is an array of tiles that was read from a file. Each tile is a dictionary.
Thanks for any help, I cant figure this out
try this:
def play()
currentTile = nil
@tiles.each do |tile|
currentTile = tile if tile['Name'] == 'Starting Square'
puts("#{currentTile['Desciption']}") unless currentTile.nil?
end
end
You've got an error because currentTile became a tile not in the very first iteration. It get 'description' key only when name of tile is 'Starting Square'
I see that you're probably trying to debug by printing whether or not currentTile
is set yet. All fine and dandy.
However, note that, until the name matches Starting Square
, currentTile
will continue to be nil
, and you can't access the property of a nil
object. Maybe the starting square isn't the first tile on the list?
Looks like you're trying to print the description of currentTile after you've located it, but you have the puts inside the search loop.
Try:
def play()
currentTile = nil
@tiles.each do |tile|
if(tile['Name'] == 'Starting Square')
currentTile = tile
end
end
puts("#{currentTile['Desciption']}")
end
There's still no guarantee that you won't get a nil reference (if there are no tiles with the name 'Starting Square', but the code you've got will only work if the very first tile in @tiles is the one titled 'Starting Square'
The other answers seem to have you covered (indexing currentTile after it is set to nil), but for whatever its worth, you might want to be using symbols for your keys and values, rather than strings. Symbols are faster to look up and faster to compare, as they're just named pointers, whereas checking string equality is an O(n) operation.
So something like
def play()
currentTile = nil
@tiles.each do |tile|
if(tile[:name] == :startingSquare)
currentTile = tile
end
end
puts("#{currentTile['Desciption']}") unless currentTile.nil?
end
Then again, I don't know your application, maybe it's perfectly appropriate ^_^
精彩评论