Я не понимаю эту ключевую ошибку? - PullRequest
2 голосов
/ 03 апреля 2020

Я выполняю эту задачу, когда мне поручено написать игру «Палач», где я должен уменьшить диапазон слов в наборе. Правила игры гласят, что вы получаете 8 попыток, так что угадывайте, иначе вы Если бы пользователь несколько раз набирал одно и то же письмо, всплыло бы сообщение о том, что он уже сделал это - я использовал наборы как способ справиться с этой частью игры. Ниже приведен мой код:


word_list = ["python", "java", "kotlin", "javascript"]
word = random.choice(word_list)
word_set = set(word)

hidden = []
for i in word:
    hidden.append("-")
# print(hidden)


print("H A N G M A N")

count = 0
while(count < 8):
    print()
    print("".join(hidden))
    guess = input("Input a letter: ")
    if guess in word:
        if guess not in word_set:
            print("No improvements")
            count += 1
        else:
            for i in range(len(word)):
                if word[i] == guess:
                    print(word_set)
                    word_set.remove(word[i])
                    hidden[i] = word[i]
                    if word_set == set():
                        print()
                        print(word)
                        print("You guessed the word!")
                        print("You survived!")
    else:
        print("No such letter in the word")
        count += 1

print("You are hanged!")

Основная проблема, с которой я сталкиваюсь, - это ошибка, сообщающая мне, что 'a' и, в частности, только 'a', является ключевой ошибкой, которая выглядит следующим образом: Traceback (most recent call last): File "/Users/laipinhoong/Desktop/learnpython.py/learning.py", line 29, in <module> word_set.remove(word[i]) KeyError: 'a'

Ответы [ 5 ]

4 голосов
/ 03 апреля 2020

Проблема возникает, когда выбранное слово имеет одну и ту же букву более одного раза. В этом случае, поскольку вы перебираете все буквы в слове (for i in range(len(word))), вы попытаетесь удалить это слово несколько раз из набора word_set (столько, сколько эта буква появляется в слове), но word_set будет иметь это письмо только один раз, так как множество является уникальной коллекцией. Таким образом, во второй попытке удалить a из javascript или java, word_set.remove(word[i]) завершится неудачей, так как набор больше не будет содержать эту букву.

Чтобы предотвратить ошибку, попробуйте использовать : word_set.discard(word[i]) вместо. В этом случае письмо будет удалено, если оно существует, а если нет, исключений не будет.

1 голос
/ 03 апреля 2020

Вы пытаетесь удалить одну и ту же букву несколько раз, потому что вы повторяете word - вместо этого итерируйте ее набор букв. Вы также можете предварительно рассчитать позиции каждой буквы в вашем слове в словаре и использовать это для «заполнения пробелов», например, так:

word = "javascript"
seen = set()           # letters that were guessed get added here 
letters = set(word)    # these are the letters to be guessed

hidden = ["_" for _ in word]   # the output

positions = {l:[] for l in letters }  # a dictionary letter => positions list
for idx,l in enumerate(word):         # add positions of each letter into the list
    positions[l].append(idx)

print("H A N G M A N")

count = 0
while count < 8:
    print()
    print("".join(hidden))

    # allow only 1-letter guesses
    guess = input("Input a letter: ").strip()[0]

    # if in seen it is a repeat, skip over the remainder of the code
    if guess in seen:
        print("Tried that one already.")
        continue

    # found a letter inside your word
    if guess in positions:    
        # update the output list to contain this letter
        for pos in positions.get(guess):
            hidden[pos]=guess
        # remove the letter from the positions list 
        del positions[guess]

    else: # wrong guess
        count += 1
        print("No improvements: ", 8-count, "guesses left.")

    # remember the seen letter    
    seen.add(guess) 

    # if the positions dictionary got cleared, we have won and found all letters
    if not positions:    
        print(word)
        print("You guessed the word!")
        print("You survived!")
        break

# else we are dead
if count==8:
    print("You are hanged!")

Вывод:

__________
Input a letter: 
j_________
Input a letter: 
ja_a______
Input a letter: 
java______
Input a letter: 
javas_____
Input a letter: 
javasc____
Input a letter: 
javascr___
Input a letter: 
javascri__
Input a letter: 
javascrip_

# on bad inputs:
No improvements:  7 guesses left.

# on win
javascript
You guessed the word!
You survived!

# on loose
You are hanged!
0 голосов
/ 03 апреля 2020

Set.remove () выдает KeyError, если удаляемый элемент не является частью набора.

В вашем случае это вызвано тем, что word_set и word не имеют одинаковых букв.

Например, если word = java, тогда word_set = (j, a, v)

И поскольку вы перебираете слово вместо word_set, ваш код попытается удалить букву «a» дважды из word_set, что приведет к ключевой ошибке

0 голосов
/ 03 апреля 2020

Вы должны понимать, что делает ваш код:

Когда вы удаляете символ из word_set.remove (word [i]). Это удаляет его, но на 2-й итерации он не находит символ, поэтому выдает ошибку ключа, потому что не может найти ключ, который уже удален.

Попробуйте добавить условие if, как в этом коде, чтобы проверить, если ключ существует перед удалением, практически обходится, если его не существует и спасает вас от ошибки

import random

word_list = ["python", "java", "kotlin", "javascript"]
word = random.choice(word_list)
print(word)
word_set = set(word)

hidden = []
for i in word:
    hidden.append("-")
#print(hidden)


print("H A N G M A N")

count = 0
while(count < 8):
    print()
    print("".join(hidden))
    guess = input("Input a letter: ")
    if guess in word:
        if guess not in word_set:
            print("No improvements")
            count += 1
        else:
            for i in range(len(word)):
                if word[i] == guess:

                    if word in word_set:
                        word_set.remove(word[i])
                    hidden[i] = word[i]
                    if word_set == set(hidden):
                        print()
                        print(word)
                        print("You guessed the word!")
                        print("You survived!")
    else:
        print("No such letter in the word")
        count += 1

print("You are hanged!")
0 голосов
/ 03 апреля 2020

Ваша ключевая ошибка будет происходить каждый раз, когда вы выбираете букву, которая повторяется в слове. Когда вы делаете word_set.remove(word[i]) внутри for i in range(len(word)): l oop и word имеет одну и ту же букву в нескольких i с, эта ключевая ошибка возникнет, когда она достигнет второй i, соответствующей этой букве в слово. Это будет иметь больше смысла для вас, если вы пройдете по коду в python tutor .

...