gp0478
gp0478

Reputation: 91

Flaw in hangman program

I need to write a simple hangman function that takes in one string (the word that's being guessed) and a list of letters (the letters that are guessed). This is the code I'm using:

def WordGuessed(Word, letters):
    if letters == []:
        return False
    else:
        for i in letters:
            if i not in Word:
                return False
        else:
            if i == letters[-1]:
                return True

The code usually works, but I am finding that occasionally prints the wrong answer. For example, if

WordGuessed('durian', ['h', 'a', 'c', 'd', 'i', 'm', 'n', 'r', 't', 'u'])

It prints False when it should be printing True. Can anyone see where my code is wrong?

Upvotes: 2

Views: 57

Answers (2)

Azat Ibrakov
Azat Ibrakov

Reputation: 10971

@jonhopkins said it right: instead of checking that word contains all guessed letters we should check if all word's letters were guessed.

But your code can be much cleaner:

  • if you need to check if list instance is empty just use negation,

  • if we've reached else block of for-else that means that we've reached the end of iterable without returning or breaking, no need to additionally check that.

So solution can be written as

def WordGuessed(Word, letters):
    if not letters:
        return False
    else:
        for i in Word:
            if i not in letters:
                return False
        else:
            return True

Finally, since we only need to check letters appearance once, we can work with unique collections of letters like sets

def WordGuessed2(Word, letters):
    return set(Word).issubset(set(letters))

Test

>>> word = 'durian'
>>> guessed_letters = ['h', 'a', 'c', 'd', 'i', 'm', 'n', 'r', 't']
>>> WordGuessed(word, guessed_letters)
False
>>> WordGuessed2(word, guessed_letters)
False
>>> guessed_letters.append('u')
>>> WordGuessed(word, guessed_letters)
True
>>> WordGuessed2(word, guessed_letters)
True

Upvotes: 0

jonhopkins
jonhopkins

Reputation: 3842

You are returning False as soon as you find a guessed letter that is not in the word. In your example, the very first letter is not in the word.

It would work if instead you loop through Word and check each letter if it is in the array letters:

def WordGuessed(Word, letters):
    if letters == []:
        return False
    else:
        for i in Word:
            if i not in letters:
                return False
        else:
            if i == Word[-1]:
                return True

# prints True
print(WordGuessed('durian', ['h', 'a', 'c', 'd', 'i', 'm', 'n', 'r', 't', 'u']))

# prints False, missing 'u'
print(WordGuessed('durian', ['h', 'a', 'c', 'd', 'i', 'm', 'n', 'r', 't']))

Upvotes: 1

Related Questions