在Ruby中将两个字符串过滤成一个的最佳方法

3

我正在尝试找出一种方法,根据猜测一个数组中的字母来将两个数组过滤成一个数组。这基本上就是“猜词游戏”。但如果我有

word_array = ["b", "u", "s", "b", "o", "i"]
hidden_array = Array.new(word_array.length, "-")

p hidden_array

我希望能在控制台中打印出 ["b", "-", "-", "b", "-", "-"],如果猜测的字母是“b”。那么,作为初学者,创建一个随时间变化的数组的好方法是什么?它应该是哈希表吗?谢谢!

移除 u、s、o、i 的条件是什么? - Gopal
busboi 到底是什么?这是一个真实的单词吗? - Tom Lord
我假设 busboi 只是一个例子,@TomLord!哈哈 - Ed de Almeida
@Gopal,条件是与“b”不同。 “b”是猜测的字母,程序可能会显示“b”,但不会显示其他字母。就像OP所解释的那样,在hagman游戏中一样。 - Ed de Almeida
4个回答

6
到目前为止,所有的解决方案都是围绕数组展开,但不要忘记字符串基本上就是一个字符数组。只需使用字符串即可:
word = 'busboi'
guesses = 'bs'

word.tr('^'+guesses, '-')
# => "b-sb--"

String#tr 方法可以将第一个参数中的所有字母映射到第二个参数中,因此您可以执行 ROT13、简单密码等操作,或者在本例中使用否定特性 ^ 来反转第一个集合并替换所有不匹配的字符。


我喜欢。word.gsub(/[^#{guesses}]+/, '-') 是一种变体。 - Cary Swoveland
@CarySwoveland 是的,那也可以,但 tr 对于这个工作来说是完美的。 - tadman

3
你可以将找到的字母存储在数组中,并创建一个方法来进行打印。
word_array = ["b", "u", "s", "b", "o", "i"]
found_letters = []
def hangman_prompt(found_letters)
  word_array.map do |char|
    found_letters.include?(char) ? char : "-"
  end.join(" ")
end

那么你可以像这样在输入循环中使用它:
loop do
  puts hangman_prompt(found_letters)
  puts "what is your guess?"
  input = gets.chomp
  if word_array.include? input
    found_letters << input
  end
end

我在这里使用了Array#map,它创建一个长度相同的新数组。原始数组中的每个项目都会传递到代码块中,该块决定如何将它们复制到新数组中。

太棒了。谢谢Max!我都明白了,除了在hangman_prompt方法的末尾标记为.join(" ")。我以前见过.join..但从未在方法定义结尾处使用过。不过应该很容易弄清楚!看起来这只是一种更简单的方式来整合所需的.join。 - Rob Matthews
是的,我想那只是一种语法技巧。这里之所以有这个原因是,如果你puts一个数组,它会有换行符,而这不是你想要的。你可以在puts之前使用print或连接。 - max pleaner

2

一种方法:

word_array = ["b", "u", "s", "b", "o", "i"]
word_array_i = word_array.map.with_index { |e,i| [e,i] }                                                
#=> [["b", 0], ["u", 1], ["s", 2], ["b", 3], ["o", 4], ["i", 5]] 
p hidden_array = Array.new(word_array.length, "_")

until hidden_array == word_array
  puts 'make a guess'
  guess = gets.chomp
  if word_array.include? guess
    puts 'correct guess'
    ar = word_array_i.select { |arr| arr.first == guess }
                     .flatten.select { |e| e.class == Fixnum }
    ar.each { |e| hidden_array[e] = guess }
  else
    puts 'incorrect guess'
  end
  p hidden_array
  puts
end
puts 'game complete'

研究的关键方法在这里,包括Array#include?Enumerator#with_index


2
我建议不要使用数组,只使用字符串。 代码
def replace_underscores(word, hidden_word, guess)
  word.scan(Regexp.new(guess)) { hidden_word[Regexp.last_match.begin(0)] = guess }
  hidden_word
end

例子

word = "busboi" 
hidden_word = "_" * word.length
  #=> "______"

replace_underscores(word, hidden_word, "a") # guess "a"
  #=> "______"
replace_underscores(word, hidden_word, "b") # guess "b"
  #=> "b__b__"                                            
replace_underscores(word, hidden_word, "r") # guess "r"
  #=> "b__b__" 
replace_underscores(word, hidden_word, "o") # guess "o"
  #=> "b__bo_" 
replace_underscores(word, hidden_word, "u") # guess "u"
  #=> "bu_bo_" 
replace_underscores(word, hidden_word, "s") # guess "s"
  #=> "busbo_" 

检查是否已经猜出了hidden_word:

def guessed?(hidden_word)
  hidden_word.count('_').zero?
end

guessed?(hidden_word)   
  #=> false

Let's permit one more guess.

replace_underscores(word, hidden_word, "i") # guess "i"
  #=> "busboi" 

guessed?(hidden_word)   
  #=> true

注释

我使用了方法String#scan,并带有一个块,该块对每个匹配项执行。在块内,使用类方法Regexp::last_match检索MatchData对象。(或者,可以将全局变量$~替换为Regexp.last_match。有关详细信息,请搜索“special global variables” Regexp。)方法MatchData.begin用于获取要用猜测的字母替换的str中字符的索引。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接