Reputation: 111
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!
Upvotes: 1
Views: 1228
Reputation: 180540
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")
Upvotes: 1
Reputation: 54273
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
Upvotes: 2