我正在将一个给定的单词与用户对刽子手游戏的猜测进行比较。 word
是用户想要猜测的字符串,guesses
是一个字符串,它与用户猜对的字母连接在一起。
def initialize(word)
@word = word
@guesses = ''
@wrong_guesses = ''
end
我正在使用if word.delete(guesses).empty?
来确定胜利条件。这个代码是针对每个猜测运行的,所以我无法找到用户猜到所有正确字母的位置,并且word.delete(guesses)
没有评估为空。
def check_win_or_lose
if @word.delete(@guesses).empty?
#is this a better choice?
#if @word == self.word_with_guesses
return :win
elsif @wrong_guesses.length >= 7
return :lose
else
return :play
end
end
它有效,但我觉得这有点hacky,使用delete
的副作用。我想知道是否有更好,更简洁的方法来做到这一点。也许使用一些正则表达式?
我已经在程序的另一部分使用了一个函数;不确定它是否比.delete.empty?
方法更快/更好。它返回word
,'-'
代替未提取的字母:
def word_with_guesses
displayed = @word
@guesses.length > 0 ? displayed.gsub(/[^#{guesses}]/i, '-') : displayed.gsub(/./, '-')
end
答案 0 :(得分:3)
考虑guesses
是一个字符列表(至少是我对刽子手游戏的期望),这样做:
def won word, guess
(word.chars & guess) == word.chars.uniq
end
测试一些输入:
word = 'banana'
guess1 = %w(b a m)
guess2 = %w(b a m n)
puts won(word, guess1)
puts won(word, guess2)
#$ ruby words.rb
#false
#true
答案 1 :(得分:1)
我想我会这样做:
word.chars.sort == guesses.sort
编辑:经过进一步考虑,我可能会这样做:
def initialize(word)
@word = word
@letters_remaining = @word.chars
@correct_guesses = []
@wrong_guesses = []
end
def guess(letter)
if found_idx = @letters_remaining.index(letter)
@correct_guesses << @letters_remaining.delete_at(found_idx)
return :win if @letters_remaining.empty?
else
@wrong_guesses << letter
return :lose if @wrong_guesses.size >= MAX_WRONG_GUESSES
end
:play
end
这里发生的事情是我们保留@letters_remaining
数组,initialize
中的数字填充了该字母的字母。每次猜测时,我们都会在@letters_remaining
中查找猜到的字母。如果找到了,我们会将其删除并将其添加到@correct_guesses
,然后检查@letters_remaining
是否为空。如果是,则用户赢了。
如果猜测的字母不在@letters_remaining
中,我们会将其添加到@wrong_guesses
并检查后者的大小以确定用户是否已丢失。
如果以上都不是,则用户继续播放。
你会注意到我在数组而不是字符串中存储猜测等。由于我们的大多数逻辑都涉及字母而不是整个字符串,因此这更有意义。
编辑2:以上假设每次猜测&#34;填写&#34;一次只能写一封信。如果您希望每个猜测都填写所有匹配的字母,它将看起来像这样:
def guess(letter)
if @letters_remaining.delete(letter)
@correct_guesses << letter
return :win if @letters_remaining.empty?
else
@wrong_guesses << letter
return :lose if @wrong_guesses.size >= MAX_WRONG_GUESSES
end
:play
end
答案 2 :(得分:1)
大多数惯用语可能是:
word.chars.all?{|c| guesses[c]}
答案 3 :(得分:1)
考虑到字母的猜测会在秘密字中暴露该字母的所有实例,您可以写:
(word.chars - guesses).empty?
编辑:在反思中,您似乎可能需要一个方法,该方法采用一个猜测的参数并返回:win
,:lose
或:continue
,考虑到之前的所有猜测。如果是这样,您可以执行以下操作。
<强>代码强>
MAX_INCORRECT_GUESSES = 7
在开头执行:
def init(word)
@word = word
@nbr_incorrect = 0
end
在每次猜测后执行,直到返回:win
或:lose
:
def win_lose_or_continue(guess)
if @word.include?(guess)
@word.delete!(guess)
return @word.empty? ? :win : :continue
end
@nbr_incorrect += 1
@nbr_incorrect == MAX_INCORRECT_GUESSES ? :lose : :continue
end
<强>实施例强>
首先,显示结果的助手:
def results(guesses)
puts "@word = #{@word}"
guesses.each_char.each do |c|
puts "win_lose_or_continue(#{c}) = #{win_lose_or_continue(c)}, @word now #{@word}"
end
end
init('cat')
guesses = "argptc"
results(guesses)
@word = cat
win_lose_or_continue(a) = continue, @word now ct
win_lose_or_continue(r) = continue, @word now ct
win_lose_or_continue(g) = continue, @word now ct
win_lose_or_continue(p) = continue, @word now ct
win_lose_or_continue(t) = continue, @word now c
win_lose_or_continue(c) = win, @word now
init('cat')
guesses = "argptbfjk"
results(guesses)
@word = cat
win_lose_or_continue(a) = continue, @word now ct
win_lose_or_continue(r) = continue, @word now ct
win_lose_or_continue(g) = continue, @word now ct
win_lose_or_continue(p) = continue, @word now ct
win_lose_or_continue(t) = continue, @word now c
win_lose_or_continue(b) = continue, @word now c
win_lose_or_continue(f) = continue, @word now c
win_lose_or_continue(j) = continue, @word now c
win_lose_or_continue(k) = lose, @word now c
答案 4 :(得分:1)
我认为你的初始解决方案并不像听起来那么糟糕。问题是“删除”和“空”?与手头的问题无明显关系。阅读代码的任何人都需要联系他们相关的原因。
一个简单的解决方法是引入解释变量以明确为什么 delete
和empty?
是相关的。
从概念上讲,我认为你完全符合核心理念:将“实际猜测”的集合与“必要的猜测”进行比较。
当没有任何东西可以猜测时,玩家获胜 - 也就是说,当实际猜测的集合包含所有必要的猜测时。
您的necessary_guesses.delete(actual_guesses).empty?
解决方案会检查actual_guesses
是necessary_guesses
的子集。您可以根据您想要强调的内容以不同的方式编写它:
unguessed_characters = necessary_guesses.delete(actual_guesses)
win if unguessed_characters.empty?
或:
unguessed_characters = necessary_guesses.chars - actual_guesses.chars
win if unguessed_characters.empty?
如果您愿意使用实际的Set对象,您甚至可以编写如下内容:
win if set_of_necessary_guesses.subset?(set_of_actual_guesses)
简而言之,计算机对您的解决方案感到满意,但专注于名称可以使人类更容易。
答案 5 :(得分:0)
另一个黑客:你可以通过使用位操作使其更简洁。 不太了解ruby,但这在C ++中会是怎样的
long int checker = 0;
for(int i=0;i<word.length();i++)
{
long int t = word[i]-'a';
t = 1<<t;
if((t&checker)==0)
{
checker |= t;
}
}
for(int i=0;i<guesses.length();i++)
{
long int t = guesses[i]-'a';
t = 1<<t;
if((t&checker)==0){
return false;
}
}
return true;
也许内置的功能可以在更短的时间内优雅地解决,但如果你想定义自己的功能,你可以试试这个。希望这有帮助