Working with multiple occurrences of elements in a list - python

I'm still a noob when it comes to coding and I'm trying to create my own hangman game. I ran into some difficulties when it comes to guessing characters of a word which occur more than once in a word.
Here's a snippet of my code:
def random_word():
#word generator
randomized = random.randint(0,(len(content_words)-1))
word_to_guess = content_words[randomized].lower()
splitted = []
word_progress = []
for character in word_to_guess:
splitted.append(character.lower())
word_progress.append("?")
counter = 0
while counter <= 5:
print(word_to_guess)
print(splitted)
print(word_progress)
#Start of the game
options = str(input("Do you want to guess the word or the characters?: ").lower())
#word
if options == "word":
guess_word = input("Please your guess of the word: ").lower()
if guess_word == word_to_guess:
print("Correct! The word was " + word_to_guess + " you only needed " + str(counter) + " tries!")
break
elif guess_word != word_to_guess:
counter += 3
print("You have entered the wrong word ! You now have " + str(5-counter) + " tries left!")
continue
#characters
elif options == "characters":
guess_character = input("Please enter the character you would like to enter!: ")
if guess_character in splitted and len(guess_character) == 1:
print("Correct! The character " + guess_character.upper() + " is in the word were looking for!" )
for char in word_to_guess:
if char == guess_character:
word_progress[word_to_guess.index(char)] = word_to_guess[word_to_guess.index(char)]
continue
....so basically in the character section only the first occurrence of the guessed character gets implemented into the word_to_guess list. What is the best way to handle this problem?
By the way this is the first question I've ever asked regarding to coding and on this platform, please excuse me if I didn't really formulate my problem in the most efficient way.

index will only return the index of the first occurence of your character.
You should use enumerate to iterate on the characters and indices at the same time:
for index, char in enumerate(word_to_guess):
if char == guess_character:
word_progress[index] = guess_character

Related

Improve the odds of winning at hangman with ai

I'm new (and to stack overflow, this is the first question I have ever asked) to python, I have been self-teaching myself for a couple of weeks. I was doing some beginner projects when I decided to make a hangman ai.
#importing
import random
import time
import sys
from collections import Counter
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#defining some variables
list_of_words = open("dictionary.txt", "r")
list_of_words = list_of_words.read().split()
SYMBOL = "abcdefghijklmnopqrstuvwxyz"
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#main game loop
def main():
while True:
print("\nGenerating word...")
word = list_of_words[random.randint(0, len(list_of_words) - 1)].lower()
word_guess = []
wrong_attempts = 0
wrong_letters = []
game_state = True
for symbol in word:
if symbol in SYMBOL:
word_guess.append("_")
else:
word_guess.append(symbol)
word_show = " ".join(word_guess)
word = list(word)
while game_state != False:
print("\n" + word_show)
print("\nWrong attempts [{0}/5]" .format(wrong_attempts))
if len(wrong_letters) > 0:
print("\nLetters guessed [{0}]" .format(", ".join(wrong_letters)))
letter = "-"
while letter not in SYMBOL or letter == "" or len(letter) > 1:
try:
letter = input("\nGuess a letter or enter 0 to call the ai: ")
except:
print("\nUnexpected error ocurred, try again")
if letter == "0":
correct_letters = [letter for letter in word_guess if letter in SYMBOL]
letter = ai_solver(wrong_letters, word_guess)
elif letter in wrong_letters or letter in word_guess:
print("\nYou already guessed letter [{0}]" .format(letter))
letter = ""
if letter in word:
for i in range(len(word)):
if letter == word[i]:
word_guess[i] = letter
else:
wrong_letters.append(letter)
wrong_attempts += 1
word_show = " ".join(word_guess)
if "".join(word_guess) == "".join(word):
print("\nYou won!")
game_state = False
elif wrong_attempts == 5:
print("\nYou lost!")
print("The word was [{0}]" .format("".join(word)))
game_state = False
option = input("\nWant to play again?[Y/N]: ")
if option.lower().startswith("n"):
sys.exit(0)
def ai_solver(letters_attempted, word_guess):
letters_attempted = letters_attempted if len(letters_attempted) != 0 else ""
available_words = []
for word in list_of_words:
append = False
if len(word) == len(word_guess):
append = True
for i in range(len(word_guess)):
if word[i] in letters_attempted:
append = False
break
if word_guess[i] != "_":
if word[i] != word_guess[i]:
append = False
break
if append == True:
print("[{0}]" .format(word))
available_words.append(word)
common_letters = [letter for letter in "".join(available_words) if letter not in word_guess]
common_letters = Counter("".join(common_letters)).most_common(1)
return common_letters[0][0]
main()
What I tried to do is, to filter all the possible words that have the same length as word_guess.
Then filter out any words that contained a letter that was guessed incorrectly by checking letters_attempted.
Then it would filter out all words that had letters that did not match with word_guess.
if word_guess[i] != "_":
if word[i] != word_guess[i]:
append = False
break
Although it works fine, sometimes it would lose, what can I add to increase the chances of winning?
Thank you!
Your two filter steps are a good first start. There are several different steps you could take to try to improve things. Let's call the words that fit the criteria so far the candidate words.
The first step would be to analyze all the candidate words and figure out which letter appears most frequently in the candidate words. (Not counting repeated letters multiple times.) That letter would make a good next guess.
A slightly more sophisticated approach would look at information gain from a guess. That is, it might be that half the candidate words have a 's', but all such words end in 's'. There might be slight fewer candidate words with a 't', but the 't' can appear anywhere in the word. So, when you guess 't' you actually get a lot more information about what the word could be, because you are shown the location of the 't' when you guess it correctly. Particularly when you don't have enough guesses to figure out every word, such a strategy may help you figure out more words in the guesses that you have.

