I'm writing a hangman.
The script consist of two functions:
setup() which initializes all the variables (the word, number of guesses, lists of letters to check etc) and main (which is the main game loop).
The last thing setup() does is calling the main().
From main() you can invoke setup() to reset the game.
By design, the main() function needs to access the variables created by setup() and vice versa. It requires me to heavily use "global" statements - for all declarations within setup().
How should I approach it to avoid having "bad" global variables?
import random
def setup():
with open("Ex30_Pick_a_word/sowpods.txt", "r") as f:
lines = [x for x in f.readlines()]
count = 0
for line in lines:
count += 1
global selected_word
selected_word = lines[random.randint(1, count)].rstrip()
## initialize variables
global guess_state
guess_state = ['-' for letter in selected_word]
global bad_letters
bad_letters = ""
global chances
chances = 6
## start game
print("\n\n\n#### WELCOME TO HANGMAN ###")
print("Word to guess is: " + selected_word + ".") ## debug only ;)
main()
def main():
while True:
success = False
print("\n""The word is:")
display = "".join(guess_state)
print(display)
global chances
print("You've got " + str(chances) + " chances left.")
guess_letter = input("Guess a letter:").capitalize()
## logic
for letter_id, letter in enumerate(selected_word):
if guess_letter == letter: ## if found
if guess_state[letter_id] == "-": ## if not yet found
guess_state[letter_id] = letter
success = True
break
if not success:
global bad_letters
if guess_letter in bad_letters:
print("You've aread tried: \"" + guess_letter + "\"")
else:
bad_letters += guess_letter + " "
chances -= 1
if ''.join(guess_state) == selected_word:
print("You've won, the word was: " + selected_word)
again = input("Do you want to play again? (y/n)")
if again == "y":
setup()
break
if len(bad_letters) > 0:
print("\nBad letters: " + bad_letters)
if chances == 0:
print("Game Over.")
again = input("Do you want to play again? (y/n)")
if again == "y":
setup()
break
setup()
Related
So I'm trying to make a little hangman game in Python. I've managed it already, but I've seen lots of other people using functions to achieve this. Here's my code without using function:
from hangman_words import word_list
import random
def select_word():
return random.choice(word_list)
hidden_word = select_word()
char_lines = "_" * len(hidden_word)
guessed_letters = []
Lives = 8
game_start = input("Would you like to play HangMan? (Y/N)\n")
if game_start.upper() == "Y":
prompt_user = True
elif game_start.upper() == "N":
print("*Sad Python Noises*")
prompt_user = False
else:
print("You to say 'Yes'(Y) or 'No'(N)")
while (Lives > 0 and prompt_user == True):
user_input = input("Choose a letter!\n\n")
user_input = user_input.upper()
if user_input.upper() in guessed_letters:
print("\nYou have already guessed that letter. Choose something else!")
elif hidden_word.count(user_input) > 0:
for i, L in enumerate(hidden_word):
if L == user_input:
char_lines = char_lines[:i] + hidden_word[i] + char_lines[i+1:]
print("\nCorrect!")
print(char_lines)
else:
guessed_letters.append(user_input)
print("\nNope, that letter isn't in the word. Try again!")
Lives -= 1
if char_lines == hidden_word:
print("Well done! You won the game!")
print(f"You had {Lives} lives remaining and your incorrect guesses were:")
print(guessed_letters)
exit()
print(f"Lives remaining: {Lives}")
print(f"Incorrect guessed letters: {guessed_letters}")
print(char_lines)
if (Lives == 0 and prompt_user == True):
print("You have ran out of lives and lost the game!.....you suck")
if prompt_user == False:
print("Please play with me")
My current code for the version using functions is like this:
from hangman_words import word_list
import random
def select_word():
global blanks
selected_word = random.choice(word_list)
blanks = "_" * len(selected_word)
return selected_word, blanks
def game_setup():
global lives
global guessed_letters
global hidden_word
lives = 20
guessed_letters = []
hidden_word = select_word()
return lives, guessed_letters, hidden_word
def play_option():
game_start = (input("Would you like to play HangMan? (Y/N)\n")).upper()
if game_start == "Y":
global prompt_user
prompt_user = True
game_setup()
return prompt_user
elif game_start == "N":
print("*Sad Python Noises*")
exit()
else:
print("You need to say 'Yes'(Y) or 'No'(N)")
def user_input_check(user_input):
if type(user_input) != str: # [Want to check if unput is of tpye Str]
print("Please input letter values!")
elif user_input != 1:
print("Please only input single letters! (e.g. F)")
else:
pass
def game_board(user_input, hidden_word, guessed_letters, blanks, lives):
if user_input in guessed_letters:
print("You have already guessed that letter. Choose something else!")
elif hidden_word.count(user_input) > 0:
for i, L in enumerate(hidden_word):
if L == user_input:
blanks = blanks[:i] + hidden_word[i] + blanks[i+1:]
print("Correct!")
print(blanks)
else:
guessed_letters.append(user_input)
print("Nope, that letter isn't in the word. Try again!")
lives -= 1
print(f"Lives remaining: {lives}")
print(f"Incorrect guessed letters: {guessed_letters}")
print(blanks)
return
def win_check(blanks, hidden_word, lives, guessed_letters):
if blanks == hidden_word:
print("Well done! You won the game!")
print(f"You had {lives} lives remaining and your incorrect guesses were:")
print(guessed_letters)
exit()
def lives_check(lives, prompt_user):
if (lives == 0 and prompt_user == True):
print("You have ran out of lives and lost the game!.....you suck")
exit()
play_option()
while (lives > 0 and prompt_user == True):
user_input = (input("Choose a letter!\n\n")).upper()
user_input_check(user_input)
game_board(user_input, hidden_word, guessed_letters, blanks, lives)
win_check(blanks, hidden_word, lives, guessed_letters)
lives_check(lives, prompt_user)
I think I should be using classes instead of functions really, but I'd like to get it work with functions first, then try adapting it to work with classes. If I'm using functions, how does return actually work? Does returning variable names put those variables within the global name-space? Or does return only work when you assign the returned value to a global name-space variable? Like this:
def add_one(a):
return a + 1
b = add_one(3) # b = 4
You're correct, return works by setting the function to be equal to whatever you return it as.
I'm writing code with Python 2.7 that checks if a character is present in a input string but Python keeps skipping part of my if-statement.
Each time I run the code and enter a guess character value, the execution goes straight to the else statement and never executes the if(guess in PuzzleSetter) == True block at all.
What am I doing wrong?
PuzzleSetter = " "
List = []
def setPuzzle():
PuzzleSetter = raw_input("Puzzle setter set your word: ")
PuzzleSetter = PuzzleSetter.replace(" ", "")
print("Guessing player try guessing: "+PuzzleSetter.upper())
time.sleep(5)
print(chr(27) + "[2J")
List = [' __ ']*len(PuzzleSetter)
print("\n")
print(List)
while(True):
guess = raw_input("\nGuessing player make your guess: ")
if len(guess) != 1:
print("You are meant to enter a single letter")
continue
else:
guess = guess.upper()
print(guess)
if(guess in PuzzleSetter) == True:
finder = PuzzleSetter.find(guess)
print(PuzzleSetter+" contains "+str(PuzzleSetter.count(guess))+" "+guess+"'s")
for count in range(PuzzleSetter.count(guess)):
List[finder] = guess.upper()
finder = PuzzleSetter.find(guess, finder+1)
print(List)
if List.count("__") == 0:
print("Guessing player wins!")
break
else:
HangerMan()
enter += 1
if enter == 7:
print("Guessing player lost!")
print("\nPlayer two becomes the puzzle setter")
setPuzzle()
As I thought, you're leaving PuzzleSetter as input and not converting it to upper case like you are guess. If it contains any lower case letters they will never be found. Try this:
PuzzleSetter = raw_input("Puzzle setter set your word: ")
PuzzleSetter = PuzzleSetter.replace(" ", "")
PuzzleSetter = PuzzleSetter.upper()
print("Guessing player try guessing: "+PuzzleSetter)
There is one small problem with my code , after I get all the letters correct, I had to enter another letter only it will show that I got it right. What is the problem?
import random
import string
import sys
def split(word):
return list(word)
alphabet = 'abcdefghijklmnopqrstuvwxyz'
list(alphabet)
words = ['hat','pop' ,'cut' , 'soup' , 'you' , 'me' , 'gay' , 'lol' ]
guess_word = []
wrong_letters_storage = []
secret_word = random.choice(words)
word_length = print("the length of the word is " + str(len(secret_word)))
correct_letters = split(secret_word)
def words():
for letter in secret_word:
guess_word.append("-")
return print("the words that you are guessing is " + str(guess_word))
def guessing():
while True:
c = 0
b = 7
while c <= 7:
print("")
hide = ""
print("you have " + str(b) + " guess left")
print("Wrong letters : " + str(wrong_letters_storage))
command = input("guess: ").lower()
if not '-' in guess_word:
print("you win!")
break
elif command == 'quit':
print("thank you for playing my game")
break
else:
if not command in alphabet :
print("pick an alphabet")
elif command in wrong_letters_storage:
print("you have picked this word")
else :
if command in secret_word :
print("right")
c += 1
b -= 1
for x in range(0, len(secret_word)):
if correct_letters[x] == command:
guess_word[x] = command
print(guess_word)
elif not command in secret_word :
print("wrong")
wrong_letters_storage.append(command)
c += 1
b -= 1
else :
print("error")
print("*"*20)
return print("Thank you for playing my game")
words()
guessing()
print("the words that you are guessing is " + secret_word )
Your code has several "problems":
you check if the current solution has no more '-' in it, after you ask for the next character input()
return print("whatever") returns None because the print function prints and returns None
you use variables with single_letter_names that make it hard to know what they are for
you use list's instead of set()'s for lookups (its fine here, but not optimal)
You can fix your problem by moving the test statement before the input() command:
# your code up to here
while True:
c = 0
b = 7
while c <= 7:
if not '-' in guess_word:
print("you win!")
break
print("")
hide = ""
print("you have " + str(b) + " guess left")
print("Wrong letters : " + str(wrong_letters_storage))
command = input("guess: ").lower()
if command == 'quit':
print("thank you for playing my game")
break
else:
# etc.
It would probably be better to do some more refaktoring:
import random
import string
import sys
def join_list(l):
return ''.join(l)
def guessing():
# no need to put all this in global scope
alphabet = frozenset(string.ascii_lowercase) # unchangeable set of allowed letters
words = ['hat', 'pop', 'cut', 'soup', 'you', 'me', 'beautiful', 'lol']
secret = random.choice(words) # your random word
secret_word = list(secret.lower()) # your random word as lowercase list
wrong = set() # set of wrongly guessed characters
right = set() # set of already correctly guessed characters
correct = frozenset(secret_word) # set of letters in your word, not changeable
guess_word = ['-' for k in correct] # your guessed letters in a list
guesses = 7
guessed = 0
print("The length of the word is ", len(secret))
# loop until breaked from (either by guessing correctly or having no more guesses)
while True:
print("")
print(f"you have {guesses-guessed} guess left")
if wrong: # only print if wrong letters guessed
print(f"Wrong letters : {wrong}")
# print whats know currently:
print(f"Guess so far: {join_list(guess_word)}")
command = input("guess: ").strip().lower()
try:
if command != "quit":
command = command[0]
except IndexError:
print("Input one letter")
continue
if command == 'quit':
print("thank you for playing my game")
break
else:
if command not in alphabet:
print("pick an alphabet")
continue
elif command in (wrong | right):
print("you already picked this letter")
continue
else :
guessed += 1
# always lookup in set of lowercase letters
if command in correct:
right.add(command)
for i,letter in enumerate(secret_word):
if command == letter:
# use the correct capitalisation from original word
guess_word[i] = secret[i]
else:
print("wrong")
wrong.add(command)
print("*"*20)
# break conditions for win or loose
if join_list(secret_word) == join_list(guess_word):
print("You won.")
break
elif guessed == guesses:
print(f"You lost. Word was: {join_list(secret_word)}")
break
guessing()
I've programmed a game that takes a song and artist name from an external file. The program prints the artist name but masks the title of the song, and the user must guess the title correctly to earn points. That works fine, but I want to add a time limit, so they only have 60secs to get the highest score they possibly can.
Here's the part of the code I'm referencing:
def pickSong_random():
score=0
lives=5
songFile = open("F_Songs.txt","r")
songList = songFile.readlines() #Reads from the bridged file
songFile.close()
while True:
chosenSong = random.choice(songList)
chosenSong = chosenSong.strip("\n")
artistAndSong = chosenSong.split(":") #Defines song split
toDisplay = ""
toDisplay += artistAndSong[0] + ": "
songTitleWords = artistAndSong[1].split(" ")
for word in songTitleWords:
#loop through
toDisplay += word[0] + " "
print(toDisplay)
#print("2" +toDisplay)
toDisplay = toDisplay.strip("None")
guesses = 0
while guesses <2:
guesses += 1
guess = input("[Guess]: ")
#Guess checking
if guess.lower() == artistAndSong[1].lower():
print("Correct! The song was " + artistAndSong[1] + " by " + artistAndSong[0])
print("It took you", guesses, "guess(es)!")
if guesses == 1:
print ("(+3 points)")
print("\n")
score += 3
break
elif guesses == 2:
print ("(+1 point)")
print("\n")
score += 1
break
else:
print("That's incorrect, guess again.\n")
lives = lives-1
if lives == 0:
print ("You have no more lives to continue! Your score was:",score)
time.sleep(3)
slow_print ("Would you like to play again?")
playAgain = input("[Y/N]: ")
if playAgain == ("n") or playAgain == ("N"):
sys.exit()
if playAgain == ("Y") or playAgain == ("y"):
print ("Your last score was",score,", lets see if you can beat it this time...")
time.sleep(1)
print ("\n")
pickSong_random()
I've tried playing around with this concept, but no luck thus far:
import time
countdown=True
time=60
while countdown == True:
time = time-1
time.sleep(1.0)
print (time)
countdown=True
if time == 0:
print ("You've ran out of time!")
UPDATE 1
My projects code has now changed quite a far bit
#Casey_Neale
import sys
import random
import time
import math
import csv
import time, sys
newaccounts=True
loggedIn=False
yn=True
def tutorial(): #Games introduction
slow_print("Your aim is to get as many points as possible...")
print("\n")
time.sleep(1.5)
slow_print("You need to guess the name of each song to gain points...")
print("\n")
time.sleep(1.5)
slow_print("You have two guesses for each song...")
print("\n")
time.sleep(1.5)
slow_print ("The artist name is provided for you...")
time.sleep(0.5)
print("\n")
def slow_print(s):
for c in s:
sys.stdout.write( '%s' % c )
sys.stdout.flush()
time.sleep(0.03)
def leaderboard():
print ("\n")
print ("⬇ Check out the leaderboard ⬇") #LEADERBOARD SECTION
f = open('H_Highscore.txt', 'r')
leaderboard = [line.replace('\n','') for line in f.readlines()]
for i in leaderboard:
print(i)
f.close()
time.sleep(10)
sys.exit()
def loginsys():
doublecheck=True
while doublecheck == True:
verifyRegister = input ("➡Welcome | Are you a registered user?\n[Y/N]: ")
print (" ")
if verifyRegister == "n" or verifyRegister == "N": #If the user is not already registered
if newaccounts == True:
loop=True
while loop == True:
username = input ("Please enter a username\n[User]: ")#Prompts the user to provide a desired username
print (" ")#Prompts for username
checkusername = input ("Please retype your username\n[Verify]: ")#Verifys username
print (" ")#Prompts to verify username
if checkusername != username:
print ("Invalid, please try again")
loop=True
else:
loop=False
time.sleep(0.5)
passloop=True
while passloop == True:
password = input ("Please enter a password\n[Password]: ") #Prompts the user to provide a desired password
print (" ")#Prompts for password
checkpassword = input ("Please retype your password\n[Verify]: ") #Verifys password
print (" ")#Prompts to verify password
if checkpassword != password:
print ("Invalid, please try again")
print (" ")
passloop=True
else:
passloop=False
file = open("C_AccountData.txt","a") #Opens the file C_AccountData.txt in write mode/opens connection
file.write("USRN:") #Prefix Username to make the file easier to read
file.write(username) #Writes the username
file.write("|") #Partition for visual ease to make the file easier to read
file.write("PSWD:") #Prefix Password to make the file easier to read
file.write(password)#Writes the password
file.write("\n") #New line to make the file easier to read
file.close() #Closes file/ends connection
print ("✓Your account has been created") #Verifies that the account has been made to the user
time.sleep(2)
print ("\n")
doublecheck=True #Loop
if verifyRegister == "Y" or verifyRegister == "y":
loop=True
if loop == True:
user = input("[User]: ")
passw = input("[Password]: ")
f = open("C_AccountData.txt", "r")
for line in f.readlines():
uspwd = line.split("|")
us = uspwd[0]
pw = uspwd[1]
if (user in us) and (passw in pw):
loop=False
print("Login successful, welcome",user)
doublecheck=False
else:
if loop == True:
print ("\n")
print ("Sorry, your account details were not recognised. ")
else:
if verifyRegister != "Y" or verifyRegister != "y" or verifyRegister != "N" or verifyRegister != "n" or verifyRegister !="backup":
print("\n")
doublecheck=True
def pickSong_random():
score=0
lives=5
songFile = open("F_Songs.txt","r")
songList = songFile.readlines() #Reads from the bridged file
songFile.close()
while True:
chosenSong = random.choice(songList)
chosenSong = chosenSong.strip("\n")
artistAndSong = chosenSong.split(":") #Defines song split
toDisplay = ""
toDisplay += artistAndSong[0] + ": "
songTitleWords = artistAndSong[1].split(" ")
for word in songTitleWords:
#loop through
toDisplay += word[0] + " "
print(toDisplay)
#print("2" +toDisplay)
toDisplay = toDisplay.strip("None")
guesses = 0
while guesses <2:
guesses += 1
guess = input("[Enter your guess]: ")
#Guess checking
if guess.lower() == artistAndSong[1].lower():
print("✓Correct! The song was " + artistAndSong[1] + " by " + artistAndSong[0])
print("It took you", guesses, "guess(es)!")
if guesses == 1:
print ("\n")
print ("⬆(+3 points)⬆")
print("\n")
score += 3
break
elif guesses == 2:
print ("\n")
print ("⬆(+1 point)⬆")
print("\n")
score += 1
break
else:
print("❌The song name isn't",guess,"\n")
lives = lives-1
if guesses == 2:
print ("Sorry, you couldn't guess the song.")
print ("\n")
if lives == 0:
print ("You have no more lives to continue! Your score was:",score)
time.sleep(3)
print("\n")
slow_print ("Would you like to play again?")
playAgain = input("\n[Y/N]: ")
if playAgain == ("n") or playAgain == ("N"):
print ("\n")
user = str(input("Enter a name to save your highscore: ")) #user variable is not saved from the login system as it is defined as a function separately
file = open ("H_Highscore.txt","a")
file.write(user)
file.write(",")
file.write(str(score)) #(int(x)) can not be written
file.write("pts")
file.write("\n")
file.close()
time.sleep(0.5)
leaderboard()
sys.exit()
if playAgain == ("Y") or playAgain == ("y"):
print ("Your last score was",score,", lets see if you can beat it this time...")
time.sleep(1)
print ("\n")
pickSong_random()
loginsys() #LOGIN PROTOCOL
time.sleep(3)
print("\n")
tutorial() #TUTORIAL PROTOCOL
slow_print ("Prepare yourself! The game will begin in...\n")
time.sleep(0.5)
print("\n")
slow_print("5...")
time.sleep(0.5)
print("\n")
slow_print("4...")
time.sleep(0.5)
print("\n")
slow_print ("3...")
time.sleep(0.5)
print("\n")
slow_print ("2...")
time.sleep(0.5)
print("\n")
slow_print ("1...")
time.sleep(0.5)
print("\n")
pickSong_random() #GAME PROTOCOL
sys.exit() #EXIT PROTOCOL
Here's how to do it with the threading.Timer() class I suggested in a comment. These can be configured to delay a specified amount of time and the call as function of your choosing.
In the code below I've defined a callback function named timeout() and a global variable named time_ran_out that it sets to True when the timer expires. There's comments in the added code describing what's being done. All the callback function does is set the value of a variable. Other code in the pickSong_random() function checks the value of this variable to determine if the callback function got called or not.
The nice thing about Timer instances (and functions they callback) is that their execution occurs in the background, in parallel with the the main thread which is running the game itself—so using them doesn't impact game's execution or code very much.
Note I also reformatted your code so it follows PEP 8 - Style Guide for Python Code guides so it's a lot more readable (and easier to work on) in my opinion.
import random
import sys
import time
from threading import Timer
TIMELIMIT = 10.0 # Seconds (set low for testing).
def slow_print(s):
for c in s:
sys.stdout.write('%s' % c)
sys.stdout.flush()
time.sleep(0.03)
def pickSong_random():
# Local Timer callback function.
def timeout():
nonlocal time_ran_out # Reference variable defined in enclosing scope
# (so a local one isn't created automatically).
time_ran_out = True
score = 0
lives = 5
songFile = open("F_Songs.txt", "r")
songList = songFile.readlines() # Reads from the bridged file
songFile.close()
while True:
chosenSong = random.choice(songList)
chosenSong = chosenSong.strip("\n")
artistAndSong = chosenSong.split(":") # Defines song split
toDisplay = ""
toDisplay += artistAndSong[0] + ": "
songTitleWords = artistAndSong[1].split(" ")
for word in songTitleWords:
# loop through
toDisplay += word[0] + " "
print(toDisplay)
# print("2" +toDisplay)
toDisplay = toDisplay.strip("None")
guesses = 0
timer = Timer(TIMELIMIT, timeout) # Create a timer thread object.
time_ran_out = False # Define local variable the callback function modifies.
timer.start() # Start the background timer.
while guesses < 2:
if time_ran_out:
print('Times up!')
break
guesses += 1
guess = input("[Enter your guess]: ")
# Guess checking
if guess.lower() == artistAndSong[1].lower():
print("✓Correct! The song was " + artistAndSong[1]
+ " by " + artistAndSong[0])
print("It took you", guesses, "guess(es)!")
if guesses == 1:
print("\n")
print("↑(+3 points)↑")
print("\n")
score += 3
break
elif guesses == 2:
print("\n")
print("↑(+1 point)↑")
print("\n")
score += 1
break
else:
print("╳The song name isn't", guess, "\n")
lives = lives-1
if guesses == 2:
print("Sorry, you couldn't guess the song.")
print("\n")
if lives == 0:
print("You have no more lives to continue! Your score was:", score)
time.sleep(3)
print("\n")
slow_print("Would you like to play again?")
playAgain = input("\n[Y/N]: ")
if playAgain == ("n") or playAgain == ("N"):
print("\n")
# user variable is not saved from the login system as it is
# defined as a function separately
user = str(input("Enter a name to save your highscore: "))
file = open ("H_Highscore.txt", "a")
file.write(user)
file.write(",")
file.write(str(score)) # (int(x)) can not be written
file.write("pts")
file.write("\n")
file.close()
time.sleep(0.5)
leaderboard()
sys.exit()
if playAgain == ("Y") or playAgain == ("y"):
print("Your last score was", score,", lets see if you can beat it this time...")
time.sleep(1)
print("\n")
pickSong_random()
if __name__ == '__main__':
pickSong_random()
Simply record the start time, and break from your loop if the time is up. By sleeping you make your program hibernate and the user can not do anything. So "fasteness" does not make any difference because you can't do anything while the program sleeps:
import random
import datetime
correct = 0
start = datetime.datetime.now()
while True:
print("Math test. Add , dont screw up, you got {}s left".
format(20-(datetime.datetime.now()-start).seconds))
a,b = random.choices(range(1,20),k=2)
c = input(" {:>2} + {:>2} = ".format(a,b))
if (datetime.datetime.now()-start).seconds > 20:
print("Times up. Score: {}".format(correct))
break
try:
if a+b == int(c):
correct += 1
print("Correct")
else:
print("Wrong")
except:
print("Wrong")
Output:
Math test. Add , dont screw up, you got 20s left
17 + 8 = 23
Wrong
Math test. Add , dont screw up, you got 18s left
10 + 2 = 12
Correct
Math test. Add , dont screw up, you got 14s left
1 + 7 = 8
Correct
Math test. Add , dont screw up, you got 12s left
5 + 19 = 24
Correct
Math test. Add , dont screw up, you got 8s left
4 + 3 = 7
Correct
Math test. Add , dont screw up, you got 5s left
3 + 18 = 21
Correct
Math test. Add , dont screw up, you got 3s left
15 + 12 = 27
Correct
Math test. Add , dont screw up, you got 1s left
7 + 8 = 15
Times up. Score: 6
It turns out you were actually reassigning the "time" module to an integer of 60, overwriting the library, which is why it had no attribute ".sleep()". Also the countdown part is irrelevant and a bit redundant. Anyways, this revised bit of code worked for me:
import time
sec=60
while sec != 0:
print(sec)
sec = sec-1
time.sleep(1)
print ("You've ran out of time!")
Hope this helps!
While Om Agarwal may have a possible solution, you may also want to consider using a non-blocking approach in your game using the built-in pygame time.
start_ticks = pygame.time.get_ticks()
while guesses < 2:
# OTHER GAME CODE HERE
seconds = (pygame.time.get_ticks() - start_ticks) / 1000
if seconds > 60:
print ("You've ran out of time!")
break
Cheers!
Edit 1: Added example modification.
import pygame
import time
import random
import sys
def pickSong_random():
score = 0
lives = 5
songFile = open("F_Songs.txt", "r")
songList = songFile.readlines() # Reads from the bridged file
songFile.close()
while True:
chosenSong = random.choice(songList)
chosenSong = chosenSong.strip("\n")
artistAndSong = chosenSong.split(":") # Defines song split
toDisplay = ""
toDisplay += artistAndSong[0] + ": "
songTitleWords = artistAndSong[1].split(" ")
for word in songTitleWords:
# loop through
toDisplay += word[0] + " "
print(toDisplay)
# print("2" +toDisplay)
toDisplay = toDisplay.strip("None")
guesses = 0
start_ticks = pygame.time.get_ticks()
while guesses < 2:
guesses += 1
guess = input("[Guess]: ")
seconds = (pygame.time.get_ticks() - start_ticks) / 1000
if seconds > 60:
print("You've ran out of time!")
break
# Guess checking
if guess.lower() == artistAndSong[1].lower():
print("Correct! The song was " + artistAndSong[1] + " by " + artistAndSong[0])
print("It took you", guesses, "guess(es)!")
if guesses == 1:
print("(+3 points)")
print("\n")
score += 3
break
elif guesses == 2:
print("(+1 point)")
print("\n")
score += 1
break
else:
print("That's incorrect, guess again.\n")
lives = lives - 1
if lives == 0:
print("You have no more lives to continue! Your score was:", score)
time.sleep(3)
slow_print("Would you like to play again?")
playAgain = input("[Y/N]: ")
if playAgain == "n" or playAgain == "N":
sys.exit()
if playAgain == "Y" or playAgain == "y":
print("Your last score was", score, ", lets see if you can beat it this time...")
time.sleep(1)
print("\n")
pickSong_random()
so i have this hangman code... again, thanks in advance, and it reveals the words one by one and that works fine, but when there is multiple words like two l's in hello and two p's in apple it only reveals one not two. i don't know why this is and I've done some google greasing and what came up was enumerating but I've tried that to no avail.
This is the code:
def hangman():
global fullWordList
fullWordList = []
global wrongnums
wrongnums =[]
print("What is the word to be guessed?")
print("Words means that there are no numbers")
global guessnum
guessnum=input('>')
fullWord = guessnum
for line in fullWord:
for c in line:
fullWordList.append(c)
print (fullWordList)
print("how many chances?")
global chances
chances=int(input('>'))
print("game in beginning")
# sleep(5)
# print ("\n" * 100)
global blanks
blanks = '_ ' * len(guessnum)
print()
print(blanks)
guessing()
def guessing():
global fullWordList
global chances
print("guess a letter")
global guess
guess=input('>')
guessloop()
def guessloop():
global chances
if guess in fullWordList:
if guess in fullWordList:
letterIndex = guessnum.index(guess)
global blanks
blanks = blanks[:letterIndex*2] + guess + blanks[letterIndex*2+1:]
fullWordList.remove(guess);
global lenWord
lenWord = len(fullWordList)
print (fullWordList)
print (lenWord)
print ("Guess is correct!")
if guess in fullWordList:
guessloop()
else:
wrongnums.append(guess)
print (wrongnums)
if lenWord == 0:
print()
print("Word: ",blanks)
win()
else:
print()
print("Word: ",blanks)
guessing()
else:
if lenWord == 0:
win()
else:
print()
print("Word: ",blanks)
guessing()
elif guess in wrongnums:
print("You've guessed that!")
guessing()
else:
chances -=1
wrongnums.append(guess)
print (wrongnums)
print ("Guess is wrong! ", chances, " more failed attempts allowed.")
if chances == 0:
gameOver()
else:
guessing()
def check():
print()
print("Word: ",newBlanks)
guessing2()
def win():
print("You guessed it well done")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
def gameOver():
print("You ran out of guesses, sorry, you lose")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
Now i have also got a code:
def hangman():
global fullWordList
fullWordList = []
global wrongnums
wrongnums =[]
print("What is the word to be guessed?")
print("Words means that there are no numbers")
global guessnum
guessnum=input('>')
fullWord = guessnum
for line in fullWord:
for c in line:
fullWordList.append(c)
print (fullWordList)
print("how many chances?")
global chances
chances=int(input('>'))
print("game in beginning")
# sleep(5)
# print ("\n" * 100)
global blanks
blanks = '_ ' * len(guessnum)
print()
print(blanks)
guessing()
def guessing():
global fullWordList
global chances
print("guess a letter")
global guess
guess=input('>')
guessloop()
def guessloop():
global chances
if guess in fullWordList:
if guess in fullWordList:
letterIndex = guessnum.index(guess)
global blanks
guesses = (guessnum)
guesses = blanks[letterIndex]
blanks[letterIndex] = guess
fullWordList.remove(guess);
global lenWord
lenWord = len(fullWordList)
print (fullWordList)
print (lenWord)
print ("Guess is correct!")
if guess in fullWordList:
guessloop()
else:
wrongnums.append(guess)
print (wrongnums)
if lenWord == 0:
print()
print("Word: ",blanks)
win()
else:
print()
print("Word: ",blanks)
guessing()
else:
if lenWord == 0:
win()
else:
print()
print("Word: ",blanks)
guessing()
elif guess in wrongnums:
print("You've guessed that!")
guessing()
else:
chances -=1
wrongnums.append(guess)
print (wrongnums)
print ("Guess is wrong! ", chances, " more failed attempts allowed.")
if chances == 0:
gameOver()
else:
guessing()
def check():
print()
print("Word: ",newBlanks)
guessing2()
def win():
print("You guessed it well done")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
def gameOver():
print("You ran out of guesses, sorry, you lose")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
hangman()
This is what i edited it to and got this error:
blanks[letterIndex] = guess
TypeError: 'str' object does not support item assignment
I really am stumped, i hope this is enough data to help.
I've tried to change your code as little as possible, but I need to get code working fully to work out all the bugs, so I'm sharing what I've done with your code.
You've identified two problems - one is that as soon as there's a single match, the program moves on to the next guess, without checking for multiple positive hits.
The second problem is that the error you were getting is that 'blanks' was a string and you were trying to change a character at a specific index (line 43 of the second code sample: blanks[letterIndex] = guess). Strings are immutable, so the attempt to alter a character in place isn't possible. There's more than one way around this - one that I went with (below) is to set 'blanks' up as a list, allowing you to change any of the elements of the list (since lists are mutable). To display the list to the user, try ''.join(blanks) to make a presentable string out of the list.
I made a few changes to the code (again, trying to honour your structure and style) to come up with something that works:
removed the variable guessnum (you only need fullWord)
converted 'blanks' from being a string to a list - now you can make changes as guesses are correct. This directly relates to the question you ask.
simplified the flow of your if ... else statement in the guessing function, going through the three possible outcomes: correct guess, repeated guess, and incorrect guess. Within those are some sub-checks (if correct, is it a win? if incorrect, is it a loss?) I included some comments so you can see what changes were made and where.
when a guess is correct, 'blanks' is updated accordingly for EVERY match that occurs. (And blanks is displayed by using ''.join(blanks) to make a string of the elements.) When a guess is correct, fullWordList is also updated for EVERY match that occurs - the letter is replaced with '-'. So now a check for a win is whether the fullWordList contains only '-' elements.
There's still no catching of exceptions, but what is here works with a word like 'apple' - trying to win, lose, and repeat guesses.
Hope it helps - let me know if there's something that isn't clear. I didn't want to just re-write your code, but wanted to walk through one approach to the problem.
There are other improvements that can be made, but this at least clears your hurdles.
THE CODE
def hangman():
global fullWordList
fullWordList = []
global wrongnums
wrongnums =[]
print("What is the word to be guessed?")
print("Words means that there are no numbers")
# no need to set two variables for same thing (fullWord and guessnum)
global fullWord
fullWord=input('>')
for line in fullWord:
for c in line:
fullWordList.append(c)
print (fullWordList)
print("how many chances?")
global chances
chances=int(input('>'))
print("game in beginning")
# sleep(5)
# print ("\n" * 100)
global blanks
# treat blanks as a list rather than string (list is mutable)
blanks = ['- '] * len(fullWord)
print()
print(blanks)
guessing()
def guessing():
global fullWordList
global chances
print("guess a letter")
global guess
guess=input('>')
guessloop()
def guessloop():
global chances, guess, blanks, blankList, fullWordList
# three possibilities: correct guess, repeated guess, incorrect guess
# 1. correct guess
if guess in fullWordList:
#generates list of indices of ALL matches
# stackoverflow.com/questions/9542738/python-find-in-list
letterIndex = [i for i, x in enumerate(fullWordList) if x == guess]
print letterIndex
for idx in letterIndex:
# change elements in blank list if there's a match
blanks[idx] = (guess +' ')
# update fullWordList to replace correct guesses with '-'
fullWordList[idx] = ('-')
# display the updated blank list as a string
print ''.join(blanks)
# replace all occurrences of guess from fullWordList with '-'
print ("Guess is correct!")
# add guess to wrongnums to record it as 'already guessed'
wrongnums.append(guess)
# check if it's a winning guess
if fullWordList == ['-']*len(fullWord):
print()
# display updated list as string
print("Word: ", ''.join(blanks))
win()
# 2. repeated guess
elif guess in wrongnums:
# don't add to wrongnums if already guessed (letter is already in there)
if guess in wrongnums:
print("You've guessed that!")
print ''.join(blanks)
# 3. incorrect guess
else:
chances -=1
wrongnums.append(guess)
print (wrongnums)
print ("Guess is wrong! ", chances, " more failed attempts allowed.")
print ''.join(blanks)
if chances == 0:
gameOver()
guessing()
def check():
print()
print("Word: ",newBlanks)
guessing2()
def win():
print("You guessed it well done")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
def gameOver():
print("You ran out of guesses, sorry, you lose")
print("Would you like to play again?")
PG = input(">")
if PG == "yes" or PG == "Y" or PG == "Yes" or PG == "yea" or PG == "Yea":
print ("Game will restart in 5 seconds")
sleep(5)
hangman()
else:
print("Going to main menu in 5 seconds")
sleep(5)
start()
hangman()