Creating a "Flashcard" vocabulary program - python

I'd like to make a program in Python 3 that would be essentially vocabulary flashcards. I'd be able to list the terms, add a term, or display a random definition to try and accurately guess. Once guessed accurately, I would be given the option for another definition to guess. Alternatively, I'd like to just be able to display a random key:value pair, and to continue viewing pairs until I enter EXIT.
I have made most of the program using a dictionary, but am not sure how to go about with entering the proper command to enter the key for the definition displayed. If anyone could provide suggestions, I'd appreciate it! Also I got some sort of error message when entering this code in and had to do a bunch of indentations, not sure what I did wrong there.
import random
terms = {"1" : "def 1", #Dictionary of 'terms' and 'definitions'
"2" : "def 2",
"3" : "def 3"}
menu = None
while menu != "4":
print("""
DIGITAL FLASHCARDS!
1 - List Terms
2 - Add Term
3 - Guess Random Definition
4 - Exit
""")
menu = input("\t\t\tEnter Menu option: ")
if menu == "1": # List Terms
print("\n")
for term in terms:
print("\t\t\t", term)
input("\n\tPress 'Enter' to return to Main Menu.\n")
elif menu == "2": # Add Term
term = input("\n\tEnter the new term: ").upper()
if term not in terms:
definition = input("\tWhat is the definition? ")
terms[term] = definition
print("\n\t" + term, "has been added.")
else:
print("\n\tThat term already exists!")
input("\n\tPress 'Enter' to return to Main Menu.\n")
elif menu == "3": # Guess Random Definition. Once correct, choose new random definition
print("\n\t\t\tType 'Exit' to return to Menu\n")
choice = random.choice(list(terms.values()))
print("\n\t" + choice + "\n")
guess = None
while guess != "EXIT":
guess = str(input("\tWhat is the term? ")).upper()

display a random definition to try and accurately guess. Once guessed accurately, I would be given the option for another definition to guess
Use terms.items() to get key and value at the same time.
Define the process of generating a new definition question into a function generate_question() to avoid duplicity.
elif menu == "3": # Guess Random Definition. Once correct, choose new random definition
print("\n\t\t\tType 'Exit' to return to Menu\n")
def generate_question():
term, definition = random.choice(list(terms.items()))
print("\n\t" + definition + "\n")
return term
term = generate_question()
guess = None
while guess != "EXIT":
guess = input("\tWhat is the term? ").upper()
if guess == term:
print("Correct!")
if input("\tAnother definition?(y/n)").upper() in ["Y", "YES"]:
term = generate_question()
else:
break
Alternatively, I'd like to just be able to display a random key:value pair, and to continue viewing pairs until I enter EXIT.
elif menu == "4": # Random display a term-definition pair.
print("\n\t\t\tType 'Exit' to return to Menu\n")
exit = None
while exit != "EXIT":
term, definition = random.choice(list(terms.items()))
print(term + ":", definition)
exit = input("").upper() # Press enter to continue.
Remember to modify the beginning part:
while menu != "5":
print("""
DIGITAL FLASHCARDS!
1 - List Terms
2 - Add Term
3 - Guess Random Definition
4 - View term-definition pairs
5 - Exit
""")

Related

'while' loop not behaving as expected