How do I have a list accept lowercase in place of capitalized letters in Hangman for a randomized list in Python 3?

I have been looking around to see if I could find something that could help, but nowhere has an answer for what I'm looking for. I have a Hangman game I'm doing for a final project in one of my classes, and all I need is to make it so if a word has a capital letter, you can input a lowercase letter for it. This is the code.
import random
import urllib.request
wp = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-
type=text/plain"
response = urllib.request.urlopen(wp)
long_txt = response.read().decode()
words = long_txt.splitlines()
###########
# Methods #
###########
def Run():
dashes1 = "-" * len(word)
dashes2 = "-" * len(word2)
used_letter = []
dashes = dashes1 + " " + dashes2
#dashes ="-" * len(secretWord)
guessesLeft = 6
while guessesLeft > -1 and not dashes == secretWord:
print(used_letter)
print(dashes)
print (str(guessesLeft))
guess = input("Guess:")
used_letter.append(guess)
if len(guess) != 1:
print ("Your guess must have exactly one character!")
elif guess in secretWord:
print ("That letter is in the secret word!")
dashes = updateDashes(secretWord, dashes, guess)
else:
print ("That letter is not in the secret word!")
guessesLeft -= 1
if guessesLeft < 0:
print ("You lose. The word was: " + str(secretWord))
print(dashes)
else:
print ("Congrats! You win! The word was: " + str(secretWord))
print(dashes)
def updateDashes(secret, cur_dash, rec_guess):
result = ""
for i in range(len(secret)):
if secret[i] == rec_guess:
result = result + rec_guess
else:
result = result + cur_dash[i]
return result
########
# Main #
########
word = random.choice(words)
word2 = random.choice(words)
#print(word)
#print(word2)
secretWord = word + " " + word2 # can comment out the + word2 to do one
word or add more above to create and combine more words will have to adjust
abouve in Run()
splitw = ([secretWord[i:i+1] for i in range(0, len(secretWord), 1)])
print (splitw)
Run()
any bit of help is appreciated. The website I'm using has a bunch of words that are being used for the words randomly generated. Some are capitalized, and I need to figure out how to let the input of a letter, say a capital A, accept a lowercase a and count for it.
you could compare after you converted everything to lowercase.
e.g. you could do
secretWord = word.lower() + " " + word2.lower() # that should make your secret all lowercase
for the input you should do the same:
guess = input("Guess:").lower()
after that it should not matter if it is upper or lower case. it should always match if the letter is the correct one.
hope that helps
Simply check everything in lowercase:
[...]
elif guess.lower() in secretWord.lower():
[...]
and so on.
I would just change this line:
while guessesLeft > -1 and not dashes == secretWord:
to:
while guessesLeft > -1 and not dashes.lower() == secretWord.lower():
This way you are always comparing lower-case representations of the user's input to the lower-case representation of your secretWord. Since this is the main loop for your game, you want to break out of this as soon as the user's guess matches your word regardless of case. Then later in your code, you will still check whether they had any guesses left, and print out their answer and the secret word as before.
No other changes required, I think.
You could just force all comparisons to be made in the same Case, such as lowercase.
Let’s say that your word is "Bacon". and someone enters "o".
That will be a match because quite obviously “o” equals “o” so you can cross that letter off the list of letters left to guess.
But in the case that someone enters “b” then b is NOT equal to “B”.
So why not just force all letters to be compared using the same case?
So your comparison will be like
elif guess.Lower() in secretWord.Lower()
My python is rusty as hell, but the idea here should do what you want to do

