I wrote my very muddy (apologies) code for pyg latin (taken from Codeacademy).
It works ok, except I want to add a While True... statement so that if a user puts in a number or a blank field the input box re-appears until the condition is met
pyg='gy'
original=raw_input("please enter a word")
original_lc=original.lower()
first=original_lc[0]
rest=original_lc[1:len(original_lc)]
while True:
if len(original) >0 and original.isalpha():
print "Your word: " + original_lc
if first in "aeiou":
print "your pyglatin translation: " + original_lc + pyg
else:
print "your pyglatin translation: " + rest + first + pyg
break
else:
print "You entered a blank field or a number. Please try again."
break
I know this is incorrect. Any tips?
You can put the loop at the beginning, so that the user is asked for a new input if the first one is bad:
pyg='gy'
original=raw_input("please enter a word")
# keep asking for an input until the user inputs something valid
while len(original) == 0 or not original.isalpha():
print "You entered a blank field or a number. Please try again."
original=raw_input("please enter a word")
# at this point, the input should be valid
original_lc=original.lower()
first=original_lc[0]
rest=original_lc[1:len(original_lc)]
print "Your word: " + original_lc
if first in "aeiou":
print "your pyglatin translation: " + original_lc + pyg
else:
print "your pyglatin translation: " + rest + first + pyg
The call for raw_input should be inside your loop.
while True:
pyg='gy'
original=raw_input("please enter a word")
original_lc=original.lower()
first=original_lc[0]
rest=original_lc[1:len(original_lc)]
if len(original) >0 and original.isalpha():
print "Your word: " + original_lc
if first in "aeiou":
print "your pyglatin translation: " + original_lc + pyg
else:
print "your pyglatin translation: " + rest + first + pyg
break
else:
print "You entered a blank field or a number. Please try again."
break
Related
I am writing a python based terminal game of Hangman for a project.
Currently, the correctly guessed letters and letters remaining are displayed correctly if the player makes a correct guess or an incorrect guess.
I am having an issues displaying the letters if the player makes an invalid guess.
I have a for loop that displays the guessed letters and unguessed letters which works as expected.
However, I have an if else statement at the start of the function that determines if the user inputs a correct character.
The problem I have is that the letters are only displayed if the user makes a valid entry.
So if the user repeats a letter, inputs a number instead of a letter, or inputs multiple characters, the code to display the letters doesn’t run so the user wont be able to see their “gamescreen”.
This is the main function for the main game.
def new_game(category, difficulty):
"""
Starts a new game which takes the category and difficulty
parameters chosen by the user to generate a word from the spreadsheet.
"""
# Generate the word the player is trying to guess
random_word = random.choice(
SHEET.worksheet(difficulty + "_" + category)
.get_values().pop()).upper()
# Print the category and difficulty level chosen by the user
print(f"Category: { category.capitalize() }")
print(f"Difficulty level: { difficulty.capitalize() }")
guessed_letters = ""
wrong_guesses = 0
print_hangman(wrong_guesses)
# Print random word for testing.
print(f"your word is: {random_word}")
# Display blank letters in word for user.
print(len(random_word) * " _ " + "\n ")
# Create a loop that ends when the player loses. Break if player wins.
while wrong_guesses < 7:
player_choice = input("Please pick a letter...: \n").upper()
print(f"Category: { category.capitalize() }")
print(f"Difficulty level: { difficulty.capitalize() } \n")
print_hangman(wrong_guesses)
clear()
# Prints error message if player choice is not a letter from a-z.
if not player_choice.isalpha():
print(
f"{player_choice} is not a valid letter... " +
f"You have {7 - wrong_guesses} guess(es) remaining...")
print_hangman(wrong_guesses)
guessed_letters = guessed_letters + player_choice
wrong_letters = 0
# Prints the players guessed letters and remaining blank spaces.
for letter in random_word:
if letter in guessed_letters:
print(
f" { letter.upper() } ", end=""
)
else:
print(" _ ", end="")
wrong_letters += 1
print("")
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
# Print error message if player inputs more than one letter.
elif len(player_choice) != 1:
print(
"Please input one letter at a time..." +
f"You have {7 - wrong_guesses} guess(es) remaining...")
print_hangman(wrong_guesses)
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
# Print error message if player repeats the same letter.
elif player_choice in guessed_letters:
print(
f"{player_choice.upper()} has already been guessed..." +
f"You have {7 - wrong_guesses} guess(es) remaining...")
print_hangman(wrong_guesses)
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
# Runs if player makes a valid input.
else:
if player_choice in random_word:
print(
f"Correct, {player_choice.upper()} is in the word! " +
f"You have {7 - wrong_guesses} guess(es) remaining...")
else:
# Add 1 to the wrong_guesses variable
wrong_guesses += 1
print(
f"Sorry, {player_choice.upper()} is not in the word... " +
f"You have {7 - wrong_guesses} guess(es) remaining..."
)
print_hangman(wrong_guesses)
# Adds all letters guessed by the user
# to the guessed_letters variable.
guessed_letters = guessed_letters + player_choice
wrong_letters = 0
# Loop that displays correct letters and letters remaining.
for letter in random_word:
if letter in guessed_letters:
print(
f" { letter.upper() } ", end=""
)
else:
print(" _ ", end="")
wrong_letters += 1
print(" ")
print("\nPreviously guessed letters: \n")
print(f"{list(guessed_letters.upper())}" + "\n ")
if wrong_letters == 0:
print(
colorama.Fore.GREEN +
"Congratulations, you won! \n"
)
print(f"The word is {random_word.upper()}!\n")
sub_menu()
break
else:
print(
colorama.Fore.RED +
"\nSorry, you lose... Please try again...\n")
print(f"The word was {random_word.upper()}...\n")
sub_menu()
I’ve copied the loop into the first validity checker at line 391 to test and it does work.
I can also put the loop into the other error statements but this ends up making the code very bulky.
I’ve tried moving the loop into its own function but it is referencing other variables that are only in the new_game function.
I also tried to define an inner function but I couldn't get it to work, I had variables in the inner function that were needed in the outer function.
Any help on figuring this out would be greatly appreciated.
Also any other tips to clean up this code would be great if you notice anything ridiculous!
I have a lot of repeating print statements that I tried to avoid repeating but I couldn't get it to work the way I wanted unless I printed them out every time.
You can put the for loop in its own function and pass it the variables it needs when calling it. The function might look like this:
def display_letters(random_word, guessed_letters, wrong_letters):
for letter in random_word:
if letter in guessed_letters:
print(
f" { letter.upper() } ", end=""
)
else:
print(" _ ", end="")
wrong_letters += 1
return wrong_letters
I'm not sure about this but could you not just have the letters display after you fall out of the if statement? As in, immediately after the if statement (but not in it) just run the for loop. That might work.
Currently, I am working on a hangman program in python. I have the basics down, like displaying the blanks and detecting a correct letter, but I cannot figure out to detect when the word or sentence has been correctly identified.
EDIT
After reading the comments, I have updated my code, naming my variables using snake_case instead of camelCase and added an output to my show_word function.
def show_word(word, known_letters):
word = word.lower()
characters = ""
for i in word:
if i in known_letters:
characters = characters + i + " "
elif i == " ":
characters = characters + "/ "
else:
characters = characters + "_ "
print characters
return characters.replace(" ", "").replace("/", " ")
def guess_word(word, known_letters):
all_letters = "abcdefghijklmnopqrstuvwxyz"
word = word.lower()
guesses = 0
while show_word(word, known_letters) != word:
print("Guess a letter")
guess = raw_input()
if guess in known_letters:
print("You have already guessed %s" % (guess))
elif len(guess) != 1:
print("Only type one letter")
else:
known_letters += guess
guesses += 1
print("Well done you have guessed the word(s) (%s) in %s guesses" % (word, guesses))
guess_word("The quick brown fox jumps over the lazy dog", "")
The program now correctly identifies when I have guessed all the correct letters.
Thanks to everyone that helped.
My original code is below if anyone else needs help on this issue.
def showWord(word, knownLetters):
word = word.lower()
characters = ""
for i in word:
if i in knownLetters:
characters = characters + i + " "
elif i == " ":
characters = characters + "/ "
else:
characters = characters + "_ "
print characters
def guessWord(word, knownLetters):
word = word.lower()
guesses = 0
while showWord(word, knownLetters) != word:
print("Guess a letter")
guess = raw_input()
if guess in knownLetters:
print("You have already guessed %s" % (guess))
elif len(guess) != 1:
print("Only guess one letter")
else:
knownLetters += guess
guesses += 1
print("Well done, you guessed the word (%s) in %s guesses" % (word, guesses))
showWord(word, knownLetters)
guessWord("The quick brown fox jumps over the lazy dog", "")
Here is a template of some working code that you can hopefully use to figure out ways to modify your code.
def guessWord(word, knownLetters):
word = word.lower()
cur_word = ['_'] * len(word)
result_to_compare = ""
num_guesses = 0
while result_to_compare != word:
print("Guess a letter!")
guess = raw_input()
if guess in knownLetters:
print("You have already guessed this letter!")
else:
knownLetters += guess
for i in range(len(word)):
if guess is word[i]:
cur_word[i] = guess
print(cur_word)
result_to_compare = ''.join(cur_word)
print("Congrats! You guessed it!")
guessWord("severe", "")
I use cur_word as a temporary variable to show the progress the user is making. After a valid guess I create the string result_to_compare from the values in cur_word and compare it with the actual solution. Hope this helps. This will work with spaces between words as long as the user enters a space as the raw_input. You should be able to figure out how to modify it from here to work as your liking.
Your showWord() function returns None by default since it doesn't explicity return anything.
You should probably add return characters.replace(' ', '').replace('/', ' ') after print characters, and your end condition should be fulfilled.
You will need to adjust the output of showWord() since the letters won't exactly line up with word.
When showWord() actually returns your string of words, the following statment would equate properly:
while showWord(word, knownLetters) != word:
will then work as characters can be compared against word.
Also, it's Python convention to name your variables in snake_case rather than camelCase.
Finally, to redirect you for your bonus question, there are lots of people that have made ASCII Hangman in Python, perhaps you can reference, learn, and adopt those methods. If you have any issues with that, you can ask another question here on Stack Overflow, explicitly showing what you have tried.
Here's my version, I made the code as verbose as possible so it should be self explanatory.
def showWord(word,knownLetters):
word=word.lower()
characters=""
wordsofar=""
for char in word:
if char in knownLetters:
characters = characters + char + " "
wordsofar += char
elif char == " ":
characters = characters + "/ "
wordsofar += " "
else:
characters += "_ "
print characters
return validate(word, wordsofar)
def validate(word, knownLetters):
word_dict = {}
for c in word:
if c not in word_dict:
word_dict[c] = 1
else:
word_dict[c] += 1
for c in knownLetters:
if c not in word_dict:
return False
else:
word_dict[c] -=1
for k,v in word_dict.iteritems():
if v != 0:
return False
return True
and then for the while loop, you'll be checking if showWord(word, knownLetters) returns false.
I am trying to expand on Codeacademy's Pig Latin converter to practice basic programming concepts.
I believe I have the logic nearly right (I'm sure it's not as concise as it could be!) and now I am trying to output the converted Pig Latin sentence entered by the user on a single line.
If I print from inside the for loop it prints on new lines each time. If I print from outside it only prints the first word as it is not iterating through all the words.
Could you please advise where I am going wrong?
Many, many thanks for your help.
pyg = 'ay'
print ("Welcome to Matt's Pig Latin Converter!")
def convert(original):
while True:
if len(original) > 0 and (original.isalpha() or " " in original):
print "You entered \"%s\"." % original
split_list = original.split()
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = "".join(new_sentence)
print final_sentence
break
else:
print ("That's not a valid input. Please try again.")
return convert(raw_input("Please enter a word: "))
convert(raw_input("Please enter a word: "))
Try:
pyg = 'ay'
print ("Welcome to Matt's Pig Latin Converter!")
def convert(original):
while True:
if len(original) > 0 and (original.isalpha() or " " in original):
final_sentence = ""
print "You entered \"%s\"." % original
split_list = original.split()
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = final_sentence.append(new_sentence)
print final_sentence
break
else:
print ("That's not a valid input. Please try again.")
return convert(raw_input("Please enter a word: "))
convert(raw_input("Please enter a word: "))
It's because you are remaking final_sentence every time in the for loop instead of adding to it.
I'm not sure of the program logic but a quick solution would be appending all the final_sentence in a list, and after the for print the list with a Join.
pyg = 'ay'
print ("Welcome to Matt's Pig Latin Converter!")
def convert(original):
to_print = []
while True:
if len(original) > 0 and (original.isalpha() or " " in original):
print "You entered \"%s\"." % original
split_list = original.split()
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = "".join(new_sentence)
to_print.append(final_sentence)
print " ".join(to_print)
break
else:
print ("That's not a valid input. Please try again.")
return convert(raw_input("Please enter a word: "))
convert(raw_input("Please enter a word: "))
This code does what you want?
Your issue is here:
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = "".join(new_sentence)
print final_sentence
You are joining a single word to itself. You will want to save all the words from inside the loop, then print them once the loop are processed them all.
final = []
for word in split_list:
new_word = word[1:] + word[0] + pyg
final.append(new_word)
print ' '.join(final)
Or, just for fun, here's the one-liner:
print ' '.join([word[1:]+word[0]+'ay' for word in split_list])
EDIT: Also, #furas makes a good point in their comment, to print with no newline simply add a , to the end of the print statement:
for word in split_list:
first = word[0]
print word[1:] + first + pyg,
My hangman program is fully functioning except there is one problem, let's say the word is mathematics, I guess m, a, t, h, e - but once I guess the other m, it says I guessed it (as opposed to saying "You already guessed this letter") but it doesn't replace the _.
My Code:
def start():
import random
words = ["barbershop", "cuddle", "furious", "demolition", "centaur", "forest", "pineapple", "mathematics", "turkish"]
word = random.choice(words);
hiddenword = len(word) * "-"
used_letters = []
lives = 6
print "Welcome to Hangman! You have 6 guesses, good luck!"
while True:
print word
print "".join(hiddenword)
guess = raw_input("> ")
hiddenword = list(hiddenword)
if len(guess) > 1:
print "Error: 1 Letter Maximum"
elif len(guess) < 1:
guess = raw_input("> ")
else:
if guess.isdigit() == True:
print "Error: Hangman only accepts letters."
else:
if guess in used_letters and word.count(guess) == 1:
print "You already guessed that letter"
else:
if guess.lower() in word:
print "You got the letter " + "'" + guess + "'" + "!"
hiddenword[word.index(guess)] = guess
used_letters.append(guess)
else:
lives -= 1
print "-1 Guesses"
print "Guesses:", lives
used_letters.append(guess)
if lives == 0:
print "GAME OVER: You're out of guesses, try again!"
break
if hiddenword == word:
print "Cangratulations, you got the word!"
break
start()
P.S. - I know I have a lot of excess code e.g. if statements, please do not comment on that.
The problem appears to be with the line:
hiddenword[word.index(guess)] = guess
The string method .index(x) returns the index of the first incidence of x. So this line will persistently fill in the first "m" in mathematics.
Assuming you want the game to reveal all instances of a letter when it is guessed (e.g., show both m's in "mathematics" when you guess "m"), you can substitute this:
for i, x in enumerate(word):
if word[i] == guess:
hiddenword[i] = guess
for your line:
hiddenword[word.index(guess)] = guess
Also, to get the "Congratulations!" message to appear, you will need to change if hiddenword == word to if ''.join(hiddenword) == word, since hiddenword is a list at this point.
Removing multiple occurences of a character in a string in python is easily achieved using:
your_string.replace("m", "");
http://www.tutorialspoint.com/python/string_replace.htm
I'm working on a Python version of hangman that works off of a .txt file wordlist. For some reason, in playthroughs after the initial playthrough, the script won't show certain letters. Everything else works the way I want it to, more or less.
My code:
import random
wordlist = open("wordlist.txt").read().split()
word = random.choice(wordlist)
strikes = 0
hidden_letters = []
alphabet = "abcdefghijklmnopqrstuvwxyz"
guesses = []
def new_word():
global word
global guesses
word = random.choice(wordlist)
for letter in set(word):
if letter in alphabet:
hidden_letters.append(letter)
guesses = []
def current_progress():
for letter in word:
if letter in hidden_letters:
print '_',
elif letter == ' ':
print ' ',
else:
print letter,
print "\n"
def play_again():
global strikes
print "Would you like to play again?"
answer = raw_input("y/n: ")
if answer == "y":
strikes = 0
main()
elif answer == "n": exit(0)
else:
print "That's not a valid answer."
play_again()
def letter_in_word(x):
global strikes
global hidden_letters
if x in word:
hidden_letters.remove(x)
print "That letter is in the word."
current_progress()
if hidden_letters == []:
print "You win!"
play_again()
else:
print "You have %d strike(s)." % strikes
elif not x in word:
print "That letter is not in the word."
current_progress()
strikes = strikes + 1
print "You have %d strike(s)." % strikes
def main():
new_word()
current_progress()
global strikes
while strikes < 6 and not hidden_letters == []:
print "Guess a letter. \n Letters that have been already guessed are:", guesses
guess = raw_input("> ")
if guess in alphabet and len(guess) == 1:
if not guess in guesses:
guesses.append(guess)
letter_in_word(guess)
else:
print "You've already guessed that letter. Pick another."
current_progress()
print "You have %d strikes." % strikes
else:
print "Sorry, that's not a valid guess."
current_progress()
print "You have %d strikes." % strikes
if strikes == 6:
print "Oop! You lose."
print "The answer was:", word
play_again()
print "Welcome to Hangman!"
print "Six strikes and you lose."
print "----------"
main()
Your problem: when the player guesses a letter that exists in the current word and in a previous word, but was not guessed in the previous word (the player lost that game), the letter is still in the hidden_letters list because remove(x) only removes the first instance of that letter. In other words, your list contains two of the same letter during some executions, which violates an implied requirement of your code. You can fix this by adding hidden_letters = [] in your new_word() function before you add the new word's letters.
From the Python tutorial (emphasis mine):
list.remove(x)
Remove the first item from the list whose value is x. It is an error
if there is no such item.
Or, I think you could add the statement
del hidden_letters[:]
on the beggining of new_word(). It would clear the hidden_letters list.