1

I've been writing a program (a hangman game) today, and have come across a few snags, I know you guys don't like people just using this as answers to their homework, but I have searched quite a while, and while I have posted this program earlier in the development, I have come to new ground. I am getting to grips with lists, tuples, dictionaries, etc. and this program has been great practice. Sorry for the wall of text!

The Question:

Is there a way to refer to a string when using a list?

Context - defining a function (last line being a test to see if working)

def click_1 (text):
    key_1 = word.index [letter]
    hidden_word[key_1] = letter
    print (hidden_word)

This throws up a long error, which I wont post, here is the 'important' part in my eyes:

File "/Users/foo/Desktop/Hangman.py", line 19, in click_1
    key_1 = word.index [letter]
TypeError: 'builtin_function_or_method' object is not subscriptable

If someone could help me, that would be great. I've tried using the 'in' statement, but I have not been able to make it work - currently, though I suspect it may be part of the solution. I've tried:

key_1 = word.index [letter in word]

and:

key_1 = word.index([letter] in word)

both of which do not work.

Cheers in advance from a young programmer!

6
  • I susped word is not what you suspect it is. What is the output of type(word) just before the error? Commented Dec 24, 2014 at 18:25
  • 3
    key_1 = word.index(letter) Commented Dec 24, 2014 at 18:26
  • @ReutSharabani I don't fully understand your question, but does this: word_list = ["APPLE", "PEAR", "BANNANA"] word = word_list [random.randrange(-1,3)] hidden_word = ["_"] * len(word) Answer? Commented Dec 24, 2014 at 18:26
  • Don't understand the question either. I see you passing in text but not using it in the function. How are the other variables you do reference generated and what type are they? Commented Dec 24, 2014 at 18:33
  • It would help if you explained: 1. What type word is; 2. what type letter is; 3. exactly what you want to do with this line of code that you can't get working. It would help to show specific examples of a value for word, a value for letter, and exactly what you want key_1 to end up being in each case, showing your reasoning. The reason I say this is because as it stands, I have absolutely no idea what you're trying to ask. What do you mean by "refer to a string when using a list"? What do you mean by "using a list"? Refer to what string? Commented Dec 24, 2014 at 19:38

2 Answers 2

2

I have no idea what your function is SUPPOSED to do, but here's the issue you're having:

def click_1(text):
    key_1 = word.index [letter]
    # word.index(letter) calls the function,
    # word.index[letter] tries to treat the function like a dictionary
    # and pull up its value attached to the key `letter`
    hidden_word[key_1] = letter
    print (hidden_word)

Alternatively I'd suggest looking at a different design pattern. Try instead:

the_word = generate_random_word_from(word_list)
# which is probably as simple as random.choice(word_list)

guessed_letters = set()

def display_word():
    global the_word
    global guessed_letters
    # globals are bad in practice, but this is actually a great use case
    # for a global if you haven't wrapped this all up in OOP yet!

    masked_list = [letter if letter in guessed_letters else "_" for
                     letter in the_word]
    # this is literally:
    # # masked_list = []
    # # for letter in the_word:
    # #     if letter in guessed_letters:
    # #         masked_list.append(letter)
    # #     else:
    # #         masked_list.append("_")
    masked_word = ''.join(masked_list)
    # join the list on an empty string, e.g.:
    # ['s','_','m','e','w','_','r','d'] becomes 's_mew_rd'
    print(masked_word)
    # this wouldn't be a bad place to trigger your win condition, too.
    # Could be as simple as
    # # if "_" not in masked_word:
    # #     you_win()

def guess_letter():
    global the_word
    global guessed_letters

    guessed_letter = prompt_for_letter_somehow()
    if guessed_letter not in the_word:
        add_hangman_piece() # put another arm/leg/whatever on your dude
    guessed_letters.add(guessed_letter)
        # add that letter to the guessed_letters set anyway
    # validation would be nice here so you can't just keep guessing the same letters
Sign up to request clarification or add additional context in comments.

8 Comments

I think passing in word and guessed_letters would be a better design
@PadraicCunningham the best design would be to wrap it all in a class HangmanGame and letting it modify it that way, but passing in the same two variables every time doesn't really make sense. These really are globals, so treat them as such.
I don't agree, globals are never a good idea. It is actually pretty simple to create a game without ever needing globals
@PadraicCunningham to each their own. I avoid globals in instances where you shouldn't really be using them, but these truly are global variables. Let's call a horse a horse and define it explicitly, rather than passing the same set of arguments to every call of drive(analog_car) :)
@AdamSmith, any extension that requires different parameters passed to any function with globals in it. Say, guessing two words. This may not be evident now, but if it's needed later (when more code is already written), it's just going to be harder to re-factor. And is the alternative really complicated? OK, we can disagree.
|
1

This is a hangman game I had to make for the mitx intro to computer science a long time ago, you may find it useful and it shows how to make a game without the need for any global declaration:

from string import ascii_lowercase


def is_word_guessed(secret_word, letters_guessed):
    return all(x in letters_guessed for x in secret_word)


def get_available_letters(letters_guessed):
    return "".join([x for x in ascii_lowercase if x not in letters_guessed])


def get_guessed_word(secret_word, letters_guessed):
    return "".join([letter if letter in letters_guessed else "_" for letter in secret_word])


def hangman(secret_word):
    print "Welcome to the game Hangman!"
    print "I am thinking of a word that is {} letters long\n-----------".format(len(secret_word))
    guesses = 8
    letters_guessed = []
    missed_l = ''
    correct_l = ''
    while True:
        if is_word_guessed(secret_word, letters_guessed):
            print "Congratulations, you won!"
            break
        elif len(missed_l) == 8:
            print "Sorry, you ran out of guesses. The word was {}.".format(secret_word)
            break
        print "You have {} guesses left".format(guesses)
        print "Available Letters: {}".format(get_available_letters(letters_guessed))
        l = raw_input("Please guess a letter: ").lower()
        if l in letters_guessed:
            print "Oops! You've already guessed that letter: {}\n-----------".format(
                get_guessed_word(secret_word, letters_guessed))
        elif l in secret_word:
            letters_guessed.append(l)
            get_guessed_word(secret_word, letters_guessed)
            correct_l += l
            print( "Good guess: {}\n-----------".format(
                "".join([x if x in letters_guessed else "_" for x in secret_word])))
        elif l not in secret_word:
            letters_guessed.append(l)
            guesses -= 1
            print "Oops! That letter is not in my word: {}\n-----------".format(
                get_guessed_word(secret_word, letters_guessed))
            missed_l += l

hangman("foobar")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.