keskiviikko
keskiviikko

Reputation: 9

How to replace matching characters in a string? (Ruby)

I'm building a hangman game and I have no idea how to replace underscores in hidden_word (String) with matching letters in player_input (Array). Any ideas what I should do? Thank you in advance, I appreciate it!

def update
  if @the_word.chars.any? do |letter|
     @player_input.include?(letter.downcase)
     end
     puts "updated hidden word" #how to replace underscores?
  end
  puts @hidden_word
  puts "You have #{@attempts_left-1} attempts left."
end

I have two Strings, the_word and hidden_word, and an Array, player_input. Whenever the player selects a letter which matches with the_word, the hidden_word should update.

For example

the_word = "RUBY"

hidden_word = "_ _ _ _"

Player chooses "g", hidden_word still "_ _ _ _"

Player chooses "r", hidden_word updates "R _ _ _"

Here's the rest of the code:


class Game
    attr_reader :the_word

    def initialize
        @the_word = random_word.upcase
        @player_input = Array.new
        @attempts_left = 10
    end

    def random_word
        @the_word = File.readlines("../5desk.txt").sample.strip()
    end

    def hide_the_word
        @hidden_word = "_" * @the_word.size
        puts "Can you find out this word? #{@hidden_word}"
        puts "You have #{@attempts_left} attempts left."
        puts @the_word #delete this
    end

    def update
        if @the_word.chars.any? do |letter|
            @player_input.include?(letter.downcase)
            end
            puts "updated hidden word" #how to replace underscores?
        end
        puts @hidden_word
        puts "You have #{@attempts_left-1} attempts left."
    end

    def guess_a_letter
        @player_input << gets.chomp
        puts "All the letters you have guessed: #{@player_input}"
    end

    def has_won?
        if !@hidden_word.include?("_") || @player_input.include?(@the_word.downcase)
            puts "You won!"
        elsif @attempts_left == 0
            puts "You lost..."
        end
    end

    def game_round #the loop need fixin
        puts "Let's play hangman!"
        hide_the_word
        while @attempts_left > 0
            guess_a_letter
            update
            @attempts_left -= 1 #fix this
            has_won?
            break if @player_input.include?("q") #delete this
        end
    end
end


new_game = Game.new
new_game.game_round

Upvotes: 0

Views: 283

Answers (3)

castwide
castwide

Reputation: 323

One option is to use a regular expression:

@hidden_word = @the_word.gsub(/[^#{@player_input.join('')}\s]/i, '_')

Upvotes: 0

mechnicov
mechnicov

Reputation: 15517

I don't sure about downcase because you have used uppercase too.

Choose only one letter case.

But it will work for you:

def update
  @the_word.each_char.with_index do |letter, index|
     @hidden_word[index] = letter if @player_input.include?(letter.downcase)
  end

  puts @hidden_word
  puts "You have #{@attempts_left-1} attempts left."
end

It compares each letter of secret word with user's inputs and changes underscore in hidden word by coincidence.

Here I used String#each_char, String#[]=, Enumerator#with_index

Upvotes: 0

fphilipe
fphilipe

Reputation: 10054

Here's some code that should get you going. Collect the guessed letters in an array. Then, map the chars of the word to either the char if it was guessed or an underscore.

word = "RHUBARB"
guessed_letters = ['A', 'R', 'U']
hidden_word = word.chars.map { |c| guessed_letters.include?(c) ? c : '_' }.join
# => "R_U_AR_"

Upvotes: 1

Related Questions