Selecting random word with length-criterion. How to decompose? - python

This is plan of my game I finished(it works). I want to at the beginning add a difficulty level. Easy is six letter word, medium is seven, and hard is eight or more. Where would it go?
Letters = set(string.ascii_lowercase)
def main():
words = [line.strip() for line in open("E:\wordlist.txt")]
correct_word = random.choice(words).strip().upper()
letters = list(correct_word)
random.shuffle(letters)
word = ""
for i in range (len(letters)):
word += letters[i]
print("Welcome to my game, solve the puzzle.")
print("Lets play")

(In general you will find http://codereview.stackexchange.com more suitable than SO for how-do-I-implement or refactor questions on incomplete code.)
Ok, you first want to prompt user for the difficulty level, convert that to corresponding wordlength, wordlength, then use those in your word-selecting-and-shuffling code.
This could all do with a little refactoring, and since you need to pass some data around, I refactored into a class with setup(),play() methods.
Also you only want to read in your wordlist once (e.g. in the class __init__() method), not every game.
Note the use of the tuple assignment from dict level_to_wordlength, and the
compact while-loop idiom in choose_random_word()
import random
import string
class Hangman(object):
def __init__(self, wordlist = 'wordlist.txt'):
self.words = [word.strip() for word in open(wordlist)] # store them uppercase
#self.level = None
#self.min_wordlength = None
#self.max_wordlength = None
self.correct_word = None
self.letters_unused = None
def select_difficulty(self):
while True:
level = raw_input("Choose difficulty: E(asy) M(edium) H(ard) : ")
level = (level or " ")[0].upper()
if level in 'EMH':
return level
print "Error: bad level"
# or store it in self.level if needed
def choose_random_word(self, min_wordlength, max_wordlength):
word = ''
while not( min_wordlength <= len(word) <= max_wordlength ): # note the idiom
word = random.choice(self.words)
self.correct_word = word
def setup(self):
level = self.select_difficulty() # or store it in self.level if needed
# Convert level to wordlength constraints... we could use an if..elif ladder for simplicity,
# but here's a neat idiomatic method using tuple assignment from a dict.
level_to_wordlength = {'E': (6,6), 'M': (7,7), 'H': (8,999)}
min_wordlength, max_wordlength = level_to_wordlength[level]
self.choose_random_word(min_wordlength, max_wordlength)
self.letters_unused = set(string.ascii_uppercase)
def play(self):
letters = list(self.correct_word)
random.shuffle(letters)
word = ''.join(letters)
print("Welcome to my game, solve the puzzle.")
print("Let's play")
# ... you do the rest ...
if __name__ == '__main__':
game = Hangman()
game.setup()
game.play()

Related

Solving a Positional Argument Error in a Pythonic Class and Method

Disclaimer
To preface this, I am new to programming and even newer to python, so my knowledge of the mechanics of the interpreter is very limited.
Explanation I am currently writing a pythonic code that simulates a text-based game of cheating hangman, which means the program changes the word to evade the player from guessing the correct word using "word families." The game requires three files: hangman.py, play_hangman.py, and dictionary.txt. In hangman.py, I have created a hangman class that contains the self-instance of the class, several methods for producing the necessary objects, and a play method that uses these methods. Then, in play_hangman.py, it calls the hangman instance, and the play method, and puts the play method into a while loop that repeats as long as the player enters "yes" to keep playing.
The Problem I have called the methods into the play function for executing the game. However, it gives me an error saying:
- "12 positional arguments: 'word_length', 'num_guesses',
'remaining_words', 'remainingWords', 'letters_already_guessed',
'askForWordLength', 'printGameStats', 'askForPlayerGuess',
'wordStatus', 'printCountOfRemainingWords', 'retreiveRemainingWords',
and 'askForNumberOfGuesses' "
These are the twelve variables and methods I have called in the def play(): function. I have researched that I need to call an object of the class before the method, which I attempted to do, but does not work. I am not sure how to avoid the error.
HANGMAN.PY
import re
class Hangman:
# hangman self method
def hangman(self):
self.hangman = Hangman() # object of the Hangman class
def words(self):
with open('dictionary.txt') as file: # opens dictionary text file
file_lines = file.read().splitlines() # reads and splits each line
all_words = [] # empty list to contain all words
valid_words = [] # empty list to contain all valid words
for word in file_lines: # traverses all words in the file lines
if len(word) >= 3: # accepts word if it has at least 3 letters
all_words.append(word) # appends accepted word to list
# list of all invalid characters in python
CHARACTERS = ["~", "`", "!", "#", "#", "$", "%", "^", "&", "*", "(",
")", "-", "_", "=", "+", "[", "]", "{", "}", "|", "\","
"", "'", "?", "/", ">", ".", "<", ",", "", ";", ":"]
for i in CHARACTERS: # traverse list of invalids
for word in all_words:
if i not in word: # if invalid character is not in word
valid_words.append(word) # accept and append to list
return valid_words # return list of valid words
def askForWordLength(self, valid_words):
word_lengths = [] # empty list for possible word lengths
for word in valid_words: # traverse list of valid words
length = word.__len__() # record length of current word
if (length not in word_lengths):
word_lengths.append(length) # accept and append to list
word_lengths.sort()
# inform user of possible word lengths
print('The available word lengths are: ' + str(word_lengths[0]) + '-'
+ str(word_lengths[-1]))
print()
# have user choose from possible word lengths
while(1):
try:
length = int(input('Please enter the word length you want: '))
if (length in word_lengths):
return length
except ValueError:
print('Your input is invalid!. Please use a valid input!')
print()
def askForNumberOfGuesses(self):
while(1):
try:
num_guesses = int(input('Enter number of guesses you want: '))
if (num_guesses >= 3):
return num_guesses
except ValueError:
print('Your input is invalid!. Please use a valid input!')
print()
def wordStatus(self, length):
status = '-'
for i in range(0, length):
status += '-'
return
def remainingWords(self, lines, length):
words = []
for word in lines:
if (word.__len__() == length):
words.append(word)
return words
def printGameStats(self, letters_guessed, status, num_guesses):
print('Game Status: ' + str(status))
print()
print('Attempted Guesses' + str(letters_guessed))
print('Remaining Guesses' + str(num_guesses))
def askPlayerForGuess(self, letters_guessed):
letter = str(input('Guess a letter: ')).lower()
pattern = re.compile("^[a-z]{1}$")
invalid_guess = letter in letters_guessed or re.match(pattern, letter) == None
if (invalid_guess):
while (1):
print()
if (re.match(pattern, letter) == None):
print('Invalid guess. Please enter a correct character!')
if (letter in letters_guessed):
print('\nYou already guessed that letter' + letter)
letter = str(input('Please guess a letter: '))
valid_guess = letter not in letters_guessed and re.match(pattern, letter) != None
if (valid_guess):
return letter
return letter
def retrieveWordStatus(self, word_family, letters_already_guessed):
status = ''
for letter in word_family:
if (letter in letters_already_guessed):
status += letter
else:
status += '-'
return status
def retrieveRemainingWords(self, guess, num_guesses, remaining_words,
wordStatus, guesses_num, word_length,
createWordFamiliesDict,
findHighestCountWordFamily,
generateListOfWords):
word_families = createWordFamiliesDict(remaining_words, guess)
family_return = wordStatus(word_length)
avoid_guess = num_guesses == 0 and family_return in word_families
if (avoid_guess):
family_return = wordStatus(word_length)
else:
family_return = findHighestCountWordFamily(word_families)
words = generateListOfWords(remaining_words, guess, family_return)
return words
def createWordFamiliesDict(self, remainingWords, guess):
wordFamilies = dict()
for word in remainingWords:
status = ''
for letter in word:
if (letter == guess):
status += guess
else:
status += '-'
if (status not in wordFamilies):
wordFamilies[status] = 1
else:
wordFamilies[status] = wordFamilies[status] + 1
return wordFamilies
def generateListOfWords(self, remainingWords, guess, familyToReturn):
words = []
for word in remainingWords:
word_family = ''
for letter in word:
if (letter == guess):
word_family += guess
else:
word_family += '-'
if (word_family == familyToReturn):
words.append(word)
return words
def findHighestCountWordFamily(self, wordFamilies):
familyToReturn = ''
maxCount = 0
for word_family in wordFamilies:
if wordFamilies[word_family] > maxCount:
maxCount = wordFamilies[word_family]
familyToReturn = word_family
return familyToReturn
def printCountOfRemainingWords(self, remainingWords):
show_remain_words = str(input('Want to view the remaining words?: '))
if (show_remain_words == 'yes'):
print('Remaining words: ' + str(len(remainingWords)))
else:
print()
def play(self, askForWordLength, askForNumberOfGuesses, remainingWords,
words, wordStatus, printCountOfRemainingWords, printGameStats,
askPlayerForGuess, retrieveRemainingWords):
MODE = 1
openSession = 1
while (openSession == 1):
word_length = askForWordLength(words)
num_guesses = askForNumberOfGuesses()
wordStatus = wordStatus(word_length)
letters_already_guessed = []
print()
game_over = 0
while (game_over == 0):
if (MODE == 1):
printCountOfRemainingWords(remainingWords)
printGameStats(remainingWords, letters_already_guessed,
num_guesses, wordStatus)
guess = askPlayerForGuess(letters_already_guessed)
letters_already_guessed.append(guess)
num_guesses -= 1
remainingWords = retrieveRemainingWords(guess, remainingWords,
num_guesses, word_length)
wordStatus = wordStatus(remainingWords[0], letters_already_guessed)
print()
if (guess in wordStatus):
num_guesses += 1
if ('-' not in wordStatus):
game_over = 1
print('Congratulations! You won!')
print('Your word was: ' + wordStatus)
if (num_guesses == 0 and game_over == 0):
game_over = 1
print('Haha! You Lose')
print('Your word was: ' + remainingWords[0])
print('Thanks for playing Hangman!')
Self as First Parameter
When creating functions inside classes, the first parameter should be 'self', as you've done in the function askForNumberOfGuesses. This happens because, when calling functions from an object, Python passes the object to 'self' so the method's logic can access its data.
When calling functions such as "play" (in which you haven't used the self parameter in the declaration), the first parameter will be handled as the self, even though it has a different name. So, actually, your code expects the variable 'words' to be a Hangman object.
Static Functions
If the function needs to know information about the object, you need to add the 'self' as the first parameter.
However, if your method does not use any data declared inside the Hangman class (such as self.hangman that you've created inside init) you can just add a "#staticmethod" to the line before the function definition. This way, Python will know that you don't need self and that the first parameter is not the object.
Notice that, if you want to use a static method, you can use the class itself to call the method. You don't even need to create an object:
Hangman.static_function_name(function_parameters) # calls static function
hangman_object = Hangman()
hangman_object.non_static_function_name(function_parameters) # calls non-static function
hangman_object.static_function_name(function_parameters) # calls static function using object (there is no problem)
Design Considerations
Also, I believe you should change your init implementation and use 'self' to store data that you use in more than one function, instead of passing arguments to all the functions and returning them.
Also note that, in order to create a Hangman object, you need to use ():
self.hangman = Hangman # reference to the Hangman class
self.hangman = Hangman() # Object of the Hangman class
However, if you create a Hangman object inside init, it will call init again and this will go on "forever". So, you shouldn't create a Hangman object inside it's init method. I believe you should create the Hangman object in play_hangman.py file and call the play method from there.
In my opinion, init should create all the data you need as self.<var_name>, load should prepare words or whatever you need using self.<functions_you_create> and play should just start the game. play_hangman.py shouldn't need to know all these parameters.
hangman.py
class GameClass:
def __init__(self):
self.words = list()
# TODO: Implement adding other game data
def load(self):
# TODO: Implement logic
self.words.append('country')
pass
def play(self):
# TODO: Implement loop logic
print(self.words)
# while(True):
# break
pass
play_hangman.py
game = GameClass()
game.load()
game.play()
IDE
Use a good IDE so it will remember you to add self if you are not used yet.
None of those methods have self as their first argument.
And that is what is used to define class methods and give access to attributes.
So, adding that "self" keyword is the first step to make your code work.
I would recommend installing a linter, it automatically identifies this kind of error for you:

First input not inserting into List

I am writing a program to accept user input to build a sentence word-by-word. After the user is done it is supposed to display the the sentence and the amount of words in the list. I know my code isn't complete and I am only requesting help for one issue. As of the moment I cannot get the first input to append or insert into the list, while others are. Any help would be great. I have been searching for awhile with no progress.
Code:
index = 0
def main():
wordList = []
inputFunc(wordList = [])
def inputFunc(wordList = []):
global index
print("To make a sentence, enter one word at a time... ")
wordInput = input("Enter word... : ")
wordList.insert(index,wordInput)
index += 1
choice = input("(y = Yes, n = No, r = Reset List)Another word?: " )
inputCalc(choice)
completeList(wordList)
def inputCalc(choice):
while choice == 'y':
inputFunc()
while choice == 'n':
return
while choice == 'r':
clearList()
def completeList(wordList):
print(wordList)
exit()
def clearList():
wordList.clear()
main()
main()
There's lots of issues with your code, but the main reason why your word is not being appended to your list is because mutable default arguments don't generally do what you want.
Instead just perform everything in a single function.
def main():
inputFunc()
def inputFunc():
running = True
wordList = []
while running:
print("To make a sentence, enter one word at a time... ")
wordInput = input("Enter word... : ")
wordList.append(wordInput)
while True:
choice = input("(y = Yes, n = No, r = Reset List)Another word?: " )
if choice == 'y':
break
elif choice == 'n':
running = False
break
elif choice == 'r':
wordList = []
break
print(wordList)
if __name__ == "__main__":
main()
The detailed answer is The first time you call inputFunc() inside main() you pass an empty list:
def main():
wordList = []
inputFunc(wordList=[])
When you call it again via recursion inside inputCalc(choice) you call inputFunc() without passing any arguments thus using a different list, the pre-initialized list.
def inputCalc(choice):
while choice == 'y':
inputFunc()

How would I write a program that can call a variable from another def?

So I set out to make a simple game of hangman and everything worked fine, the whole code worked but it lacked the ability to allow the user to replay when the game is over. Thus I set out to put all the code I have written in various functions. So that I can call the functions when they are required (I thought it was the most logical way to allow replay-ability). Various problems followed but one stood out.
The main culprit (I think) is that I could not successfully get a value to update globally. I've read similar questions on the site but could not successfully adapt it to my case. I have a sample code to show what exactly I mean:
def GameMode():
choice = input('Play alone or play with friends? A F : ')
choice = choice.upper()
if choice == 'A':
wordslotmachine = ['stand','emerald','splash']
word = random.choice(wordslotmachine)
word = word.upper()
Rules()
elif choice == 'F':
word = input('Enter your word for your friends to guess: ')
word = word.upper()
Rules()
else:
choice = input('Please enter A or F: ')
choice = choice.upper()
I would need the program to remember what the value of "word" is and use this word in another method (this method is ran by another method showed below "Rules()"):
def MainGame():
guesses = ''
turns = 10
underscore = 0
seconds = 1
checker = 0
cheaterchance = 5
while turns > 0: #check if the turns are more than zero
for char in word: # for every character in secret_word
if char in guesses: # see if the character is in the players guess
print(char+' ', end='')
else:
print('_ ', end='')# if not found, print a dash
underscore += 1
if underscore == 0:
print(': You got it!')
Wait()
NewGame()
break
#A block of if's to check for cheating
if guess not in word:
print('Your guesses so far: '+guesses)
turns -= 1
if turns == 0:
break
else:
print('')
print('Try again. You have',turns,'more guesses')
print('Delayed chance to answer by',seconds,'seconds')
counter = 1
print(0,'.. ', end='')
while counter < seconds:
time.sleep(1)
print(counter,'.. ', end='')
counter += 1
if counter == seconds:
time.sleep(1)
print(counter,'.. done!', end='')
print('')
print('')
seconds += 1
underscore = 0
else:
print('Your guesses so far: '+guesses)
underscore = 0
#The else portion of the code to check for cheating
I have tried defining "word" outside of the function. Doing this doesn't fix the problem, GameMode() will not successfully update the value of "word". And whatever the value of "word" defined outside of the function will be called and used by MainGame(). However doing this shows another problem.
That being, the code that previously worked (it successfully read the input and correctly updated the game status) now does not work. Even if the correct letter is entered by the user, the program reads the input as incorrect.
These are the two problems I have faced so far and have yet to find a way to overcome them.
Note: I have successfully created a way to make the game replay-able by putting the entire original code (without the functions) inside a while loop. However I would still very much like to know how I can get the code to work using functions.
Edit: This is the function for Rules():
def Rules():
#Bunch of prints to explain the rules
MainGame()
print('Start guessing...')
Wait() is just a delay function with a countdown.
Global vs. Local variables.
You can reference and use a global variable from within a function, but you cannot change it.
It's bad practice, but you CAN declare a variable within your function to be global and then changes to it inside your function will apply to the variable of the same name globally.
HOWEVER, what I suggest is to return the word at the end of your function.
def whatever_function(thisword):
do some stuff
return word
new_word = whatever_function(thisword)
Functions can, and usually should, return values. Make GameMode() return the word to the caller;
def GameMode():
choice = input('Play alone or play with friends? A F : ')
choice = choice.upper()
if choice == 'A':
wordslotmachine = ['stand','emerald','splash']
word = random.choice(wordslotmachine)
word = word.upper()
Rules() #ignore this
elif choice == 'F':
word = input('Enter your word for your friends to guess: ')
word = word.upper()
Rules() #ignore this
else:
choice = input('Please enter A or F: ')
choice = choice.upper()
return word
From the main call GameMode and save the word;
def MainGame():
guesses = ''
turns = 10
underscore = 0
seconds = 1
checker = 0
cheaterchance = 5
word = GameMode() # add this here
You almost certainly want to use a class with instance variables
Contrived example:
class Hangman:
def __init__(self):
print("Starting hangman")
def mode(self):
# ...
self.word = 'whatever'
def play(self):
print("Look i have access to word", self.word)
if __name__ == '__main__':
hm = Hangman()
hm.mode()
hm.play() # may be what you want to put in a while loop
To access a global variable from inside a function, you have to tell python that it is global:
my_global_var = 1
def some_func():
global my_global_var
You have to use global keyword in every method that the global variable is being used or python will think you are defining/ using a local variable
Having said that, you should avoid globals as a coding practise.
global word #probably define this after imports.
def GameMode():
global word #add this
choice = input('Play alone or play with friends? A F : ')
choice = choice.upper()
if choice == 'A':
wordslotmachine = ['stand','emerald','splash']
word = random.choice(wordslotmachine)
word = word.upper()
Rules() #ignore this
elif choice == 'F':
word = input('Enter your word for your friends to guess: ')
word = word.upper()
Rules() #ignore this
else:
choice = input('Please enter A or F: ')
choice = choice.upper()
def MainGame():
guesses = ''
turns = 10
underscore = 0
seconds = 1
checker = 0
cheaterchance = 5
global word # add this here
use the code
global word
above the def or let the def return the value of word so it is stored in a variable outside the def

Python - Word Scramble Game

While this assignment is past due (I joined the class late unfortunately) I still need to figure it out. I have the following list of words:
abhor:hate
bigot:narrow-minded, prejudiced person
counterfeit:fake; false
enfranchise:give voting rights
hamper:hinder; obstruct
kindle:to start a fire
noxious:harmful; poisonous; lethal
placid:calm; peaceful
remuneration:payment for work done
talisman:lucky charm
abrasive:rough; coarse; harsh
bilk:cheat; defraud
I need to read this file into a dictionary, pick a random key, scramble it, then ask the user to solve it. Unlike other solutions on here, it does not iterate three times, but runs until the user enters 'n'. The code will ask the user after each round if the user wants to continue the game. The user can also type 'hint' to get the definition of the word.
There is a similar question here: (http://www.dreamincode.net/forums/topic/302146-python-school-project-write-a-word-scramble-game-status-complete/) or rather the result of a question, but I am not knowledgeable enough to bridge the gaps and make it work for my purposes. None of the variation on this that I have seen on stack overflow come close enough for me to bridge the gap either, likely because I just don't know enough yet. Before we even start, this code does not yet work at all really, I am pretty lost at this point, so please be gentle. My code so far is below:
import random
from random import shuffle
#Reads the words.txt file into a dictionary with keys and definitions
myfile = open("words.txt", "r")
wordDict = dict([(line[:line.index(":")], line[line.index(":") +1 : -1])
for line in myfile.readlines()])
#print (b)
def intro():
print('Welcome to the scramble game\n')
print('I will show you a scrambled word, and you will have to guess the word\n')
print('If you need a hint, type "Hint"\n')
#Picks a random key from the dictionary b
def shuffle_word():
wordKey = random.choice(list(wordDict.keys()))
return wordKey
#Gives a hint to the user
def giveHint(wordKey):
hint = wordDict[wordKey]
return hint
#Below - Retrieves answer from user, rejects it if the answer is not alpha
def getAnswer():
answer = input('\nEnter your first guess: ')
while True:
if answer.isalpha():
return answer
else:
answer = input('\nPlease enter a letter: ')
def keepPlaying():
iContinue = input("\nWould you like to continue? ")
return iContinue
def scramble():
theList = list(shuffle_word())
random.shuffle(theList)
return(''.join(theList))
#Main Program
if keepPlaying() == 'y':
intro()
shuffle_word()
randomW = shuffle_word()
#scramKey = list(randomW)
thisWord = scramble()
print ("\nThe scrambled word is " +thisWord)
solution = getAnswer()
if solution == thisWord:
print("\nCongratulations")
if solution == 'Hint' or solution == 'hint':
myHint = giveHint(wordKey)
print(myHint)
else:
print("\nThanks for playing")
I have edited this post to ask for new information, though I am not sure if that ishow its properly done. Thanks to the help of those below, I have made progress, but am stuck not on a specific piece.
I have two questions. 1: How can I get the giveHint() function to return the definition of the random key selected by the shuffle_wprd() function. I know what I have above will not work because it is simply returning a string, but it seems like just using a dict.get() function would not get the correct definition for the random word chosen.
2: How can I get the program not to ask the user to continue on the first pass, but to then ask from then on. I thought about using a while loop and redefining the variable during the iteration, but I don't know enough to get it to work properly.
regardless, thank you to those people who have already helped me.
This should help you out a bit, the length seems to be of no benefit as a hint as you can see the length of the scrambled word so I used the definition as the hint,I think you also want to ask the user to guess the word not individual letters:
from random import shuffle, choice
#Reads the words.txt file into a dictionary with keys and definitions
with open("words.txt") as f:
word_dict = {}
for line in f:
# split into two parts, word and description
word, hint = line.split(":")
word_dict[word] = hint
def intro():
print('Welcome to the scramble game\n')
print('I will show you a scrambled word, and you will have to guess the word\n')
#Picks a random key from the dictionary b
def pick_word():
word = choice(list(word_dict.keys()))
return word
#Gives a hint to the user
def give_hint(word):
# return the definition of the word
descrip = word_dict[word]
return descrip
#Below - Retrieves answer from user, rejects it if the answer is not alpha
def get_answer():
while True:
answer = input('Please enter a guess: ')
if answer.isalpha():
return answer
else:
print("Only letters in the word")
def main():
intro()
word = pick_word()
# give user lives/tries
tries = 3
shffled_word = list(word)
# shuffle the word
shuffle(shffled_word)
# rejoin shuffled word
shffled_word = "".join(shffled_word)
# keep going for three tries as most
while tries > 0:
inp = input("Your scrambled word is {}\nEnter h if you want to see your hint or any key to continue".format(shffled_word))
if inp == "h":
print("The word definition is {}".format(give_hint(word)))
ans = get_answer()
if ans == word:
print("Congratulations you win!")
break
tries -= 1
# ask user if they want to play again, restarting main if they do
play_again = input("Press 'y' to play again or any key to exit")
if play_again == "y":
main()
# else the user did not press y so say goodbye
print("Goodbye")
main()
There are a few more bits to be added but I will leave that up to you.
Thank you to all those who helped. For any who come along later, the final product is here. Similar to what Padraic Cunningham put, but without the three answer limit, and without his more elegant solution of wrapping the main program into a called function.
import random
from random import shuffle, choice
#Reads the words.txt file into a dictionary with keys and definitions
with open("words.txt") as f:
wordDict = {}
for line in f:
# split into two parts, word and description
word, hint = line.split(":")
wordDict[word] = hint
#print (b)
def intro():
print('Welcome to the scramble game\n')
print('I will show you a scrambled word, and you will have to guess the word\n')
print('If you need a hint, type "Hint"\n')
#Picks a random key from the dictionary b
def shuffle_word():
wordKey = choice(list(wordDict.keys()))
return wordKey
#Gives a hint to the user
def giveHint(wordKey):
descrip = wordDict[word]
return descrip
#Below - Retrieves answer from user, rejects it if the answer is not alpha
def getAnswer():
answer = input('\nEnter a guess: ')
while True:
if answer.isalpha():
return answer
else:
answer = input('\nPlease enter a letter: ')
def getAnswer2():
answer2 = input('\nEnter another guess: ')
while True:
if answer2.isalpha():
return answer2
else:
answer2 = input('\nPlease enter a letter: ')
def keepPlaying():
iContinue = input("\nWould you like to continue? ")
return iContinue
#def scramble():
# theList = list(shuffle_word())
# random.shuffle(theList)
# return(''.join(theList))
#Main Program
while keepPlaying() == 'y':
intro()
#shuffle_word()
randomW = shuffle_word()
cheatCode = giveHint(randomW)
#scramKey = list(randomW)
thisWord = list(randomW)
print(thisWord)
random.shuffle(thisWord)
print(thisWord)
thisRWord = ''.join(thisWord)
print ("\nThe scrambled word is " +thisRWord)
solution = getAnswer()
loopMe = False
while loopMe == False:
if solution == randomW:
print("\nCongratulations")
loopMe = True
if solution == 'Hint' or solution == 'hint':
print(cheatCode)
if solution != randomW:
loopMe = False
solution = getAnswer2()

simple text based hangman in python

I'm working on a simple text based hangman game in python. I have a rough program running but I've encountered two minor problems:
Why does the welcome message print twice?
When the user inputs a letter not in the word two times in a row, the second time, the "nope, try again"-message does not display and current word does not display. The first time an incorrect letter is input, it works. Why doesn't it work the second time?
from random import randrange
class HangmanApp:
def __init__(self, interface):
self.infile = open("hangman.txt", "r")
self.interface = textInterface()
for line in self.infile:
self.wordlist = line.split()
self.secretword = self.wordlist[randrange(len(self.wordlist))]
self.letter_list = list(self.secretword)
#tests the user's guess
def guess(self):
self.new_list = ["_"]*len(self.secretword)
#keep loop going as long as there are letters in the list
while self.letter_list != ["_"]*len(self.letter_list):
self.guess = self.interface.guess()
if self.guess in self.letter_list:
while self.guess in self.letter_list:
i = self.letter_list.index(self.guess)
#replace that letter from the list with "_"
self.letter_list[self.letter_list.index(self.guess)] = "_"
#add the chosen letter to a new list for display
self.new_list[i] = self.guess
#print list with letter added
self.interface.correct(self.new_list)
else:
self.interface.incorrect(self.new_list)
self.guess = self.interface.guess()
class textInterface:
def __init__(self):
print("Welcome to Hangman!")
def guess(self):
guess = input("Guess a letter! ")
return guess
def display (self, word):
string = ' '.join(word)
print(string)
def incorrect(self, word):
print("Nope, try again")
self.display(word)
def correct(self, word):
print("Correct")
self.display(word)
def main():
inter = textInterface()
app = HangmanApp(inter)
app.guess()
The welcome message is printed twice because you're creating two instances of textInterface: one in main() and another inside HangmanApp.__init__(). I think you meant to do:
self.interface = interface
instead of
self.interface = textInterface()
Inside HangmanApp.guess(), after receiving an incorrect guess (reaching the else: clause) you have an extra guess prompt that is not needed---one that doesn't pass through your checking code. I think this is probably causing the issue with it not working the second time around.

Categories

Resources