I'm trying to create a little game.
The rules are very straightforward: you give an English word, and the computer will try to guess this word letter by letter.
The thing is, I'm trying to make the computer guess the letters in a smart way. Let me give you a simple example of what I'm trying to build so you can understand:
You give the word "cat" to the computer to guess.
The 130K words list I have is narrowed to only the words who have 3 characters, which makes up to 805 words only. And from this list of words, an alphabet is created, containing only 25 letters (not the whole 26) because the new 805 words list contains all the letters of the alphabet but the "z". So we now have a list containing 25 (different) letters.
-- As I can't upload anything here on SO, we will say for this example that the massive 130K words list is a 10 words list (variable name "fullDice") --
If you try to run my code, pick a word from inside this list or else
it's not going to work
The computer now guesses a random letter from this 25 letters list.
If the letter is not in the word, he doesn't do anything and re-guess a letter from the list.
But if the letter is in the word, that's where things become more complicated. Let's say the computer guess the letter "c". I want the computer to re-narrow the possible words list, to only those having a "c" in the first character. That way, the 805-words list become now an only 36 words list. Because there are only 36 words who are 3 characters and starts with a "c", a new alphabet is created. And the new alphabet is now made of only 14 letters, making it easier for the computer to guess the next letter and be correct about it. And so on until he finds all the letters.
I'm stuck on part 5. If you try to run my code just below, you'll see that the dictionnary list is never narrowed. That's my problem.
import time
from random import randint
fullDice = ["panda", "tiger", "cat", "elephant", "whale", "leopard", "gorilla", "fish", "snake", "eagle"]
askForWord = input("Please enter an english word: ")
while True:
updatedDice = []
for k in range (0, len(fullDice)):
if len(askForWord) == len(fullDice[k]):
updatedDice += [fullDice[k]]
alphabet = []
for i in range (0, len(updatedDice)):
for n in range (0, len(updatedDice[i])):
if updatedDice[i][n] not in alphabet:
alphabet += [updatedDice[i][n]]
guessRandomLetter = alphabet[randint(0, len(alphabet) - 1)]
print("I guess the letter: " + guessRandomLetter)
print("From this dice: " + str(len(updatedDice)))
print("From this amount of letters: " + str(len(alphabet)) + "\n")
time.sleep(0.75)
guessedWordUnderlined = "_" * len(askForWord)
if guessRandomLetter in askForWord:
for m in range(0, len(askForWord)):
if askForWord[m] == guessRandomLetter: # CHECKING IF THE GUESSED LETTER IS INSIDE THE WORD
guessedWordUnderlined = list(guessedWordUnderlined)
guessedWordUnderlined[m] = guessRandomLetter
guessedWordUnderlined = ''.join(map(str, guessedWordUnderlined))
if guessedWordUnderlined == askForWord: # CHECK IF USER HAS WON
print("YOU WON")
break
you just asked a qs including that code.
i tryed to make it work only with the available words in the dictionnary you gave as "python".
from random import randint
import random
import time
import datetime
random.seed(datetime.datetime.now())
wordOfTheUser = input("ENTER ENGLISH WORD HERE: ")
if wordOfTheUser in ("abracadabra", "python", "coding", "soup", "paper", "list", "leader", "program", "software", "eating","abcdefghigklmnopqrstuvwxyz"):
pass
else:
print("your word is not on the list, still devlopping.")
raise
diceList1 = ["abracadabra", "python", "coding", "soup", "paper", "list", "leader", "program", "software", "eating","abcdefghigklmnopqrstuvwxyz"]
diceList2 = []
for k in range (0, len(diceList1) - 1):
if len(diceList1[k]) == len(wordOfTheUser):
diceList2 += [diceList1[k]]
makeAlphabet = []
for b in range (0, len(diceList2)):
for x in range (0, len(diceList2[b])):
if diceList2[b][x] not in makeAlphabet:
makeAlphabet += [diceList2[b][x]]
computerWordSize = "_" * int(len(wordOfTheUser))
a= len(makeAlphabet)
while True:
try:
randomIndex = randint(0, a)
except ValueError:
randomIndex = randint(0, a)
pass
try:
letterChosenRandomly = makeAlphabet[randomIndex]
except IndexError as e:
try:
randomIndex = randint(0, int(len(makeAlphabet)))
letterChosenRandomly = makeAlphabet[randomIndex]
except:
pass
print("I guess the letter -> " + letterChosenRandomly)
diceList3 = []
if letterChosenRandomly in wordOfTheUser:
print("\n=== WON ===> " + letterChosenRandomly)
print("=== ALPHABET ===> " + str(len(makeAlphabet)))
print("=== HDW1 ===> " + str(len(diceList1)))
print("=== hdw2 ===> " + str(len(diceList2)))
print("=== hdw3 ===> " + str(len(diceList3)) + "\n\n")
k=-1
makeAlphabet = []
for i in range (0, len(wordOfTheUser) ):
if letterChosenRandomly == wordOfTheUser[i]:
computerWordSize = list(computerWordSize)
computerWordSize[i] = letterChosenRandomly
for l in range (0, len(diceList2)):
if computerWordSize[i] == diceList2[l][i]:
diceList3 += [diceList2[l]]
for d in range(0, len(diceList3)):
for h in range(0, len(diceList2[b])):
if diceList2[d][h] not in makeAlphabet:
makeAlphabet += [diceList2[d][h]]
won = False
computerWordSize = ''.join(map(str, computerWordSize))
print(computerWordSize)
if computerWordSize == wordOfTheUser:
won = True
if won is True:
print("YOU WON")
break
time.sleep(1)
else:
print("\n=== LOOSE ===> " + letterChosenRandomly)
print("=== ALPHABET ===> " + str(len(makeAlphabet)))
print("=== HDW1 ===> " + str(len(diceList1)))
print("== hdw2 ===> " + str(len(diceList2)))
print("=== hdw3 ===> " + str(len(diceList3)) + "\n\n")
try:
makeAlphabet.remove(letterChosenRandomly)
except:
print ("Letters not in list")
break
k=0
diceList3 = []
for q in range (0, len(wordOfTheUser) - 1):
for l in range(0, len(diceList2)):
if computerWordSize[q] == diceList2[l][q]:
diceList3 += [diceList2[l]]
for d in range(0, len(diceList3)):
for h in range(0, len(diceList2[b])):
try:
if diceList2[d][h] not in makeAlphabet:
makeAlphabet += [diceList2[d][h]]
except:
try:
for s in range(0, len(diceList3)):
for f in range(0, len(diceList2)):
if diceList2[s][f] not in makeAlphabet:
makeAlphabet += [diceList2[s][f]]
except:
("your word is too short")
time.sleep(1)
I believe the problem is that if guessedWordUnderlined in askForWord will never be true. The in operator tests whether the first operator is within the second argument, which is a container, such as a list or string. "_" * len(askForWord), the value of guessedWordUnderlined, is a string of underscores, and you are testing whether or not that is in askForWOrd. If the vale of askForWord is cat, askForWord can be thought of as ["c", "a", "t"], so the in operator will be testing "___" == "c" or "___" == "a" or "___" == "t", none of which will be true. This means that the code beneath it will never execute, so the code just repeats forever, randomly guessing letters within the word. I cannot really tell what the function of this if is, as you already know each letter you could have chosen is in askForWord, though I'm sure I'm missing something obvious.
As an aside, you frequently use a construction similar to for x in range(0, len(LIST): ... LIST[x], which can be more concisely and obviously written as for x in LIST: ... x. For example, your code
for k in range (0, len(fullDice)):
if len(askForWord) == len(fullDice[k]):
updatedDice += [fullDice[k]]
alphabet = []
could be written as
for k in fullDice:
if len(askForWord) == len(k):
updatedDice += [k] # This should be updatedDice.append(k), but I
# have left it as-is for simplicity's sake.
alphabet = []
which should help your code become more readable. There are a few other edits that could be made to make your code more pythonic, but aside from that line I cannot see anything functionally wrong with it. If you share what this if is supposed to help, it might make it a bit easier to find any other errors in your code. I hope this helps, and good luck!
Having reviewed your code again, I believe the problem is in the statement guessedWordUnderlined = "_" * len(askForWord). This creates a string of underscores whose length is equal to that of askFOrWord. The problem is that each at each iteration of the while True: loop, a new string. This means that at each iteration, the string becomes a list of underscores with one correct letter, but in the next iteration it is overridden. To fix this, you should move the line guessedWordUnderlined = "_" * len(askForWord) from its current location to directly below askForWord = input("Please enter an english word: "). This will mean that it is present in the global scope rather than the local scope, meaning it won't get overwritten. You should also put the line global guessedWordUnderlined at the beginning of the while loop, if I'm not mistaken. This may require you to rework some code. Hope this works for you!
Related
The propolem is Exception has occurred: IndexError
string index out of range. this happens in line 46
and to have lots of word option made a list with 5 letter words
i think the propolem is with the fact i origonial made it for number instead of leaters
The propolem is Exception has occurred: IndexError
string index out of range. this happens in line 46
and to have lots of word option made a list with 5 letter words
i think the propolem is with the fact i origonial made it for number instead of leaters
##
# wordel
# Print the welcome message.
print("Welcome to wordel!")
print("You will guess the final word.")
##
# random words
# using randint()
import random
# open file
with open(r"C:\Users\Admin\OneDrive\Documents\wordel list.txt") as file:
data = file.read()
words = data.split()
# Generating a random number for word position
final_word = random.randint(0, len(words)-1)
print("Position:", final_word)
print("Word at position:", words[final_word])
# Set an empty final_word.
final_word = ""
password_is_valid = False
# Print 100 empty lines.
for i in range(0, 100):
print()
# Keep track of the player's progress.
counter = 0 # The current turn number.
guessed_correctly = False # Whether Player 2 has guessed correctly.
all_guess_symbols = "" # All of the symbols.
# Loop 10 times, maximum
while counter < 10:
# Ask for player 2's guess.
guess_number = counter + 1
guess = input("guess the final_word: ")
# Only consider the guess if it is four digits long.
if len(guess) == 5:
# Create a string with the symbols for the current guess.
current_guess_symbols = ""
for i in range(0, 5):
if guess[0] == final_word[0]:
current_guess_symbols = current_guess_symbols + "🟢"
else:
current_guess_symbols = current_guess_symbols + "🟥"
# Add the current guess' shapes to the whole game's shapes.
all_guess_symbols = all_guess_symbols + current_guess_symbols + "\n"
print(current_guess_symbols)
# If the guess symbols are all green circles, Player 2 won.
# Set the
if current_guess_symbols == "🟢🟢🟢🟢":
# Set the counter to 10 to immediately end the game loop.
counter = 10
guessed_correctly = True
else:
# Continue to the next guess.
counter = counter + 1
else:
# Print an error message if the guess is too short.
print("Sorry, your guess is too short. Enter a 5 digit final_word.")
# Print all guess symbols at the end of the game.
print()
print(all_guess_symbols)
print()
# Print the ending message.
if guessed_correctly == True:
print("Congratulations, you guessed the final_word!")
else:
print("Sorry, you did not guess in time.")
print("The final_word was: " + final_word)
You are getting IndexError at this line:
if guess[0] == final_word[0]:
This is most likely because either guess or final_word is an empty string. You have applied no input validation to the user's guess, so that could easily become an empty string. (also that line should probably be if guess[i] == final_word[i]:).
However with the code as you've written, final_word is guaranteed to be an empty string.
Your code at lines 14-21 does successfully read a word from the specified file (assuming your file is non-empty), but then at line 23 you have:
# Set an empty final_word.
final_word = ""
Which resets the variable to the empty string.
So I'm making a hanging man game and I have run into a problem regarding indexes. Basically, I want to find the index of a letter inside a secret word, the problem is that if the secret word includes two letters that are the same, for instance, "guacamole", where the letter a has the index of 2 and 4 but when I want to find the index of a, it only prints "2" and not "4". Is there a way around this? Thanks in advance!
Part of code where problem occurs:
for letter in secret_word:
if user_guess == letter:
current_word_index = secret_word.find(letter)
print(current_word_index) #Not in full program, only to test errors.
Full code:
#Hanging man
import string
space = "\v"
dbl_space = "\n"
secret_word = str(input("Enter a secret word: "))
guess_low = list(string.ascii_lowercase)
used_letters = []
user_errors = 0
user_errors_max = 1
secret_word_index = int(len(secret_word))
secret_word_placeholder = list(range(secret_word_index))
while user_errors != user_errors_max:
user_guess = str(input("Enter a letter: "))
if len(user_guess) != 1:
print("You have to pick one letter")
if user_guess in guess_low:
guess_low.remove(user_guess)
used_letters.extend(user_guess)
print(used_letters)
for letter in secret_word:
if user_guess == letter:
current_word_index = secret_word.find(letter)
if user_errors == user_errors_max:
print("You lost the game, the secret word was: " + secret_word)
This is an example of what you are trying to achieve. use list comprehension.
string='hello'
letter='l'
[idx for idx,ch in enumerate(string) if ch==letter]
Python's string find accepts a start parameter that tells it where to start searching:
>>> "guacamole".find('a')
2
>>> "guacamole".find('a', 3)
4
Use a loop, and use the index of the last hit you found + 1 as the start parameter for the next call.
Another more verbose solution might be:
str1 = "ooottat"
def find_all_indices(text, letter):
indices_of_letter = []
for i, ch in enumerate(text):
if ch == letter:
indices_of_letter.append(i)
return indices_of_letter
print(find_all_indices(str1, 'o'))
Side note:
Indexes is the nontechnical plural of index. the right technical plural for index is indices
Yes, if you instantiate a new_variable to be the secret_word variable before the for loop, the in the line current_word_index = secret_word.find(letter) change secret_word.find(letter) to new_variable .find(letter) then below the if statement write new_variable = new_variable [1:] which will remove the letter just found.
so your code would look something like:
new_variable = secret_word
for i in secret_word
if user_guess == letter:
current_word_index = new_variable.find(letter)
#I would do print(current_word_index) this will show the index
#Or current_word_index = current_word_index + ',' + new_variable.find(letter)
new_variable= new_variable[1:] #this will take away your letter.
Basically my plan was to return text with random-sized letters in words i.e. "upper" or "lower". The script is working, though it seems raw (I am a Beginner and I'd appreciate some corrections from You).
The problem is:
It is not consistent. With that said, it can print word 'about' even if it should be 'About' or something similar.
I want to be sure that the maximum of UPPER or lower letters in a row do not exceed 3 letters. and I don't know how to do it.
Thank you in advance.
#!/usr/bin/env python3
import random
message = input()
stop = ''
def mocking(message):
result = ''
for word in message:
for letter in word:
word = random.choice(random.choice(letter.upper()) + random.choice(letter.lower()))
result += word
return result
while stop != 'n':
print(mocking(message))
stop = input("Wanna more? y/n ").lower()
if stop == 'n':
break
else:
message = input()
You need to split the input into words, decide how many positions inside the word you want to change (minimum 3 or less if the word is shorter).
Then generate 3 unique positions inside the word (via random.sample) to change, check if upper then make lower else make upper. Add to resultlist and join words back together.
import random
message = "Some text to randomize"
def mocking(message):
result = []
for word in message.split():
len_word = len(word)
# get max 3 random positions
p = random.sample(range(len_word),k = min(len_word,3))
for position in p:
l = word[position]
if l.isupper():
word = word[:position] + l.lower() + word[position+1:]
else:
word = word[:position] + l.upper() + word[position+1:]
result.append(word)
return ' '.join(result)
while True:
print(mocking(message))
stop = input("Wanna more? y/n ").lower()
if stop == 'n':
break
else:
message = input()
See Understanding slice notation for slicing
At most 3 modifications? I would go with something like this.
def mocking(message):
result = ''
randomCount = 0
for word in message:
for letter in word:
newLetter = random.choice( letter.upper() + letter.lower() )
if randomCount < 3 and newLetter != letter:
randomCount += 1
result += newLetter
else:
result += letter
randomCount = 0
return result
If the random choice has modified the letter then count it.
I'm making a hangman game and have found a problem with my methodology for updating the answer. I have a variable that adds underscores equal to the amount of letters in the word the player needs to guess. However I can't figure out how to effectively update that when the player guesses a correct letter.
Here is my code
import random
'''
HANGMAN IMAGE
print(" _________ ")
print("| | ")
print("| 0 ")
print("| /|\\ ")
print("| / \\ ")
print("| ")
print("| ")
'''
def game():
print('''Welcome to hangman, you must guess letters to fill in the word.
Incorrect guesses will use up a turn, you have 7 turns before you lose.''')
lines = open("wordBank.txt").read()
line = lines[0:]
words = line.split()
myword = random.choice(words).lower()
letters = len(myword)
print("Your word has " + str(letters) + " letters.")
underscores = ""
for x in range(0, letters):
underscores += "_ "
print(underscores)
print(myword)
l = set(myword)
turn = 0
guesses = []
def guess():
thisGuess = input("Type a letter and press Enter(Return) to guess: ")
if thisGuess.lower() in l:
else:
print("Boo")
guess()
game()
You probably need to reword your question as it's not clear what you are asking. But you should look into string splicing. If they guessed the letter "a" and it goes in the third slot then you could do something like
underscores[:2] + 'a' + underscores[3:]
adapt for your code but that would replace the 3rd underscore with an "a".
UPDATE:
don't use a set, look up the index as you go. Try something like this
for index, letter in enumerate(my_word):
if letter == guessed_letter:
if not index == len(my_word) -1
underscores = underscores[:index] + letter + underscores[index+1:]
else:
underscores = undescores[:-1] + letter
Another possible approach (in Python 2.7, see below for 3):
trueword = "shipping"
guesses = ""
def progress():
for i in range(len(trueword)):
if trueword[i] in guesses:
print trueword[i],
else:
print "-",
print ""
This works by checking for each letter if it's been guessed in guesses, and printing that letter. If it hasn't been guessed, it prints -. When you put a comma at the end of a print (as in print "-",) it won't automatically print a newline, so you can continue printing on the same line. print "" prints a null string with a newline, finishing the line.
Then guessing becomes:
guesses += guess
Output is:
guesses = ''
- - - - - - - -
guesses = 'sip'
s - i p p i - -
In Python 3:
trueword = "shipping"
guesses = ""
def progress():
for i in range(len(trueword)):
if trueword[i] in guesses:
print(trueword[i], end='')
else:
print("-", end='')
print('')
you add the end='' parameter to remove the newline, instead of the comma. If you want the spaces between them, you can add sep=' ' as well to specify the separator.
Also, because list comprehensions are awesome (and this works in 2.7 & 3):
def progress():
ans = [word[x] if word[x] in guesses else '-' for x in range(len(word))]
print(' '.join(ans))
Does the same thing via list comprehensions... which are a very strong feature in python.
I have a game where the user guesses letters. They are shown a blank version of the mystery work (_____ for example, the _'s are equal to number of characters in the word). The program knows the word, and needs to replace every index in the blanked out version of the word if the letter they guess is present in the mystery word.
For example, if the player guesses "p" and the word is "hippo" they will be shown __pp_. But, my code will only replace the first instance of "p", giving __p__ instead.
Would this be easier to tackle as a list problem?
mistakes = 0
complete = False
t = False
words = ['cow','horse','deer','elephant','lion','tiger','baboon','donkey','fox','giraffe']
print("\nWelcome to Hangman! Guess the mystery word with less than 6 mistakes!")
# Process to select word
word_num = valid_number()
word = words[word_num]
#print(word)
print("\nThe length of the word is: ", str(len(word)))
attempt = len(word)*"_"
# Guesses
while not (mistakes == 6):
guess = valid_guess()
for letter in word:
if guess == letter:
print("The letter is in the word.")
position = word.index(guess)
attempt = attempt [0:position] + guess + attempt [position + 1:]
print("Letters matched so far: ", attempt)
t = True
while (t == False):
print("The letter is not in the word.")
print("Letters matched so far: ", attempt)
mistakes = mistakes + 1
hangMan = ["------------", "| |", "| O", "| / |", "| |", "| / |\n|\n|"]
hang_man()
t = True
t = False
answer = 'hippo'
fake = '_'*len(answer) #This appears as _____, which is the place to guess
fake = list(fake) #This will convert fake to a list, so that we can access and change it.
guess = raw_input('What is your guess? ') #Takes input
for k in range(0, len(answer)): #For statement to loop over the answer (not really over the answer, but the numerical index of the answer)
if guess == answer[k] #If the guess is in the answer,
fake[k] = guess #change the fake to represent that, EACH TIME IT OCCURS
print ''.join(fake) #converts from list to string
This runs as:
>>> What is your guess?
p
>>> __pp_
To loop over everything, I did not use index, because index only returns the first instance:
>>> var = 'puppy'
>>> var.index('p')
0
So to do that, I analyzed it not by the letter, but by its placement, using a for that does not put k as each letter, but rather as a number so that we can effectively loop over the entire string without it returning only one variable.
One could also use re, but for a beginning programmer, it is better to understand how something works rather than calling a bunch of functions from a module (except in the case of random numbers, nobody wants to make their own pseudo-random equation :D)
Based on Find all occurrences of a substring in Python:
import re
guess = valid_guess()
matches = [m.start() for m in re.finditer(guess, word)]
if matches:
for match in matches:
attempt = attempt[0:match] + guess + attempt[match+1:]
print("Letters matched so far: ", attempt)
else:
.
.
.