Background:
I have made a program that takes a text input, applies encryption (a simple cipher) and saves the output to a list - if desired. Messages can also be decrypted.
The program is navigated through an options menu:
1. Encrypt a message
2. View encrypted messages
3. Decrypt a message
To allow all sections of the program to access the same list (variable) of saved messages, I have written it within a class. Within the class exist def's that call on this list.
Only the 'encrypt a message' bit has been written so far.
Problem:
The user decision flow is made with two Y/N choices.
However, the choices do not work - even if the user types in 'N' - my program thinks they have typed 'Y' in both cases.
def encrypt():
def save_cip():#This function allows the user to save the ciphered message to the ciphered_messages if they choose
choosing = True
while choosing:
save_choice = input("Would you like to save your Ciphered message? (Y/N)\n")
if save_choice == "Y" or "y":
print("You chose yes")
cct.ciphered_messages.append(' '.join(["Message", str(len(cct.ciphered_messages)), ":", cipher]))
choosing = False
elif save_choice == "N" or "n":
print("You chose no")
choosing = False
continue
else:
print("That was not a valid entry, please enter Y or N only")
continue
I think the problem lay within the scope, and that somehow the same variable is not being referenced when setting and reading Y or N. I have been going up and down the same code for about 3 hours and still nothing, declaring all variables in many different places with no luck, so any advice greatly appreciated.
Full executable code:
class cct:
print("Welcome to the CaeserCipher tool v1.0")
menu_state = "main" #This is used to record what state the program is in
unciphered_messages = [] #Decrypted messages are saved here
ciphered_messages = [] #Encrypted messages are saved here
def menu(): #This is the main menu interface
while cct.menu_state == "main": #This while
cct.menu_state = input("What would you like to do? \n 1: Encrypt a Message \n 2: View Encrypted Messages \n 3: Decrypt a message\n")
if cct.menu_state == "1":
cct.encrypt()
elif cct.menu_state == "2":
cct.view()
elif cct.menu_state == "3":
cct.decrypt()
elif cct.menu_state == "main":
print("\n\nWelcome back to the menu!\n\n")
else:
print("You did not enter a valid choice. Please enter a number between 1 and 3.\n")
cct.menu_state = "make_choice"
continue
def encrypt():
def save_cip():#This function allows the user to save the ciphered message to the ciphered_messages if they choose
choosing = True
while choosing:
save_choice = input("Would you like to save your Ciphered message? (Y/N)\n")
if save_choice == "Y" or "y":
print("You chose yes")
cct.ciphered_messages.append(' '.join(["Message", str(len(cct.ciphered_messages)), ":", cipher]))
choosing = False
elif save_choice == "N" or "n":
print("You chose no")
choosing = False
continue
else:
print("That was not a valid entry, please enter Y or N only")
continue
#This while loop continually takes messages, gives the option of saving, and asks if you want to cipher another
while cct.menu_state == "1":
text = input("Enter your message: ") #Enter the message you wish to cipher
cipher = '' #Create a string for the cipher
for char in text: #This for sub-loop will increment each character by 1. e.g. A -> B, T -> U, Z -> A
if not char.isalpha():
continue
char = char.upper()
code = ord(char) + 1
if code > ord('Z'):
code = ord('A')
cipher += chr(code)
print(' '.join(["Your ciphered message is:", cipher]))
save_cip()
print(cct.ciphered_messages)
#This sub-while loop is reponsible for checking if you want to cipher another message
#and making sure the user has made a valid choice
choosing_another = True
while choosing_another == True:
choice_variable = input(' '.join(["You have", str(len(cct.ciphered_messages)), "saved messages \n", "Would you like to Cipher another? (Y/N)\n"]))
if choice_variable == "Y" or "y":
print("You chose yes")
choosing_another = False
elif choice_variable == "N" or "n":
print("You chose no")
cct.menu_state = "main"
choosing_another = False
else:
choice_variable = input("That was not a valid entry, please enter Y or N only: \n")
continue
return
def view():
#TO BE CODED
return
def decrypt():
#TO BE CODED
return
cct.menu()
This is always true:
if save_choice == "Y" or "y":
bacause its interpreted as :
if (condition) or (condition):
the 1st condition is (save_choice == "Y")
the 2nd condition is just ( "y" ) which python interprets as 'True'
So the whole condition is always True.
U probably mean:
if save_choice == "Y" or save_choice == "y":
Or better :
if save_choice.lower() == "y":
Not a python programmer, but i don't think python allows a "implied" subject for the or operator
--> IF save_choice == "Y" OR save_choice == "y" :

python trouble getting code to work

