I've made the game Mastercode and I am having troubles getting the computer to tell the user which numbers they got correct and incorrect.
My code is listed below, along with the attempt I used for getting the computer to print the correct answers. If someone could tell me what I am doing wrong and point me in the right direction, that would be great.
import random
def masterMind():
Password = "%05d" % random.randint(0, 99999) #the computer chooses 5 random numbers
for tries in range(10):
userGuess = raw_input("Guess my 5 digit password to access the treasure:")
if Password == userGuess:
print "Win on the %d try" % (tries + 1)
hint(password, userGuess)
break #terminates the ongoing loop and executes next statement
print "answer was:", Password #tells computer to print the password
def hint(password, guess): #function of the hints
for i in range(5): #the range within the five integers
if guess[i] == password[i]: #if the user's integer aligns with computers integer then an 'x' should appear
print 'x',
continue
if guess[i] in answer: #if don't have corresponding number then an 'o' will appear
print 'o',
I think you really need to check for black and white pegs in separate parts of hint(). This allows you to REMOVE something that "matched as black", and not [incorrectly] score additional whites for it.
Using lists, this can be implemented as such:
def hint(password, guess):
# convert the strings to lists so we can to assignments, below
password_list = list(password)
guess_list = list(guess)
# check for black (correct number in correct position)
for i in range(5): #the range within the five integers
if guess_list[i] == password_list[i]:
print 'x',
# punch in some non-possible value so we can exclude this on the check for white
guess_list[i] = None
password_list[i] = None
# check for white (correct number in wrong position)
for i in range(5):
if guess_list[i] == None:
continue
if guess_list[i] in password_list:
print 'o',
# remove this from the password list, so that a given
# password digit doesn't incorrectly count as multiple white
password_list.remove(guess_list[i])
# or this would work, too:
#password_list[password_list.index(guess_list[i])] = None
print
One you have more Python experience you might find more concise ways to do this with set() objects or Counter() objects... but see if you can see WHY the above works.
Here's my test case: I set the password to "12345", then did these tests:
Guess my 5 digit password to access the treasure:11111
x
Guess my 5 digit password to access the treasure:21777
o o
Guess my 5 digit password to access the treasure:77721
o o
Guess my 5 digit password to access the treasure:21774
o o o
Guess my 5 digit password to access the treasure:21775
x o o
Guess my 5 digit password to access the treasure:14355
x x x o
Guess my 5 digit password to access the treasure:12345
Win on the 7 try
Is that the result you are looking for?
First, you should move the hint call out of the if block (probably it's not a good idea to hint a user only when he/she got the password right):
if Password == userGuess:
print "Win on the %d try" % (tries + 1)
break #terminates the ongoing loop and executes next statement
hint(Password, userGuess)
By the way you were calling hint as hint(password, userGuess). Python names are case-sensitive and you should call it like this: hint(Password, userGuess). Well, really you should rename the Password variable to password - common Python convention is to use lowercase in the variable names.
Second, you have undefined variables in the hint function. I think this function should look like this:
def hint(password, guess): #function of the hints
for i in range(5): #the range within the five integers
if guess[i] == password[i]: #if the user's integer aligns with computers integer then an 'x' should appear
print 'x',
else:
print 'o',
With these changes your code works: I got 18744 password on the 10th try.
About the masterMind() part : The hint() call is executed at the wrong place. Also it uses password and not Password as a parameter
def masterMind():
Password = "%05d" % random.randint(0, 99999) #the computer chooses 5 random numbers
for tries in range(10):
userGuess = raw_input("Guess my 5 digit password to access the treasure:")
if Password == userGuess:
print "Win on the %d try" % (tries + 1)
break #terminates the ongoing loop and executes next statement
else :
hint(Password, userGuess)
print "answer was:", Password #tells computer to print the password
About the hint part :
answer isn't defined anywhere, I think you meant password.
I'm not sure you can work with integers like that, but it'll be fine if you convert them to strings.
Finally the algorithm structure doesn't work well. If a number of the guess is at the right place, the guess function will both echo x and o.
You should use a if ... elif structure, and then you could add a else clause to notify the user that this number isn't in the password at all !
Try to rewrite your hint() function with these indications, but if you need more help, here's a working solution.
def hint(password, guess): #function of the hints
for i in range(5): #the range within the five integers
if str(guess)[i] == str(password)[i]: #if the user's integer aligns with computers integer then an 'x' should appear
print 'x',
elif str(guess)[i] in str(password): #if don't have corresponding number then an 'o' will appear
print 'o',
else:
print '_', # _ is displayed if the number isn't in the password at all.
Also, it would be nice to check that the user's guess has exactly five digits. If it has less than five digits, there'll be an error.
Related
On line 7 and 14 I cant figure out how to divide the variable.
import keyboard
import random
def main(Number, Start):
Number = random.randrange(1,100)
Start = False
QA = input('Press "K" key to begin')
if keyboard.is_pressed('K'):
Start = True
input('I"m thinking of a random number and I want that number divisible by two')
print(Number)
input('Please divide this by two. *IF IT IS NOT POSSIBLE RESTART GAME*\n')
if QA == int(Number) / 2:
print('.')
else:
print('.')
main(Number=' ' ,Start=' ')
What you probably want:
Pick a random number
Make user divide this number by two (?)
Do something based on whether the guess is correct
What is wrong with your code:
You are not picking a number divisible by two. The easiest way to ensure that your number is, indeed, divisible by two, is by picking a random number and then multiplying it by two: my_number = 2 * random.randrange(1, 50). Note the change in the range. Also note that the upper limit is not inclusive, which may be not what your meant here. A typical check for divisibility by N is using a modulo operator: my_number % N == 0. If you want users to actually handle odd numbers differently, you would need to write a separate branch for that.
input returns a string. In your case, QA = input('Press "K" key to begin') returns "K" IF user has actually done that or random gibberish otherwise. Then you are checking a completely unrelated state by calling keyboard.is_pressed: what you are meant to do here is to check whether the user has entered K (if QA == "K") or, if you just want to continue as soon as K is pressed, use keyboard.wait('k'). I would recommend sticking to input for now though. Note that lowercase/uppercase letters are not interchangeable in all cases and you probably do not want users to be forced into pressing Shift+k (as far as I can tell, not the case with the keyboard package).
input('I"m thinking of does not return anything. You probably want print there, possibly with f-strings to print that prompt along with your random number.
input('Please divide this by two. does not return anything, either. And you definitely want to store that somewhere or at least immediately evaluate against your expected result.
There is no logic to handle the results any differently.
Your function does not really need any arguments as it is written. Start is not doing anything, either.
Variable naming goes against most of the conventions I've seen. It is not a big problem now, but it will become one should you need help with longer and more complex code.
Amended version:
import random
import keyboard
def my_guessing_game():
my_number = random.randrange(1, 50) * 2
# game_started = False
print('Press "K" to begin')
keyboard.wait('k')
# game_started = True
print(f"I'm thinking of a number and I want you to divide that number by two. My number is {my_number}")
user_guess = input('Please divide it by two: ')
if int(user_guess) == my_number / 2:
# handle a correct guess here
print('Correct!')
pass
else:
# handle an incorrect guess here
pass
Alternatively, you can use the modulo operator % to test whether Number is divisible by 2:
if Number % 2 == 0:
print('.')
else:
print('.')
This will check whether the remainder of Number divided by 2 is equal to 0, which indicates that Number is divisible by 2.
I am just getting into programming recently and still many things are not clear to me. However in this code I just don't understand the logic. I premise that I don't want to use either import or def(), but I want to understand how I have to reason to make this piece of code work.
A User enters the pwd, and I want there to be a check for numbers and letters that must be present.
The first while is to avoid empty pwd; at this point I dismember the pwd and check for letters and numbers.
Enter the second while and here if I enter only numbers or only letters it works but if I put numbers and letters it keeps staying in the loop.
I tried putting a break (is commented) but it doesn't work.
If anyone can make me understand what I am doing wrong I will be grateful.
Regards
pwd = input("Enter password.\n")
# This loop is used to check if the User has not typed in the password.
while len(pwd) == 0: # Enter the loop when it finds the pwd box empty
print("You left the password box empty.\n")
pwd = input("Enter the password.\n") # Query the password
n = ''.join(filter(str.isdigit, pwd))
char = pwd.isalpha()
num = n.isdigit()
# print(char, num)
# Control loop so that there are letters and numbers
while (char== False and num == True) or (char== True and num == False):
n = ''.join(filter(str.isdigit, pwd))
char= pwd.isalpha()
num = n.isdigit()
print("Attention the password must contain numbers and letters.")
pwd = input("Enter password again.\n") # Prompt for password
# break
if (char== True and num == True):
break
print("Password contains numbers and letters. Accepted!")
PS: Instead of While I tried using if, but if the User keeps putting either only numbers or only letters I have no way to go back as I can with While.
First, Issue you are getting is because of the line
char = pwd.isalpha()
At this point char will always be False, unless pwd is only alpha. So, when you enter a password that is mix of alpha and number example 123asd, char will always be False as you are directly using isalpha() method on pwd. What you want to do here is use same approach you used to check numbers. That mean adding the line below,
c = ''.join(filter(str.isalpha, pwd))
before
char = c.isalpha()
This way you are filtering all the alpha out.
Second, inside your 2nd while loop. You need to move the lines
print("Attention the password must contain numbers and letters.")
pwd = input("Enter password again.\n") # Prompt for password
on top, before doing all those alpha and digit filters. So, that you will always have the latest value stored in the pwd.
[OPTIONAL]
Furthermore, using your same approach, I would suggest to refactor your code as following.
pwd = input("Enter password.\n")
num = ''.join(filter(str.isdigit, pwd))
char = ''.join(filter(str.isalpha, pwd))
while not pwd or not num or not char:
if not pwd:
print("You left the password box empty.")
else:
print("Attention the password must contain numbers and letters.")
pwd = input("Enter password again.\n")
num = ''.join(filter(str.isdigit, pwd))
char = ''.join(filter(str.isalpha, pwd))
print("Password contains numbers and letters. Accepted!")
I am beginning to learn Python and started experimenting with an example code block. I edited it a few times, and on the last edit that I did, I added an optional random password generator. Then I decided that it would make more sense to put the password generator into a separate document, so I copied the necessary code and made a new document. After editing it however, I cannot generate an even number of digits in the password.
Pastebin
Copy of Faulty Code (Pastebin)
import math
import random
alpha = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
print('Would you like a random password suggestion generator', 'Yes or No')
permissionRandomGenerator = input().lower()
print('How long do you want your password?')
lengthRandomGenerator = int(input())
if permissionRandomGenerator == 'yes':
def randInt():
return math.floor(random.random()*10)
def randChar():
return alpha[math.floor(random.random()*27)]
randPasswordList = []
listInsert = 0
def changeCase(f):
g = round(random.random())
if g == 0:
return f.lower()
elif g == 1:
return f.upper()
while listInsert < lengthRandomGenerator:
randPasswordList.insert(listInsert, randInt())
listInsert = listInsert + 1
if listInsert >= lengthRandomGenerator:
break
randPasswordList.insert(listInsert, randChar())
randPasswordList[listInsert] = changeCase(randPasswordList[listInsert])
listInsert = listInsert + 1
continue
listInsert = 0
printList = 0
if lengthRandomGenerator <= 0:
print('It has to be longer than that')
elif lengthRandomGenerator >= 25:
print('I can\'t generate a password that long')
elif math.isnan(lengthRandomGenerator):
print('error: not valid data type')
else:
while printList < (len(randPasswordList)-1):
printItem = randPasswordList[printList]
print(printItem)
printList = printList + 1
printList = 0
randPasswordList = []
elif permissionRandomGenerator == 'no':
print('Too bad...')
else:
print('You had to answer Yes or No')
I refactored your program a bit, and got rid of a lot of unnecessary steps and inconsistencies. Here it is in full, then I'll explain each part:
import random
import string
import sys
possible_chars = string.ascii_letters + string.digits + string.punctuation
def nextchar(chars):
return random.choice(chars)
yes_or_no = input("""
Would you like a random password suggestion generated?
Type Yes to continue: """).lower()
if yes_or_no == 'yes':
try:
pwd_len = int(input('How long do you want your password? '))
except ValueError:
sys.exit("You need to enter an integer. Please start the program over.")
if 0 < pwd_len < 26:
new_pwd = ""
for _ in range(pwd_len):
new_pwd += nextchar(possible_chars)
print("Your new password is:\n" + new_pwd)
else:
print("I can only generate passwords between 1 and 25 characters long.")
else:
print("Well then, why did you run me?")
Python is not just the syntax and builtin functions, it is also the standard library or stdlib. You're going to be working with the stdlib's modules all the time, so when you think you'll be using one, read the docs! You'll learn about the module, what its intended use is, some of its history and changes (such as in which version a certain function was added), and all of the classes, functions, and attributes contained therein. Make sure you read the whole thing (none of them are that long) and try to get at least a basic idea of what each thing does. That way, such as in this case, you'll be able to pick the best function for the job. One thing I like to do in my spare time is just pick a random module and read the docs, just to learn. They're generally fairly well written, and usually pretty inclusive. Get used to Monty Python references, they're everywhere.
import random
import string
import sys
Imports are first, and should almost always be only at the top. I like to put mine in alphabetical order, with the stdlib on top, then a blank line, then 3rd-party modules, including self-written ones next. Put a blank line or two after the imports as well. One thing to remember, that I mentioned in the comments: readability counts. Code is not only meant to be read by machines, but by people as well. Comment when necessary. Be generous with whitespace (also remember that whitespace is syntactically important in Python as well, so it forces you to indent properly) to separate related bits of code, functions, classes, blocks, etc. I highly recommend reading, rereading, and spending time pondering PEP-8, the Python style guide. Its recommendations aren't absolute, but many projects that enforce coding standards rely on it. Try to follow it as much as you can. If a line comes out to 83 characters, don't sweat it, but be aware of what you're doing.
The reason I made such a big deal out of reading the docs is the following few lines:
possible_chars = string.ascii_letters + string.digits + string.punctuation
def nextchar(chars):
return random.choice(chars)
They get rid of about half of your code. string contains a bunch of predefined constants for working with strings. The three I chose should all be good valid password characters. If you're on a system that won't take punctuation marks, just remove it. Note that possible_chars is a string - like tuples, lists and dicts, strings are iterable, so you don't need to make a separate list of each individual possible character.
Next is the function - it replaces your randInt(), randChar(), and changeCase() functions, along with a bunch of your inline code, which was rather bizarre, to tell you the truth. I liked the method you came up with to decide if a letter was upper- or lower-case, but the rest of it was just way too much effort when you have random.choice() and the string constants from above.
yes_or_no = input("""
Would you like a random password suggestion generated?
Type Yes to continue: """).lower()
You may not have been aware, but you don't need to print() a description string before getting user input() - just pass the string as a single argument to input() and you'll get the same effect. I also used a triple-quoted """ (''' can also be used) string literal that differs from the more common single- ' and double-quoted " string literals in that any newlines or tabs contained within it don't need to be escaped. The take-home for now is that you can write several lines of text, and when you print() it, it will come out as several lines.
try:
pwd_len = int(input('How long do you want your password? '))
except ValueError:
sys.exit("You need to enter an integer. Please start the program over.")
I used a try/except block for the next part. If the user enters a non-integer up at the input prompt, the int() function will fail with a ValueError. I picked the simplest manner possible of dealing with it: if there's an error, print a message and quit. You can make it so that the program will re-ask for input if an error is raised, but I figured that was beyond the scope of this exercise.
if 0 < pwd_len < 26:
new_pwd = ""
for _ in range(pwd_len):
new_pwd += nextchar(possible_chars)
print("Your new password is:\n" + new_pwd)
else:
print("I can only generate passwords between 1 and 25 characters long.")
Here is where all the action happens. Using an if/else block, we test the desired length of the password, and if it's between 1 and 25 (an arbitrary upper bound), we generate the password. This is done with a for loop and the range() function (read the docs for exactly how it works). You'll notice that I use a common Python idiom in the for loop: since I don't actually need the number generated by range(), I "throw it away" by using the underscore _ character in place of a variable. Finally, the else statement handles the alternative - either pwd_len is 0 or less, or 26 or greater.
else:
print("Well then, why did you run me?")
We're at the end of the program! This else is paired with the if yes_or_no == 'yes': statement - the user entered something other than yes at the input prompt.
Hopefully this will help you understand a little bit more about how Python works and how to program efficiently using it. If you feel like you're spending a bit too much time implementing something that you think should be easier, you're probably right. One of Python's many advantages is its "batteries included" philosophy - there's a huge range of things you can do with the stdlib.
I made some small edits, and my code seems to be working now. Here is the finished product (I put comments to show what the code does, and also to mark the edits.):
import math
import random #Import necessary modules
alpha = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] #List with alphabet
print('Would you like a random password suggestion generator', 'Yes or No') #Prints the question for permission
permissionRandomGenerator = input().lower() #Stores the answer of the above question in lower case
if permissionRandomGenerator == 'yes': #Generates a password if the answer of the first question is 'yes'
print('How long do you want your password?') #Asks for length
lengthRandomGenerator = int(input()) #Stores length as an integer
def randInt(): #Creates a random integer
return math.floor(random.random()*10)
def randChar(): #Selects a random string from the list with the alphabet
return alpha[math.floor(random.random()*27) - 1]
randPasswordList = [] #Creates a list to store the password
listInsert = 0 #Creates a list index variable
def changeCase(f): #Defines a function to randomly change the case of letters before adding them to the list randPasswordList
g = round(random.random())
if g == 0:
return f.lower()
elif g == 1:
return f.upper()
while listInsert < lengthRandomGenerator + 1: #Creates a random password and inserts it into randPasswordList (I added `+ 1` here)
randPasswordList.insert(listInsert, randInt())
listInsert = listInsert + 1
if listInsert >= lengthRandomGenerator:
break
randPasswordList.insert(listInsert, randChar())
randPasswordList[listInsert] = changeCase(randPasswordList[listInsert]) #Calls the changeCase function whenever it inserts a letter
listInsert = listInsert + 1
continue
listInsert = 0
printList = 0
if lengthRandomGenerator <= 0: #If the length it 0 or less (for example, negatives) the password will not generate (I need to fix this a little bit. Currently the code attempts to create a password beforehand)
print('It has to be longer than that')
elif lengthRandomGenerator >= 25:
print('I can\'t generate a password that long')
elif math.isnan(lengthRandomGenerator): #Currently this doesn't do anything, it needs to be moved farther forward
print('error: not valid data type')
else:
while printList < (len(randPasswordList)-1): #Prints the list item by item
printItem = randPasswordList[printList]
print(printItem)
printList = printList + 1
printList = 0 #Resets the variables
randPasswordList = []
elif permissionRandomGenerator == 'no':
print('Too bad...')
else:
print('You had to answer Yes or No')
Note: I made this code purely to experiment and better learn basic aspects of Python. This code is not optimized, and is also not as random as I can (and will) make it.
P.S. Sorry if the comments are incomplete, I am still learning this language.
I don't know why you are doing over complicated for this simple problem, you can just use the constant provided by the string object, I would rather have the following programs to generate random password
import random, sys, string
def pgen(length=8):
if length < 8:
length = 8
keys = list(string.printable[:-6])
random.shuffle(keys)
return ''.join(keys)[:length]
if __name__ == '__main__':
try:
print( pgen(int(sys.argv[1])))
except Exception as e:
print("Provide length of password \n passwordgen.py <length_of_password>")
Outputs
magautam#nix1947:/tmp$ python passwordgen.py 12
HNLxi!{.qe=b
magautam#nix1947:/tmp$ python passwordgen.py 45
}w5u?+C=e[DfI.n'*1G(m{r0FH|UBKz/#kL>;Sh`tEW8-
I need to create a final project for a Beginning Python class and I decided to create a riddle program and want to simplify the following code, but am unsure how to do it. I would like to use a class to do this, but I'm having trouble figuring out how to change my main program to use the information from Class The program runs fine without using Class, but I have to use it for the final project. I am unsure how to do this, I've tried a few things like doing a points system (5 points increment for each win) and thought it would be nice to make the riddles/answers etc. into a class. The problem I'm having is how to code the self instances in the program itself. I know to import the class, but I'm struggling with how/what to change in the program without screwing everything up.. I've looked all over Stack Overflow and a variety of other internet resources, and believe I have a decent understanding of classes, importing and inheritance, but I can't seem to find any examples similar to what I'm trying to do.. Any help is greatly appreciated.
import riddle_class
banner = "~Riddle Me This~"
print(banner)
print('')
print('Instructions: You have 10 chances to answer each of the following 5 riddles.\
You will receive 5 points for each riddle you answer – up to 25 points.')
points = {'win': 0}
riddle_one = 'What\'s round, but not always around. It is light sometimes and is dark sometimes. Everyone wants to walk all over me. What am I?'
riddle_two = 'What has roots as nobody sees, Is taller than trees, Up, up it goes, And yet never grows?'
riddle_three = 'Voiceless it cries, Wingless flutters, Toothless bites, Mouthless mutters. What am I?'
riddle_four = 'Tear one off and scratch my head; what was once red is black instead.'
riddle_five = 'We\'re five little items of an everyday sort; you\'ll find us all in a tennis court'
riddle_one_answer = 'moon'
riddle_two_answer = 'mountain'
riddle_three_answer = 'wind'
riddle_four_answer = 'match'
riddle_five_answer = 'vowels'
hidden_one = '-' * len(riddle_one_answer)
hidden_two = '-' * len(riddle_two_answer)
hidden_three = '-' * len(riddle_three_answer)
hidden_four = '-' * len(riddle_four_answer)
hidden_five = '-' * len(riddle_five_answer)
guess_one = 0
guess_two = 0
guess_three = 0
guess_four = 0
guess_five = 0
points = 0
score = {'win':0}
print('')
#Riddle One
print('~Riddle Number One!~')
print(riddle_one)
print('')
while guess_one < 11:
print(hidden_one)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_one)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_one_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_one_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_one = hidden_one[:position] + user_input + hidden_one[position+1:] # Rebuild the hidden word string
if not '-' in hidden_one:
print('')
print('Nice Job!', end=' ')
results = 'win'
break
guess_one += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_one_answer,'\.')
print('______________________________________')
print('')
#Riddle Two
print('')
print('~Riddle Number Two!~')
print(riddle_two)
print('')
while guess_two < 11:
print(hidden_two)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_two)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_two_answer.count(user_input)
# Replace the hidden_word with the character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_two_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_two = hidden_two[:position] + user_input + hidden_two[position+1:] # Rebuild the hidden word string
if not '-' in hidden_two:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_two += 1
else:
print('Loser!', end=' ')
print('The word was: %s' % riddle_two_answer,'\.')
print('______________________________________')
print('')
#Riddle Three
print('')
print('~Riddle Number Three!~')
print(riddle_three)
print('')
while guess_three < 11:
print(hidden_three)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_three)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_three_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_three_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_three = hidden_three[:position] + user_input + hidden_three[position+1:] # Rebuild the hidden word string
if not '-' in hidden_three:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_three += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_three_answer,'/.')
print('______________________________________')
print('')
#Riddle Four
print('')
print('~Riddle Number Four!~')
print(riddle_four)
print('')
while guess_four < 11:
print(hidden_four)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_four)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_four_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_four_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_four = hidden_four[:position] + user_input + hidden_four[position+1:] # Rebuild the hidden word string
if not '-' in hidden_four:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_four += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_four_answer,'/.')
print('______________________________________')
print('')
#Riddle Five
print('')
print('~Riddle Number Five!~')
print(riddle_five)
print('')
while guess_five < 11:
print(hidden_five)
user_input = input('Enter one letter at a time (guess #%d): ' % guess_five)
if len(user_input) != 1:
continue
# Count the number of times the character occurs in the word
num_occurrences = riddle_five_answer.count(user_input)
# Replace the appropriate position(s) in hidden_word with the actual character.
position = -1
for occurrence in range(num_occurrences):
position = riddle_five_answer.find(user_input, position+1) # Find the position of the next occurrence
hidden_five = hidden_five[:position] + user_input + hidden_five[position+1:] # Rebuild the hidden word string
if not '-' in hidden_five:
print('')
print('WINNER!', end=' ')
results = 'win'
break
guess_five += 1
else:
print('Loser!', end=' ')
print('The word was %s' % riddle_five_answer,'/.')
print('______________________________________')
print('')
if results == 'win':
score['win'] += 1
total_wins = (score['win'])
points += 5 * total_wins
print('Total points: %d' % points) *#This is only recognizing 1 'win'*
Class
class riddle_me:
def __init__(self, turns, guess):
self.turns = 5
guess = 0
score = {'wins': 0}
def __init__(self):
guess_one = 0
guess_two = 0
guess_three = 0
guess_four = 0
guess_five = 0
UPDATE
Thank you all for your help and questions. Even the questions got me thinking more about my project. I still haven't completed the program yet, but I know it could work. I just need to practice more. I've been studying nonstop, but for some reason I'm struggling to learn this language no matter how many tutorials I search.
I'm assuming you understand what a class is, right? So your question really is, "how should I use classes in this program?"
Usually the best way to figure out what classes (and objects) you need in a program is to sit down and write out a description of what your program is trying to do, and then pick out words from that. For example:
This riddle game will ask the user a series of questions, and each time compare the user's guess with the correct answer. When the user guesses correctly, the user's points will increase. If the user does not guess correctly after 10 guesses, we will move to the next question. After all the questions have been asked, the game will display the user's points.
OK, so this is still pretty straightforward. I've highlighted some of the words that occur more than once. Each of these words represents an idea that might be usefully made into a class: the game itself, each question, the user's guess.
Some of these things don't need to be their own objects, but can be properties of other objects. For example, notice how we kept referring to "the user's points". Clearly the points number is an attribute of the user object. And the correct answer to a question should be an attribute of that question.
OK, so now we have some "things" we're going to use in our program, and some idea of what we want to know about each of them:
User:
has points (a number)
Question:
has question text (a string)
has correct answer (a string)
Guess:
has the text of the guess, what the user entered (a string)
is either right or wrong (a boolean)
Game:
has 5 questions
OK, these are starting to look like classes! We can translate these into classes pretty directly:
class User:
def __init__(self):
self.points = 0 # user starts out with zero points
class Question:
def __init__(self, question_text, correct_answer):
self.question_text = question_text
self.correct_answer = correct_answer
class Guess:
def __init__(self, text, is_correct):
self.text = text
self.is_correct = is_correct
class Game:
def __init__(self, questions):
self.questions = questions
Now we have some objects, but we can't do anything useful with them. Now we need to decide what methods to add. There's more than one right way to do this (and a lot of subtle tradeoffs, depending on which things you care more or less about).
Let's start, though, by identifying things we want to be able to do:
ask a Question, that is, print out its question_text
read in a Guess from the user
determine whether a Guess matches a Question's correct_answer text
add points to a User
find the next Question in a Game, or determine when there are no more questions
Each of these things we want to do should be a method! Now you're breaking down your program into smaller and smaller pieces. Keep doing it until it becomes obvious what each piece should do -- and then translate each piece into code. That's it!
Some of these things could potentially live in multiple places. Some things to think about:
Should reading in a Guess from the user be a method on Guess or on User? Either one is OK. Or it could even be a separate function (not a method of a class).
Where should the function that determines whether a Guess is correct or not live? Right now I have it as an attribute of the Guess class, but maybe it should be a method on Guess like is_correct_answer_to(question) that takes the question and returns True or False.
Where should we keep track of the number of guesses so far for a particular question? It could either be on the Question object, or on the User object. Or it could just be a local variable in a function like ask_question(question) which could live either on Question or maybe on Game, or maybe not as a member of a class.
These are the decisions you need to make. But hopefully this will help you get started!
I think there are two possible places to put a class into your code. One is urgently needed, the other not so much (but it could come in handy if you want to add new features to the program).
The obvious place to use a class is to encapsulate all the data and logic related to a single riddle. Each instance of the class would have attributes for the question, the answer, and perhaps other things that would be modified as the player tries to solve the riddle (the masked solution shown to the player and a list of the guesses so far, perhaps).
Something like this:
class Riddle(object):
def __init__(self, question, answer):
self.question = question
self.answer = answer
self.guesses = []
self.update_mask()
def update_mask(self):
self.masked_answer = "".join(c if c in self.guesses else "-"
for c in self.answer)
def guess(self, letter):
# perhaps do some sanity checking here, for invalid or duplicated letters
self.guesses.append(letter)
self.update_mask()
# return number of letters just matched, number yet to be guessed
return self.answer.count(letter), self.masked_answer.count("-")
The other place you might use a class is to encapsulate the game logic (e.g. how many guesses the user gets to make, how they score points) and state (e.g. the player's score and the list of Riddles to ask). This would let you adapt your program in various ways, like letting the player play again after they complete the first run.
However, I don't think that using a class for this is nearly as important as it was for the riddles. Most of the benefits would simply come from gathering the game logic into functions, rather than repeating it over and over. Make an ask_riddle function to handle a single riddle and return the score the player earned and your code will get a whole lot cleaner. If you want to make it a method of the Game class, and update the instance with the score instead, that works too. Python doesn't require you to write object oriented code (though it does make it easy to do so), so you don't need to wedge classes in where they're not needed.
Sorry...I'm kind of a programming noob. I was looking at some problem sets online and I found THIS ONE. I wrote this much:
import random
powerball=random.randint(1,42)
a=random.randint(1,53)
b=random.randint(1,53)
c=random.randint(1,53)
d=random.randint(1,53)
e=random.randint(1,53)
(f,g,h,i,j)=x=input("Your 5 Chosen Numbers:")
My problem is that I don't know how to make the program print something like "Please enter 5 numbers separated by only a comma" if more or less than five are entered. Also how would I do that if I wanted it to display a different message every other time they made that mistake?
Try this approach:
input_is_valid = False
while not input_is_valid:
comma_separated_numbers = raw_input("Please enter a list of 5 numbers,separated by commas: ")
numbers = [int(x.strip()) for x in comma_separated_numbers.split(",")]
if len(numbers) != 5:
print "Please enter exactly 5 numbers"
else:
input_is_valid = True
Looking at your link I'd say:
import random
while True:
sets = input('how many sets? ')
if type(sets) == int:
break
else:
pass
for i in range(sets):
ri = random.randint
powerball = ri(1,42)
other_numbers = sorted(ri(1,53) for i in range(5))
print 'your numbers:','\t',other_numbers,'\t','powerball:','\t',powerball
It seems that's more or less what he asks from you.
If I'm correct, you want the user to submit his series so to see if its one of the sets extracted (amirite?)
then it could be fine to do:
import random
while True:
sets = input('how many sets? ')
if type(sets) == int:
break
else:
pass
while True:
myset = raw_input('your 5 numbers:').split()
if len(myset) != 5:
print "just five numbers separated ny a space character!"
else:
myset = sorted(int(i) for i in myset)
break
for i in range(sets):
ri = random.randint
powerball = ri(1,42)
numbers = sorted(ri(1,53) for i in range(5))
print 'numbers:','\t',numbers,'\t','powerball:','\t',powerball
if numbers == myset:
print "you won!" ##or whatever the game is about
else:
print "ahah you loser"
EDIT: beware this doesn't check on random generated numbers. So it happens one number can appear more than once in the same sequence. To practice you may try avoiding this behavior, doing so with a slow pace learning some python in the way it could be:
make a set out of a copy of the list "numbers" -- use set()
if its length is less than 5, generate another number
check if the new number is in the list
if it is, then append it to the list. if its not unique yet, GOTO point 1 :-)
sort the whole thing again
there you go
happy reading the docs!
My proposition:
import random
import sys
powerball=random.randint(1,42)
a=random.randint(1,53)
b=random.randint(1,53)
c=random.randint(1,53)
d=random.randint(1,53)
e=random.randint(1,53)
bla = ["\nPlease enter 5 numbers separated by only a comma : ",
"\nPlease, I need 5 numbers separated by only a comma : ",
"\nPLEASE, 5 numbers exactly : ",
"\nOh gasp ! I said 5 numbers, no more nor less : ",
"\n! By jove, do you know what 5 is ? : ",
"\n==> I warn you, I am on the point to go off : "]
i = 0
while i<len(bla):
x = raw_input(warn + bla[i])
try:
x = map(int, x.split(','))
if len(x)==5:
break
i += 1
except:
print "\nTake care to type nothing else than numbers separated by only one comma.",
else:
sys.exit("You wanted it; I go out to drink a beer : ")
(f,g,h,i,j)=x
print f,g,h,j,i
.
Some explanation:
.
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
A break statement executed in the first suite terminates the loop without executing the else clause’s suite. A continue statement executed in the first suite skips the rest of the suite and continues with the next item, or with the else clause if there was no next item.
http://docs.python.org/reference/compound_stmts.html#index-801
.
.
x = map(int, x.split(','))
means that the function int() is applied to each element of the iterable which is the second argument.
Here the iterable is the list x.split(',')
Hence, x is a list of 5 integers
In Python 3, there is no more raw_input() , it has been replaced by input() that receives characters, as raw_input() in Python 2.
.
.