Changing loop conditions to repurpose a number guessing game - python

I am a new programmer with experience with Visual Basic for Applications and have recently changed to python.
I'm working on a number guessing game and so far progress has been great. The user enters 4 digits into the program. The program also generates a 4 digit number and the program returns Ys or Ns to show whether any digits are correct or not. EG 1357 as a user guess and 1358 as the programs number shows YYYN as output.
I'm trying to rework the program to make it simpler for users by showing H or L to suggest that they need to guess higher or lower IF the digit guessed is incorrect. If it's correct, then a Y should be shown as per normal. I am aware that it's a condition in the loop I need to change or another loop I need to add but I am struggling to see where to add this and how to write it. Does anybody have a solution for this?
Here is part of my code for the section of the program which returns the result for the guesses.
lives = 10
while lives > 0:
number = input("Enter your guess: ")
letter = ''
for i in range(len(numToGuess)):
letter += 'Y' if int(number[i]) == numToGuess[i] else 'N'
if letter == 'Y' * len(numToGuess):
print("Good job!")
break
print(letter)
lives -= 1
else:
print("Game over! You used up all of your tries.")
Does anybody have a solution for this?

I prefer to use lists for this. Meaning, I'd convert both the correct answer and the user guess into separate digits saves in two lists and then compare them.
Let's say the correct answer is '1234':
lives = 10
correct_answer = 1234
correct_answer = [int(char) for char in str(correct_answer)]
while lives > 0:
letter = ''
number = input("Enter your guess: ")
number = [int(char) for char in str(number)]
if number == correct_answer:
print("Correct!")
break
for i in range(len(correct_answer)):
if correct_answer[i] == number[i]:
letter += 'Y'
elif correct_answer[i] > number[i]:
letter += 'H'
else:
letter += 'L'
print("Your guess is wrong: ", letter)
lives -= 1
print("Game over!")
Now for example:
Enter your guess: 1111
Your guess is wrong: YHHH
Enter your guess: 1235
Your guess is wrong: YYYL
Enter your guess: 1234
Correct!
Game over!
>>>

You can use zip function for compare the letters :
>>> a='1357'
>>> b='1358'
>>> l=[]
>>> for i,j in zip(a,b):
... if i==j :l.append('Y')
... else :l.append('N')
...
>>> ''.join(l)
'YYYN'
And for check the answer you can use a generator expression within all :
>>> all(i=='Y' for i in l)
False

You don't need to change your loop condition. Just change the logic of your if expression.
letter = ''
for i in range(len(numToGuess)):
if int(number[i]) == numToGuess[i]:
letter += 'Y'
elif int(number[i]) > numToGuess[i]:
letter += 'H'
else:
letter += 'L'
Or, in one line:
letter = ''
for i in range(len(numToGuess)):
letter += 'Y' if int(number[i]) == numToGuess[i] else ('H' if int(number[i]) > numToGuess[i] else 'L')

Related

Python: How do I get an if statement to check if a condition is true at the end of a for loop?

Specifically, I'm doing the hangman challenge from the 100 days of coding by UDEMY. I can't seem to figure out how to check if the user has lost by reaching "0" of "6" lives. When I use this code, it subtracts 1 from "lives" during every instance in the for loop that doesn't match the guess:
lives = 6
while not end_of_game:
guess = input("Guess a letter: ").lower()
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
elif letter != guess:
lives -= 1
if lives == 0:
end_of_game = True
print(f"{' '.join(display)}")
I just did some bench checking of your code. After straightening out the indentation, the main problem I spot in your code is that even if a guessed letter is found and you update the display position, your "for" loop keeps checking the guessed letter against the remaining letters in your word. And that then decrements the life count even when there is a good guess.
I would think that you would want your code to more closely resemble the following code snippet:
lives = 6
while not end_of_game:
guess = input("Guess a letter: ").lower()
found_letter = False # Additional test variable
for position in range(word_length):
letter = chosen_word[position]
if letter == guess:
display[position] = letter
found_letter = True
if found_letter == False: # Do the test for good/bad guess here
lives -= 1
if lives == 0:
end_of_game = True
break
print(f"{' '.join(display)}")
The additional true/false variable "found_letter" would dictate whether or not the life count should be decremented and the test would occur once the whole word has been checked for the guessed letter.
Give that a try.

How do I convert the letter entered to lowercase in python? My code does not seem to work