update so it seems like no matter what i do or type it asks
what would you like to add?
instead of doing the other options it just keeps asking this
it should only be asking this if the user types a
this is a 2 issue thing im having and the main original post is here
How to debug errors in Python?
but the bigger issue im having is i cant get the bottom half of my code to work
it just ignores the inputs given to it and continues to add them to the list
#.....
elif user == "d" :
listdelete = input("what item do you want deleted")
list.remove (listdelete)
elif user == "p" : # prints the list
print (list)
elif user == "x" : # exits the program
print ("good bye")
print ("!!!!!!that is not a choice!!!!!!")
#right now everything is being called through a single procedure
print (option())
and on the bottom here is going to be the entire code sorry for pasting the entire code on the bottom here but i thought it would be easy to understand the whole issue if i showed the whole code and then the section thats not working since its all under one procedure
list = []
def option() :
print ("(a) -to add item ")
print ("(d) -to delete item")
print ("(p) -to see items on your list")
print ("(x) -to exit ")
#above just prints out user options with a input after
user = input("please select a choice")
if user == "a" :
item = input("what would you like to add? ")
list.append (item)
# next im going to ask if they would like to add another item
more = input(" would you like to add something else? yes or no")
while more == "yes":
if more == "yes" :
item = input("what else would you like to add? type b to back ")
if item == "b" :
print (option())
else :
list.append(item)
elif more == "no" :
print (option())
#.....
elif user == "d" :
listdelete = input("what item do you want deleted")
list.remove (listdelete)
elif user == "p" : # prints the list
print (list)
elif user == "x" : # exits the program
print ("good bye")
print ("!!!!!!that is not a choice!!!!!!")
#right now everything is being called through a single procedure
print (option())
I have updated your code which still has flaws and exploits the mutability of the list datatype but does work as you would expect it:
#!/usr/bin/env python
def AddElement(collection):
elementToAdd = input("What would you like to add: ")
collection.append(elementToAdd)
return collection
def DeleteElement(collection):
print("You have the following items:", collection)
elementToDelete = input("What item do you want deleted: ")
for elements in collection:
if elements == elementToDelete:
collection.remove(elements)
print("You have the following items left:", collection)
return collection
def WriteMenu():
print("(a) -to add item")
print("(d) -to delete item")
print("(p) -to see items on your lst1")
print("(x) -to exit")
return True
def option():
WriteMenu()
UserInput = input("Please select a choice: ")
while UserInput:
if UserInput == "a":
AddElement(collection)
elif UserInput == "d":
DeleteElement(collection)
elif UserInput == "p":
print(collection)
elif UserInput == "x":
print("Good bye!")
break
WriteMenu()
UserInput = input("Please select a choice: ")
else:
print(collection)
#right now everything is being called through a single procedure
collection = []
option()

While/if loop giving me trouble (beginner)

I have been trying to make my first "solo" python program, its a calculator where you pick what kind of formula you want it to calculate and then input the variables needed. I got issues with my while/for loop, when i run the program i get the correct menu: menu(), and then when I choose my next menu by inputting 1 i correctly get the "v_menu" however if I input 2, which should get me the "m_menu", I instead just get the v_menu like I would if I typed in a 1.
I hope my explanation made sense, im still very new to all of this. Appreciate any help I can get, been breaking my head over this for atleast one hour or so..
Cheers, and heres my code:
# coding=utf-8
#Menues
def menu():
print "Choose which topic you want in the list below by typing the corresponding number\n"
print "\t1) virksomhedsøkonomi\n \t2) matematik\n"
return raw_input("type the topic you want to pick\n >>")
def v_menu():
print "Choose which topic you want in the list below by typing the corresponding number"
print "\t1) afkastningsgrad\n \t2) overskudsgrad\n \t3) aktivernes omsætningshastighed\n \t4) Egenkapitalens forrentning\n \t5) return to main menu\n"
return raw_input("Type the topic you want to pick\n >>")
def m_menu():
print "Choose which topic you want in the list below by typing the corresponding number"
print "\t1) omregn Celsius til Fahrenheit\n \t2) omregn Fahrenheit til Celsius\n"
return raw_input("Type the topic you want to pick\n >>")
# - Mat -
#Celsius to Fahrenheit
def c_to_f():
c_temp = float(raw_input("Enter a temperatur in Celsius"))
#Calculates what the temperatur is in Fahrenheit
f_temp = c_temp * 9 / 5 + 32
#Prints the temperatur in Fahrenheit
print (str(c_temp) + " Celsius is equal to " + str(f_temp) + " Fahrenheit")
#Fahrenheit to Celsius
def f_to_c():
f_temp = float(raw_input("Enter a temperatur in Fahrenheit"))
#Calculates what the temperatur is in celsius
c_temp = (f_temp - 32) * (float(100) / 180)
#Prints the temperatur in celsius
print (str(f_temp) + " Fahrenheit is equal to " + str(c_temp) + " Celsius")
#Program
loop = 1
choice = 0
while loop == 1:
choice = menu()
if choice == "1" or "1)":
v_menu()
elif choice == "2" or "2)":
m_menu()
if choice == "1":
c_to_f()
elif choice == "2":
f_to_c()
loop = 0
Your problem is in your if statements: if choice == "1" or "1)":
What you really need is: if choice == "1" or choice == "1)":
Everything after the or gets evaluated as another expression. You're saying "if choice is equal to one or if one exists."
"1)" evaluates to "true" in this instance, so you'll always hit that branch.
The problem is here;
if choice == "1" or "1)":
v_menu()
elif choice == "2" or "2)":
You have to write them like;
if choice == "1" or choice == "1)":
v_menu()
elif choice == "2" or choice == "2)":
Otherwise, all the time your if statement is True. And if first if statement is True, then your elif statement is not going to work. That's why you can't call v_menu()

