【问题标题】:Scanning a list - IndexError: list index out of range扫描列表 - IndexError:列表索引超出范围
【发布时间】:2016-12-08 01:52:59
【问题描述】:

我创建了一个有一个错误的刽子手游戏:如果您将同一个字母猜两次,它就会中断。我已经创建了每个字母的列表,当玩家猜测该字母时,它将从列表中删除,显示剩余的可供猜测的字符。这是通过 .remove 方法完成的,如果字符已经从先前的猜测中删除,该方法将中断。

我试图将此方法嵌套在一个 for 循环中,该循环将扫描字母列表并检查用户对列表中匹配项的猜测并将其删除。如果已经猜到了,那么什么都不会发生。我收到的错误是索引错误,大概是猜测的长度。我的困惑来自这样一个事实,即当我扫描刽子手词以匹配玩家的猜测时,我可以直接在下面完成完全相同的任务。请看下面的删减代码:

# Play begins and player guesses a letter
player_word = ['_ '] * len(cpu_word)
player_word2 = ['_'] * len(cpu_word)
alphabet = ['a','b',etc.]
print 'You have 10 guesses left'

# Determines if the guess is correct
for count in range(10)[::-1]:
    guess = raw_input(str('Guess a letter: '))
    # This is the previous method that creates a bug:/
    # alphabet.remove(guess)
    for e in xrange(len(alphabet)):
        if alphabet[e] == guess:
            alphabet.remove(guess)
    for i in xrange(len(cpu_word)):
        if cpu_word[i] == guess:
            player_word [i] = cpu_word [i]
            print 'Correct!'

我有两个问题。首先是有人可以向我解释这个错误,特别是为什么它适用于扫描刽子手词但不适用于扫描列表。

其次,任何人都可以为这个问题提供解决方案。

我是编码新手,因此非常感谢任何信息!

谢谢

【问题讨论】:

    标签: python indexoutofboundsexception


    【解决方案1】:

    您的问题是使用索引循环遍历列表,并同时更改列表的大小。您可以直接遍历项目:

    for letter in alphabet:
        if letter == guess:
            alphabet.remove(guess)
    

    或者你可以在删除字母时打破:

    for e in range(len(alphabet)):
        if alphabet[e] == guess:
            alphabet.remove(guess)
            break
    

    Break 停止循环的终止,这很好,因为您在删除字母后就完成了。

    我认为set 会比列表更好,因为它提供O(1) 删除和包含。所以:

    alphabet = ['a','b','c'...] # list, bad
    alphabet = {'a','b','c'...} # set, good
    

    那么你的字母“循环”将是:

    if guess in alphabet:
        alphabet.remove(guess)
    

    【讨论】:

      【解决方案2】:

      无需遍历字母表,您可以通过以下方式检查字母是否仍在字母表中:

      if guess in alphabet:
          #And do the function here:
          alphabet.remove(guess)
      

      您的 for 循环包含一个缺陷。您正在删除字母表的猜测字母,但随后您的 for 循环继续。这会导致错误,因为您的字母现在短了一个字母,而循环仍然认为它与以前的大小相同。因此,打破for循环:

      for e in xrange(len(alphabet)):
          if alphabet[e] == guess:
              alphabet.remove(guess)
              break
      

      【讨论】:

        【解决方案3】:

        您的问题是,从数组中删除一项后,它现在少了一项,这意味着您无法转到数组的前一端。如果您的字母数组是 26 长,并且您删除了一个字母,则无法再访问第 26 个元素,因为该数组现在只有 25 个元素。在你猜对之后,你可以像这样打破:

        for e in xrange(len(alphabet)):
            #print alphabet[e], e
            if alphabet[e] == guess:
                alphabet.remove(guess)
                break
        

        但是您可以取消注释上面的行,并在删除之前检查它是否在数组中,如下所示:

        for count in range(10)[::-1]:
        guess = raw_input(str('Guess a letter: '))
        if(guess in alphabet):
            """"This is the previous method that creates a bug:/"""
            alphabet.remove(guess)
            for i in xrange(len(cpu_word)):
                if cpu_word[i] == guess:
                    player_word [i] = cpu_word [i]
                    print 'Correct!'
        

        【讨论】:

        • 我不确定哪种方法是最佳实践方法,但两者都有效,感谢您帮助我理解为什么前一种方法没有。谢谢!
        • 就我个人而言,我只会使用第二种方式(使用 if 语句),它的代码行数更少,而且看起来更简洁,但两者都可以。很高兴我能帮上忙!
        猜你喜欢
        • 1970-01-01
        • 2011-10-31
        • 2015-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多