How to get same words two time in hangman using python

Here's my code, everything works I think except it doesn't take any value more than one. Please help me out.
word = input("What's your word?\n").upper()
forguess = " ".join(word)
char = "_"
for index in range(len(word)):
word = word[:index] + char + word[index+1:]
spacedwords = " ".join(word)
print(spacedwords)
chances = 5
while chances != 0:
print("You have " + str(chances) + " chances left\n")
letter = input("Guess the letters: \n").upper()
if letter in forguess: #check if the input letter is in original word
pos = forguess.index(letter) #gets the letter position from forguess original word
spacedwords = spacedwords[:pos] + letter + spacedwords[pos+1:] #replace word in the blank ones
print(spacedwords)
if spacedwords == forguess:
print("YOU WON!!!")
break
else:
chances -= 1
if chances == 0:
print("YOU LOOSE!!!")
The main reason why your code does not work is that, while spacedwords changes when you guess a letter, forguess does not. This way your index call always just finds the first occurrence of letter. Trying to modify your code as little as possible (there would be more efficient ways to do this), here an example of how to achieve what you want:
word = input("What's your word?\n").upper()
forguess = " ".join(word)
char = "_"
for index in range(len(word)):
word = word[:index] + char + word[index+1:]
spacedwords = " ".join(word)
print(spacedwords)
chances = 5
while chances != 0:
print("You have " + str(chances) + " chances left\n")
letter = input("Guess the letters: \n").upper()
if letter in forguess: #check if the input letter is in original word
positions = [i for i,x in enumerate(forguess) if x == letter] #gets all letter positions from forguess original word
for pos in positions:
spacedwords = spacedwords[:pos] + letter + spacedwords[pos+1:] #replace all blank positions with letter
print(spacedwords)
if spacedwords == forguess:
print("YOU WON!!!")
break
else:
chances -= 1
if chances == 0:
print("YOU LOOSE!!!")
EDIT:
As the first time around I misunderstood what the OP intended to do, here again an example that tries to modify the original code as little as possible. I introduced a new variable original that in the beginning is identical to forguess. Now, every time a letter is guessed correctly, forguess is modified (the guessed letter is changed into a NULL character), so that in the next search it will not show up again. Then, in the end spaceedwords is compared to original instead of forguess.
word = input("What's your word?\n").upper()
forguess = " ".join(word)
original = " ".join(word)
char = "_"
for index in range(len(word)):
word = word[:index] + char + word[index+1:]
spacedwords = " ".join(word)
print(spacedwords)
chances = 5
while chances != 0:
print("You have " + str(chances) + " chances left\n")
letter = input("Guess the letters: \n").upper()
if letter in forguess: #check if the input letter is in original word
pos = forguess.index(letter) #gets the letter position from forguess original word
spacedwords = spacedwords[:pos] + letter + spacedwords[pos+1:] #replace word in the blank ones
forguess = forguess[:pos] + chr(0) + forguess[pos+1:]
print(spacedwords)
if spacedwords == original:
print("YOU WON!!!")
break
else:
chances -= 1
if chances == 0:
print("YOU LOOSE!!!")
Note:
The whole problem would be much more easy to handle, if you converted you forguess into a list of single characters.