Integer and string conflicts

Currently I'm working on an assignment that requires that I create a program in which the user enters a number between 0-4. The program then checks which number the user inputs and outputs a specific string. For example if the user enters 4, the program will output "80 or above: Level 4"
The problem is that the user should also be able to quit the program. I decided to create the program so if the user inputs something that is not blank (while input != "":) the program will run, but if they decide to hit enter the program will end.
This is the code I've come up with so far:
def get_level():
level = raw_input("Enter a number from 0-4 (Press <Enter> to quit): ")
return level
def check_mark(level):
if int(level) == 4:
print "80 or above: Level 4"
elif int(level) == 3:
print "70 - 79: Level 3"
elif int(level) == 2:
print "60 - 69: Level 2"
elif int(level) == 1:
print "50 - 59: Level 1"
elif int(level) == 0:
print "Below 50: Level 0"
else:
print "ERROR: out of range"
def output(level):
while level != "":
level = raw_input("Enter a number from 0-4 (Press <Enter> to quit): ")
check_mark(level)
print
def main():
user_level = get_level()
user_mark = check_mark(user_level)
print
program_output = output(user_level)
main()
I'm pretty aware that the problem has to do with the fact that raw_input only accepts strings which is what activates the "while level != "":" statement. I tried working around this by placing int() operators before each level. The problem is that it conflicts with the input if the user enters blank since it checks whether the input is an integer. Something like that anyways.
So I was hoping someone could guide me to finding a way around this. It would be much appreciated!
You probably want the next looping code:
def output(level):
level = raw_input("Enter a number from 0-4 (Press <Enter> to quit): ")
while level != "":
check_mark(level)
level = raw_input("\nEnter a number from 0-4 (Press <Enter> to quit): ")
I don't htink there is any shortcut around validating input. So the user can either type "" or an integer. What happens if the user types in letters?
I would verify all input to handle accordingly so the program doesn't break
# check for blank
if level == '':
# exit for user
# validate input if not exit
try:
level_int = int(level)
except ValueErrror:
# integer not inputed
if not (0 <= level_int <= 4):
# check that input is between 0 4
# out of range
or you could just check for expection in check_mark when you call it in main

Python Nested List - Changing and replacing individual items

