开发者

Trouble with array of dictionaries, ruby

开发者 https://www.devze.com 2022-12-23 15:36 出处:网络
I am getting the following error. game.rb:46:in `play\': undefined method `[]\' for nil:NilClass (NoMethodError)

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 ^_^

0

精彩评论

暂无评论...
验证码 换一张
取 消