I have created a hangman type game and it all works apart from if the user enters a capital letter it does not register it. The game should be case insensitive. This is the code I have tried for that part of the game.
def game():
total = len(''.join(set(myword)))
wrong_guess = 0
correct_letters = 0
while wrong_guess <= 7:
print_output()
letter = input("Guess:")
if len(letter) >= 1:
if letter.isalpha():
if letter.lower() in myword:
correct_letters += 1
for i,x in enumerate(myword):
if x is letter.lower():
output[i] = letter
else:
wrong_guess += 1
else:
print("Invalid input, please enter a guess")
else:
print("Invalid input, please enter a guess")
python has a built in function called string.lower()
do this
letter = input("Guess: ").lower()
The following code is not the proper way to compare strings or characters:
if x is letter.lower():
The is operator compares whether two instances are the same or not, it does not compare equality. You want to use the equality operator, ==:
if x == letter.lower():

Why doesnt my Code work? (Simple "Guess the Word"-Game in Python) [duplicate]

This question already has an answer here:
Python "if" statement not working
(1 answer)
Closed 4 years ago.
I'm learning Python for fun at the moment, and it went all well until now. I'm trying to extend the "Guess the Word"-Game, for example being able to let the Player choose a Word by himself (when 2 People play, 1 chooses the Word, the other guesses) I bet that my Mistake is obvious to me as soon as you point it out, but I'm gonna ask anyway. Well, here is the Code. I put in the entire Program, even tough only the top part should matter. I just put in the rest because it isn't much and maybe you guys can understand it better then.
print("Do you wish to set the Word yourself, or let the program choose?")
user_input = input("1 for own Input - 0 for Program-Input")
if user_input == 1:
Keyword = input("Type in the Word you want to use!")
else:
Keyword = "castle"
word = list(Keyword)
length = len(word)
right = list ("_" * length)
used_letters = list()
finished = False
while finished == False:
guess = input("Guess a Letter!")
if guess not in Keyword:
print("This letter is not in the word. Sorry...")
for letter in word:
if letter == guess:
index = word.index(guess)
right[index] = guess
word[index] = "_"
if guess in used_letters[0:100]:
print("You already used that letter before!")
else:
used_letters.append(guess)
list.sort(used_letters)
print(right)
print("Used letters:")
print(used_letters)
if list(Keyword) == right:
print("You win!")
finished = True
input('Press ENTER to exit')
My problem is, I wanna add the Function to be able to choose if you want to set a Word yourself, or use the word the Program has, defined as "Keyword". But no matter what I input, it always starts with "Guess a Letter" instead of skipping down to where the program sets the Keyword. Thank you in advance for your answers! :)
There's 2 issues with your code.
You put the entire block of code into the else statement. This means that if the if user_input == 1: block ever executed, you would only ask your user for a word and then the program would end because the else statement would be skipped.
You are using if user_input == 1: as your check and this will never be true because user inputs are always read in as strings. A string 1 will never equal the integer 1. This is why your program always skips to the else statement. You need to do if int(user_input) == 1:
Whenever you collect a user's input using the input function, it is a string, not int. this means you will have to either parse the value into an int or evaluate it with a string.
option 1: parsing to int:
user_input = int(input("1 for own Input - 0 for Program-Input"))
option 2: evaluating with string:
if user_input == "1":
input returns a string not a integer so it can never be equal to 1 instead it will be equal to "1".
Plus the code for the user guessing only runs when the program chooses the word so it needs to be unindented.
As a side note your code currently registered capital letters as being different from lower case, you can fix this by putting a .lower() after each input which will turn all capital letters into lowercase.
print("Do you wish to set the Word yourself, or let the program choose?: ")
user_input = input("1 for own Input - 0 for Program-Input")
if user_input == "1":
Keyword = input("Type in the Word you want to use: ").lower()
else:
Keyword = "castle"
word = list(Keyword)
length = len(word)
right = list ("_" * length)
used_letters = list()
finished = False
while finished == False:
guess = input("Guess a Letter: ").lower()
if guess not in Keyword:
print("This letter is not in the word. Sorry...")
for letter in word:
if letter == guess:
index = word.index(guess)
right[index] = guess
word[index] = "_"
if guess in used_letters[0:100]:
print("You already used that letter before!")
else:
used_letters.append(guess)
list.sort(used_letters)
print(right)
print("Used letters:")
print(used_letters)
if list(Keyword) == right:
print("You win!")
finished = True
input('Press ENTER to exit')

Python : Hang Man game