I am completing a simple programming exercise (I am still new) where I am creating a character profile by allocating 30 points to 4 different character attributes. Program features are: show current profile, create a new profile, or change existing profile. First and second feature work fine, but there is problem with the last: the program is meant to unpack the nested list item (attribute + allocated score), ask for a new score, take the difference between the old and new and change the number of available points in the pool accordingly. Finally, add a new entry to the list (attribute + newly allocated score) at position 0 and then delete the entry at position 1, which should be the old entry for this attribute. Loop through the list, and done. However, once you execute the code you will see it won't work. Please see below the complete code:
options = ["Strength", "Health", "Wisdom", "Dexterity"]
profile = []
points = 30
choice = None
while choice != "0":
print(
"""
CHARACTER CREATOR PROGRAM
0 - Exit
1 - See current profile
2 - Build new profile
3 - Amend existing profile
"""
)
choice = input("Please choose an option: ")
print()
if choice == "0":
print("Good bye.")
elif choice == "1":
for item in profile:
print(item)
input("\nPress the enter key to continue.")
elif choice == "2":
print("You can now equip your character with attributes for your adventures.")
print("You have",points,"points to spent.")
print("Now configure your character: \n")
#Run the point allocation loop
for item in options:
point_aloc = int(input("Please enter points for " + str(item) + ":"))
if point_aloc <= points:
entry = item, point_aloc
profile.append(entry)
points = points - point_aloc
print("\nYour current choice looks like this: ")
print(profile)
input("\nPress the enter key to continue.")
else:
print("Sorry, you can only allocate", points," more points!")
print("\nYour current choice looks like this: ")
print(profile)
input("\nPress the enter key to continue.")
print("\nWell done, you have configured your character as follows: ")
for item in profile:
print(item)
input("Press the enter key to continue.")
elif choice == "3":
print("This is your current character profile:\n")
for item in profile:
print(item)
print("\nYou can change the point allocation for each attribute.")
for item in profile:
point_new = int(input("Please enter new points for " + str(item) + ":"))
attribute, points_aloc = item
diff = points_aloc - point_new
if diff >0:
points += diff
print("Your point allocation has changed by", -diff,"points.")
print(diff,"points have just been added to the pool.")
print("The pool now contains", points,"points.")
entry = item, point_new
profile.insert(0, entry)
del profile[1]
input("Press the enter key to continue.\n")
elif diff <0 and points - diff >=0:
points += diff
print("Your point allocation has changed by", -diff,"points.")
print(-diff,"points have just been taken from the pool.")
print("The pool now contains", points,"points.")
entry = item, point_new
profile.insert(0, entry)
del profile[1]
input("Press the enter key to continue.\n")
elif diff <0 and points - diff <=0:
print("Sorry, but you don't have enough points in the pool!")
input("Press the enter key to continue.\n")
else:
print("Sorry, but this is not a valid choice!")
input("Press the enter key to continue.\n")
input("\n\nPress the enter key to exit.")
Note: You need to create the profile first to run the changes.
Thanks in advance for your help!!
As the comments to your question indicate, you haven't asked your question in the best way. However, I see what's wrong with it. I could show you how to fix your current code, but the truth is that the best way to fix it is to rewrite it completely. As you do so, you should adopt the following strategies:
Break your code up into parts. In this case, I would advise you to create several different functions. One could be called main_loop, and would contain the logic for looping through the menu. It wouldn't contain any of the code for updating or displaying profiles. Instead, it would call other functions, display_profile, build_profile, and amend_profile. Those functions would accept variables such as options, profile, and points, and would return values such as options and points. This will enormously simplify your code, and make it much easier to test and debug. Here's an example of what main_loop might look like:
def main_loop():
options = ["Strength", "Health", "Wisdom", "Dexterity"]
profile = []
points = 30
choice = None
while choice != "0":
print(menu_string) #define menu_string elsewhere
choice = input("Please choose an option: ")
print()
if choice == "0":
print("Good bye.")
elif choice == "1":
display_profile(profile)
elif choice == "2":
profile, points = build_profile(options, profile, points)
elif choice == "3":
profile, points = amend_profile(profile, points)
else:
print("Sorry, but this is not a valid choice!")
input("Press the enter key to continue.\n")
input("\n\nPress the enter key to exit.")
See how much nicer this is? Now all you have to do is define the other functions. Something like...
def build_profile(options, profile, points):
# insert logic here
return profile, points
Another advantage to this approach is that now you can test these functions individually, without having to run the whole program.
Use the correct idioms for list modification. Modifying a list while iterating over it takes special care, and in some cases (such as when you change the length of the list by removing or adding items you've already iterated over) it won't work at all. There are ways to do what you try to do to profile, but for a beginning programmer I would recommend something much simpler: just create a new list! Then return that list. So in your amend_profile function, do something like this:
def amend_profile(profile, points):
# other code ...
new_profile = []
for item in profile:
attribute, points_aloc = item
# other code ...
new_proflie.append(entry)
# other code ...
return new_profile, points
Note also that this is where one of your main bugs is; you create an entry containing (item, point_new) instead of (attribute, point_new), so your new tuple has an item tuple inside it, instead of a lone attribute string as expected.

Categories