Python hangman, removing blanks from the answer pool and refining what can be input

I'm currently learning Python and trying to build a set of minigames to solidify my basic knowledge, however there are a few things I want to do with my game that others on here haven't (from what I've seen, at least), and that is remove whitespace between words from the answer and the "masked" answer. I assume it would be done as an "if, else" sort of statement? Please correct me if I'm wrong.
for x in range(i): ## where i is the word
if x == " ":
continue ## wouldn't it be pointless to append something that you don't want to change?
else:
word.append('_')
Another question I had was regarding a loop statement I have at the beginning of my game, within this loop I have an if/else stating that if there are more than 1 letter in the guess, it'll return a statement telling the user that's not valid. But the game immediately stops working afterword.
while guesses < 6:
guess = raw_input("Please guess a letter: ")
if len(guess) > 1:
return "One letter at a time!"
else: continue
I'm not quite sure what to add to my code to make it continue asking for input after this.
Here's my full code, it's currently not working for me after asking for input... I took the code it from another user on here and fixed it to my tastes, since their game didn't use more than one word and didn't check to see if there was more than one letter being input when prompted, and I figured it would be good practice to modify existing code to make it do a bit more than it originally does.
def hangman():
guesses = 0
word = []
guessed = []
words = ["bichon frise", "maltese", "dachshund", "pomeranian", "golden retriever", "shih tzu", "rottweiler", "pit bull", "beagle", "poodle", "akita", "basset hound", "border collie", "boston terrier", "boxer", "bulldog", "chow chow", "chihuahua", "chinese crested", "french bulldog", "great dane", "great pyrenees", "greyhound", "icelandic sheepdog", "irish wolfhound", "komondor", "mastiff", "shnauzer", "pekingese", "welsh corgi", "redhound coonhound", "samoyed", "shiba inu", "weimaraner", "whippet", "italian greyhound", "yorkshire terrier"]
print "Welcome to Hangman. The words chosen are the names of various breeds of dogs, try and guess the word before the man is hung!"
answer = random.choice(words)
i = len(answer)
print "The length of the word is", i, "characters long"
for x in range(i):
if x == " ":
continue
else:
word.append('_')
while guesses < 6:
guess = raw_input("Please guess a letter: ")
if len(guess) > 1:
return "One letter at a time!"
else:
continue
if (guess in i):
print "The letter is in the word."
for index, letter in enumerate(i):
if letter == guess:
word[index] = guess
guessed.append(guess)
else:
print "The letter is not in the word"
guesses = guesses + 1
guessed.append(guess)
print "You have guessed these letters so far: %s)" % (''.join(guessed))
print "Letters matched so far %s): %" (''.join(word))
if ''.join(word) == answer:
break
if guesses == 6:
print "You didn't guess the right answer in time! The answer was %s" % answer
else:
print "You guessed the word!"
remove whitespace between words from the answer.
Given i (i as a string?) is the string, you probably should not use range(..) on it since range expects an int. Furthermore why do you build a list instead of a new string? You can however easily use a generator:
word = ''.join(c for c in i if c != ' ')
word is here a string that contains all characters of i that are not ' '. If you want however to generate a sequence of underscores, you can use:
word = ''.join('_' for c in i if c != ' ')
If you want to construct a list (which the remainder of the code expects), you can use list comprehension:
word = ['_' for c in i if c != ' ']
it'll return a statement telling the user that's not valid. But the game immediately stops working afterword (sic.).
That's because you use a return statement: return means you jump out of the function and (optionally) return a value. You probably want to print(..):
guesses = 0
while guesses < 6:
guess = raw_input("Please guess a letter: ")
if len(guess) > 1:
print("One letter at a time!")
else:
#process char
continue
I also noticed you use continue. continue means that you abandon the remainder of the iteration and take the next one, so it means you will not process the query. So you have to remove the continue part:
while guesses < 6:
guess = raw_input("Please guess a letter: ")
if len(guess) > 1:
print("One letter at a time!")
return ends the function right there, use print instead:
print "One letter at a time!"
As for the whitespace, why don't you append the space to the masked word? That way, the player won't have to guess it, can see that there are spaces, and your join-check will work:
for x in range(i):
if x == " ":
word.append(' ')
else:
word.append('_')

Word Guessing Game in Python?

I'm in a basic programming class and I'm a bit stuck working on this game. The idea was to create a simple word-guessing game, where the computer would choose a random word and you would attempt to guess first some letter in the word, then the word itself after 5 tries. I've gone through multiple times and I still get an error of "Invalid Syntax" when I attempt to run the module.
I'm a bit dyslexic when it comes to programming languages, so maybe there's something I'm overlooking?
I would appreciate it if someone out there could offer a bit of help!
#Word Guessing Game
#Computer picks a random word
#Player tries to guess it
#computer only responds with yes or no
import random
tries = 0
print "Welcome to the word game!"
print "\nI'm going to think of a word and you have to guess it!"
print "\nGuess which letters are in the word, then you have to guess the whole thing!"
print "\nGood luck!"
WORDS = ("follow", "waking", "insane", "chilly", "massive",
"ancient", "zebra", "logical", "never", "nice")
word = random.choice(WORDS)
correct = word
length = len(word)
length = str(length)
guess = raw_input("The word is " + length + " letters long. Guess a letter!: ")
while tries < 5:
for guess in word:
if guess not in word:
print "Sorry, try again."
else:
print "Good job! Guess another!"
tries = tries + 1 #*
if tries = 5:
final = raw_input ("Try to guess the word!: ")
if final = correct:
print "Amazing! My word was ", word, "!"
else:
print "Sorry. My word was ", word, ". Better luck next time!"
raw_input("\n\nPress enter to exit")
It should also be noted that the problems occurred after the end of the "while tries" block, when I attempted to specify the limits of the "tries" variable. I've worked with it before in a random number game, but for some reason it didn't work properly here. I would greatly appreciate some help!
It should also be noted that I run on a rather outdated version of Python, some variation of 2.0, I believe.
tries = tries + 1
if tries == 5:
final = raw_input ("Try to guess the word!: ")
if final == correct:
You need == for comparison not =, = is for assignment.
You can also replace tries = tries + 1 with tries += 1
You also want to move raw_input inside the loop and just ask the user to guess the word outside the while when the guesses are all used up:
while tries < 5:
guess = raw_input("The word is " + length + " letters long. Guess a letter!: ")
if guess not in word: # use `in` to check if the guess/letter is in the word
print "Sorry, try again."
else:
print "Good job! Guess another!"
tries += 1
# guesses are all used up when we get here
final = raw_input ("Try to guess the word!: ")
if final == correct:
print "Amazing! My word was ", word, "!"
else:
print "Sorry. My word was ", word, ". Better luck next time!"
please try this one.
import random
index = -1
infi = ("python","jumble","hide","mama")
word = random.choice(infi)
word_len = len(word)
guess = ""
attempt = 0
enter = ""
print(word)
temp = "_" * word_len
print("\t\t The word chosen by computer contain", word_len,"letters.")
print("\t Tap any letter to check if this letter is in computer word.\n")
print("\t You got 5 attempts to check if tapped letter is in computer word.\n")
print("\t\t\t\t GOOD LUCK!!!\n\n\n\n")
for i in range(0, 5):
attempt +=1
guess = input("Attempt no. "+str(attempt)+":")
if guess in word and guess != enter:
for i in range(0, word_len):
if guess == word[i]:
temp = temp[:i] + guess +temp[i+1:]
print("yes\n" + temp)
if guess not in word:
print("no")
if "_" not in temp:
print("\t\t*********** Congratulation!! You guess the word *************")
break
elif attempt == 5:
guess = input("And the word is:")
if guess == word:
print("\t\t*********** Congratulation!! You guess the word *************")
else:
print("\t\t*********** WRONG!! Shame on you *************")

Categories