I am making a hang man game. I am trying to cycle through a word and have all the repeats in the letter be appended to my list. For example the word "hello": if the user types in "l" I want all the l's to be added to my list. Right now it is only finding one "l" and if the user types an "l" again it finds the second "l".
I also want the user not to be able to type in another letter if they previously already typed it in.
I have two lists one for right guesses and wrong guesses that store every guess. For example if a user types in "h" in "hello"
"h" is a right guess so it appends to [h] but if they type in "h" again it adds it to the list so it says ["h","h"]. The wrong box works the same way but for words that are wrong. If they type in "z" for the word "hello" it says ["z"] in the wrong box.
Here is my code:
import random
user_input = ""
turns = 5
print("Welcome to Advanced Hang Man!")
print("Use your brain to unscramble the word without seeing its order!")
words = ["hello","goolge","czar","gnat","relationship","victor","patric","gir","foo","cheese"]
# Picks a random word from the list and prints the length of it
random_word = (random.choice(words))
random_word_legnth = (len(random_word))
print("Hint! The length of the word is",random_word_legnth)
hold_random_word = [i for i in random_word]
while turns != 0 and set(right_guess) != set(hold_random_word):
user_input = input("Please type your guess one letter at a time:")
right_guess = []
wrong_guess = []
#Calculating every input
if len(user_input) == 1 and user_input.isalpha():
for i in user_input:
if i in hold_random_word:
right_guess.append(i)
else:
wrong_guess.append(i)
print("Correct guess", ''.join(right_guess))
print("Wrong guess", ''.join(wrong_guess))
I'm not sure what your direct question is, but thinking about a hangman game you want to take the users guess and parse the entire word or phrase they are guessing to see if their guess matches anywhere in the word. I made a hang man game below that will function as expected (minus any error handling) Let me know if any parts confuse you, and i can explain
import random
wordcomp = []
wordguess = []
#this is a word bank for all puzzles, they are randomly chosen
word_bank = ['guess this phrase', 'Lagrange', 'foo', 'another phrase to guess']
# This loop stores each letter in a list, and generates a blank list with correct spaces and blanks for user
rand_word = random.randrange(4)
for i in word_bank[rand_word]:
wordcomp.append(i)
if i == ' ':
wordguess.append(' ')
else:
wordguess.append('__')
print('I am thinking of a word,' , wordguess , ' it has ', len(wordguess), ' characters total, GOOD LUCK \n')
wordlist = wordcomp
count = 0
placeletter = 0
wrongguess = []
guesscount = 0
while wordlist != wordguess:
guess = input('please input a lower case letter within the english alphabet!') ##Check that input is one character, and lower case
guesscount = guesscount + 1
# This for loop scans through to see if the letter that was guessed is in the actual puzzle, and places in the correct spot!!
for t in wordcomp:
if t == guess:
wordguess[placeletter] = guess
placeletter = placeletter + 1
# This check tells them they already guessed that letter... then makes fun of them
if guess in wordguess:
pass
else:
wrongguess.append(guess)
while wrongguess.count(guess) > 1:
wrongguess.remove(guess)
print('you guessed the letter ' , guess , ' already, are you person that suffers short term memory loss...')
print('The word I am thinking of: ' , wordguess)
print('The letters you have already guess are: ', wrongguess)
placeletter = 0
# This tells them they finished the puzzle and the number of guesses it took, if its over 26, it calls them stupid for obvious reasons...
if guesscount >= 26:
print('you are an idiot if it took you more than 26 guesses..... now take a minute, sit silently, and think about why you are idiot if it took over 26 guesses... for hangman... where you guess the letters of the alphabet... YOU GET IT, stupid')
elif guesscount < 26:
print('Congrats you solved the puzzle, w00t!!')
if len(user_input) == 1 and user_input.isalpha():
for i in user_input:
if i in hold_random_word and i not in right_guess:
right_guess.append(i)
elif i not in hold_random_word or i not in wrong_guess:
wrong_guess.append(i)
elif i in hold_random_word:
# here user types something that is already typed and is a right_guess
pass
else:
# Types something wrong, that was already typed
pass
print("Correct guess", ''.join(right_guess))
print("Wrong guess", ''.join(wrong_guess))
It is not clear how you are taking inputs, but I think this code can be further optimized. Give it a shot.
Edit 1:
import random
user_input = ""
turns = 5
print("Welcome to Advanced Hang Man!")
print("Use your brain to unscramble the word without seeing its order!")
words = ["hello","goolge","czar","gnat","relationship","victor","patric","gir","foo","cheese"]
random_word = (random.choice(words))
random_word_legnth = (len(random_word))
print("Hint! The length of the word is",random_word_legnth)
hold_random_word = [i for i in random_word]
# This condition can lead to issues in situations like this - abc and aabbcc [sorry couldn't quickly come up with a good actual example :)]
while turns != 0 and set(right_guess) != set(hold_random_word):
user_input = input("Please type your guess one letter at a time:").strip()
right_guess = []
wrong_guess = []
#Calculating every input
if len(user_input) == 1 and user_input.isalpha():
# user_input is 1 letter so for i in user_input will execute only once
# Use the if structure as defined above
if user_input in hold_random_word:
right_guess.append(i)
else:
# this is missing
turns -= 1
wrong_guess.append(i)
print("Correct guess", ''.join(right_guess))
print("Wrong guess", ''.join(wrong_guess))
elif len(user_input) > 1:
print("Please type only one letter at a time")
elif not user_input.isalpha():
print("Please enter only valid English letters")
else:
# handle this however you want :)
pass

