13

I have started to learn Ruby. I have a small project to build a game and tried to create a function that receives user input and handles it accordingly.

def Game.listener
  print "> "

  while listen = $stdin.gets.chomp.downcase

    case listen
    when (listen.include?("navigate"))
      puts "Navigate to #{listen}"
      break
    when ($player_items.include?(listen))
      Items.use(listen)
      break
    end

    puts "Not a option"
    print "> "
  end
end

However, the case statement is unable to detect I have typed navigate. Is there a way to fix this or if I'm totally off can someone point me in the right direction?

I have found this way to solve my problem, is it a safe and reliable way?

  while listen = $stdin.gets.chomp
      case listen.include?(listen)
      when listen.include?("navigate")
        puts "Navigate to #{listen}"
      when listen.include?("test")
        puts "test"
      when $player_items.include?(listen)
        puts "Using the #{$player_items[listen]}"
        break
      else
        puts "Not a option"
      end
      print "> "
   end
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
MrSlippyFist
  • 481
  • 2
  • 6
  • 19
  • 1
    Use regex with either `[]`-notation, `scan` or `match`. – Sagar Pandya Nov 29 '16 at 14:46
  • @sagarpandya82 Thank you. Can you provide me with an example of how this works? I'm new to this area – MrSlippyFist Nov 29 '16 at 14:51
  • 1
    `(listen.include?("navigate"))` equals `true` or `false`, so the line following is executed if `listen` equals that logical value. That's not what you want. You need to change `case listen` to `case`. – Cary Swoveland Nov 29 '16 at 15:16
  • Exactly what I needed. Thanks for the explanation. If you put this as answer I can mark your answer as solution. – MrSlippyFist Nov 29 '16 at 15:18
  • Glad to help. I can't post an answer right now, but someone else will. Please don't be in a rush to accept any answer as you don't want to discourage others. – Cary Swoveland Nov 29 '16 at 15:26
  • I see @spickermann posted a good answer. (The posting times show he undoubtedly did not see my comment before he posted.) – Cary Swoveland Nov 29 '16 at 15:35
  • `r = /\bhello\b/; listen[r]; listen.scan(r); listen.match(r)`. See [square-bracket notation](http://ruby-doc.org/core-2.3.3/String.html#method-i-5B-5D), [String#scan](http://ruby-doc.org/core-2.3.3/String.html#method-i-scan) and [String#match](http://ruby-doc.org/core-2.3.3/String.html#method-i-match) for more info. – Sagar Pandya Nov 29 '16 at 16:10
  • 1
    `listen` is a `String`, `listen.include?('navigate')` is a boolean. A boolean will never be equal to nor will it match a `String`, therefore that branch can never execute … and the same for all the other branches. – Jörg W Mittag Nov 29 '16 at 21:41
  • There's some additional information in https://stackoverflow.com/a/948157/313756 that may be helpful to folks here. – lindes Jan 15 '23 at 19:42

2 Answers2

19

If you want to use a case instead of an if-elsif block, then you can write it like this (note the blank space after the case):

while listen = $stdin.gets.chomp
  case
  when listen.include?('navigate')
    puts "Navigate to #{listen}"

  when listen.include?('test')
    puts 'test'
  
  when $player_items.include?(listen)
    puts "Using the #{$player_items[listen]}"
    break

  else
    puts "Not an option"
  end

  print "> "
end
spickermann
  • 100,941
  • 9
  • 101
  • 131
0

In your case use a if elsif

if listen.include?("navigate")
  # ...
elsif $player_items.include?(listen)
  # ...
end
Timo Schilling
  • 3,003
  • 1
  • 17
  • 29
  • Wow quick response! That'll work, thank you. I was wondering though if there was a cleaner way since the game will "listen" to a lot more inputs in the future. Hence I chose to use case – MrSlippyFist Nov 29 '16 at 14:50