How do I use "i and ch in enumerate(Answer)" to see how many of my guess characters are in the right position?

Specifically: We are to print out how many of the guess character are exactly right (correct character in the
correct position) and
and how many of the guess characters are correct values but are not in the correct
position.
Here's my code:
key = input("Input your secret key (RYBGWO):")
print("You are playing Mastermind whose purpose is to guess the secret key.")
print("Six colors are to be inputed with no repeats (RYBGW0).")
Answer = input("Please enter your 4-letter guess (RYBGWO):")
Answer_count = 0
my_string = "RYBGWO"
history = ''
while Answer.upper() != key:
ANSWER = Answer.upper()
if Answer.count("R") > 1:
Answer = input("You can not have repeating characters, try again:")
continue
elif Answer.count("Y") > 1:
Answer =input("You can not have any repeating characters, try again:")
continue
elif Answer.count("B") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif Answer.count("G") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif Answer.count("W") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif Answer.count("O") > 1:
Answer = input("You can not have any repeating characters, try again:")
continue
elif not(Answer.isalpha()):
Answer = input("Error, guess must be letters only, try again: ")
continue
elif len(Answer) !=4:
Answer=input("Your guess must contain 4 letters (rybgwo).Try again:")
continue
if 'R' and 'Y' and 'B' and 'G' and 'W' and 'O' not in Answer:
Answer = input("ERROR: Only letters RYBGWO allowed. Try again:")
continue
for i, ch in enumerate(Answer):
correct_count = 0
correct_position = 0
wrong_position = 0
i = 0
if key[i] == Answer[i] and key[ch] == Answer[ch]:
correct_count += 1
correct_position +=1
i = [len(Answer)-1]
print("Correct color and position count:", correct_count)
elif key[ch] == Answer[ch] and key[i] != Answer[i]:
correct_count += 1
wrong_position += 1
i = [len(Answer)-1]
print("Correct color, wrong position:", )
else:
print("Congratulations! You won!")
Answer_count = Answer_count + 1
print("(",Answer_count,"of 8 guesses)")
history += "\n" + Answer
print("History:", history)
The line
if key[i] == Answer[i] and key[ch] == Answer[ch]:
does not make all that much sense. Using enumerate, i is the position, that's fine, but ch is the character at that position. key[ch] does not make sense. Did you mean key.count(ch)? But even then there is no easy way to get the "correct value at incorrect position" part easily with enumerate. Consider the case of "abcd" and "baca": Here, a has different count in both strings, and yet that should be +1 for correct_count
Instead, let me suggest this: For "correct value at correct position", just zip the two strings and compare the characters. The "correct value at incorrect position" case is a bit more difficult, but can be done by creating two Counter objects and &-ing those together.
>>> x = "abcd"
>>> y = "baca"
>>> Counter(x) & Counter(y)
Counter({'a': 1, 'c': 1, 'b': 1})
>>> [a == b for a, b in zip(x, y)]
[False, False, True, False]
When calculating the totals, remember that the correct_count number includes the correct_position number, so you need to subtract those:
>>> correct_position = sum(a == b for a, b in zip(x, y))
>>> correct_count = sum((Counter(x) & Counter(y)).values()) - correct_position
Down votes are coming because your criteria is not well defined, but I think that you are asking for a basic master-mind type problem. It is easy enough if you define your problem such that the hidden values do not repeat. If your hidden value, as I define it below can have repeating values than the problem gets more complex. It can be made to work - it just takes a bit more thought.
Anyway, here is a basic implementation that I've tested on my box.
hidden = ["red", "blu", "grn", "ylw", "gold", "ora"]
def check_answer(answer):
guess_num = 0
correct_position = 0
correct_location = 0
for guess in answer:
text = "value not found"
if (len(hidden) <= guess_num):
break
if guess == hidden[guess_num]:
correct_position += 1
text = "correct value and position"
elif guess in hidden:
correct_location += 1
text = "correct value, wrong position"
guess_num += 1
print("guess {} = {} ; {}".format(guess_num, guess, text))
ans1=["red", "grn", "blu", "ylw"]
ans2=["red"]
check_answer(ans1)

Categories

Resources