I'm quite confused at why the option "B" or "C" doesn't work. You are supposed to be able to navigate the story by choosing any of the 3 options. The only option that works is "A". It's probably the smallest thing I have overlooked.
Click to See the Code Window
The program executes (From the Fuctions.py, SplashScreens()):
...
print(SplashScreen.Splash_Screen19)
cls()
Story_1_to_4(Text.Story_1,2,3,4)
Which runs this... (Located in Functions.py){Through = True}{Key = False}
def Story_1_to_4(Story_Num, Path1, Path2, Path3):
global Through
global Key
if Path1 == 3 and Path2 == 4 and Path3 == 10:
Key = True
while Through == True:
Choice = input(Story_Num)
if Choice == "A":
Choice = Path1
Through = False
elif Choice == "B":
Choice = Path2
Through == False
elif Choice == "C":
Choice = Path3
Through == False
else:
cls()
print(Text.Invalid_Syntax)
time.sleep(2)
cls()
ResetThrough()
Decision(Choice)
Story_1: (From Text.py)
Image of the Variable Story_1
And then Decision is... (Located in Functions.py)
def Decision(Choice):
cls()
if Choice == 1:
Story_1_to_4(Text.Story_1,2,3,4)
elif Choice == 2:
Story_1_to_4(Text.Story_2,3,4,10)
elif Choice == 3:
Story_1_to_4(Text.Story_3,5,6,4)
elif Choice == 4:
Story_1_to_4(Text.Story_4,7,8,9)
elif Choice == 5:
Story_Ending(Text.Story_5)
elif Choice == 6:
Story_Ending(Text.Story_6)
elif Choice == 7 and Key == True:
Story_Ending(Text.Story_7_With_Key)
elif Choice == 7 and Key == False:
Story_Ending(Text.Story_7_Without_Key)
elif Choice == 8:
Story_Ending(Text.Story_8)
elif Choice == 9:
Story_Ending(Text.Story_9)
elif Choice == 10:
Story_Ending(Text.Story_10)
For A, you set Through = False. For B and C you wrote Through == False which just evaluates an expression but doesn't assign Through.
Related
My script uses a if elif else check to determine which array item to look at for crafting values. The issue is there are a total of 24 elif statements to allow for a total of 26 choices, (1 for the if, 1 for error catching). What I'm trying to figure out is how to reduce the number of elif statements so the code is better structured.
while choice == 0:
choice = input("Choose a block (Enter only the Number):")
if not choice.isalpha(): # Makes sure that the input is a number and not a string.
choice = int(choice)
else:
choice = 0
print("Thats not a number. Choose a number Numbnuts.")
if choice == 1:
print("\n",block[0])
elif choice == 2:
print("\n",block[1])
elif choice == 3:
print("\n",block[2])
elif choice == 4:
print("\n",block[6])
elif choice == 5:
print("\n",block[7])
elif choice == 6:
print("\n",block[8])
elif choice == 7:
print("\n",block[3])
elif choice == 8:
print("\n",block[4])
elif choice == 9:
print("\n",block[5])
elif choice == 10:
print("\n",block[9])
elif choice == 11:
print("\n", block[10])
elif choice == 12:
print("\n", block[11])
elif choice == 13:
print("\n",block[12])
elif choice == 14:
print("\n",block[13])
elif choice == 15:
print("\n",block[14])
elif choice == 16:
print("\n",block[15])
elif choice == 17:
print("\n",block[16])
elif choice == 18:
print("\n",block[17])
elif choice == 19:
print("\n",block[18])
elif choice == 20:
print("\n",block[19])
elif choice == 21:
print("\n",block[20])
elif choice == 22:
print("\n", block[21])
elif choice == 23:
print("\n", block[22])
elif choice == 24:
print("\n",block[23])
elif choice == 25:
print("\n",block[24])
elif choice == 26:
print("\n",block[25])
Look for structure:
elif choice == 12:
print("\n", block[11])
elif choice == 13:
print("\n",block[12])
elif choice == 14:
print("\n",block[13])
elif choice == 15:
print("\n",block[14])
elif choice == 16:
print("\n",block[15])
Clearly, this is the same as;
print("\n", block[choice - 1])
However, for choice in {4,5,6,7,8,9} the logic isn't that simple, so you could keep the ifs:
if choice == 4:
print("\n",block[6])
elif choice == 5:
print("\n",block[7])
elif choice == 6:
print("\n",block[8])
elif choice == 7:
print("\n",block[3])
elif choice == 8:
print("\n",block[4])
elif choice == 9:
print("\n",block[5])
else:
print("\n", block[choice - 1])
You could also go a step deeper: for choice in {4,5,6} the index is choice-2, and for choice in {7,8,9} the index is choice-4:
if choice in {4,5,6}:
idx = choice - 2
elif choice in {7,8,9}:
idx = choice - 4
else:
idx = choice - 1
print("\n", block[idx])
As another answer suggested, look for structure; you have different ranges of choices that correspond to different offsets in block, so you can iterate over those:
while True:
try:
choice = input("Choose a block (Enter only the Number):")
except ValueError:
print("Thats not a number. Choose a number Numbnuts.")
continue
if choice < 1 or choice > 26:
continue
print("\n")
for limit, offset in ((3, -1), (6, 2), (9, -4), (26, -1)):
if choice <= limit:
print(block[choice + offset])
break
break
Hence for 1 <= choice <= 3 you print block[choice-1], for 4 <= choice <= 6 you print block[choice+2], and so on.
my version:
block_2 = block[:3]+block[6:9]+block[3:6]+block[9:]
print("\n", block_2[choice - 1])
I am trying to use getkey of python that I downloaded from github. But somehow my code is preventing me of achieving it. The keys.UP and keys.DOWN are not functioning, but when I tried to change the "and" in
if key == keys.DOWN and menu_selected + 1 != len(menu_option): to or then I manage the Down keys to work. But the problem is, it won't let me use the Up keys.
Below, are the part of the code I'm talking about. Thank you in advance guys!
from getkey import getkey, keys
import os
def first_choice():
os.system('cls')
print("\nFörsta valet")
input("Press Enter to continue....")
def second_choice():
os.system('cls')
print("\nAndra valet")
input("Press Enter to continue....")
def third_choice():
os.system('cls')
print("\nTredje valet")
input("Press Enter to continue....")
def end_program():
os.system('cls')
print("\nAvsluta programmet")
input("Press Enter to continue....")
menu_option = ["Förstaval\t\t", "Andraval\t\t", "Tredjeval\t\t", "Avsluta\t\t"]
menu_selected = 0
while True:
os.system('cls')
print("\x1b[?25l")
if menu_selected == 0:
print(menu_option[0] + "<--")
print(menu_option[1])
print(menu_option[2])
print(menu_option[3])
elif menu_selected == 1:
print(menu_option[0])
print(menu_option[1] + "<--")
print(menu_option[2])
print(menu_option[3])
elif menu_selected == 2:
print(menu_option[0])
print(menu_option[1])
print(menu_option[2] + "<--")
print(menu_option[3])
elif menu_selected == 3:
print(menu_option[0])
print(menu_option[1])
print(menu_option[2])
print(menu_option[3] + "<--")
key = getkey()
if key == keys.DOWN and menu_selected + 1 != len(menu_option):
menu_selected += 1
elif key == keys.UP and not (menu_selected == 0):
menu_selected -= 1
elif key == keys.ENTER:
if menu_selected == 0:
first_choice()
elif menu_selected == 1:
second_choice()
elif menu_selected == 2:
third_choice()
elif menu_selected == 3:
end_program()
break
Output:
I am currently trying to program a mathematical card trick, which asks the user what pile their random card is in. However, the second time it runs (the 'trick phase' has to occur 3 times for the trick to work) the list index becomes out of range. I am unsure where exactly the problem lies and will attach the current version so you can try to run it to see clearer. Thanks!
import random
def makedeck():
listy = []
cardsindeck = 0
while cardsindeck != 21:
suit = random.randint(1,4)
if suit == 1:
suit = "D"
elif suit == 2:
suit = "H"
elif suit == 3:
suit = "S"
else:
suit = "C"
cardtype = random.randint(1,13)
if cardtype == 1:
card = "A"
elif cardtype == 2:
card = "2"
elif cardtype == 3:
card = "3"
elif cardtype == 4:
card = "4"
elif cardtype == 5:
card = "5"
elif cardtype == 6:
card = "6"
elif cardtype == 7:
card = "7"
elif cardtype == 8:
card = "8"
elif cardtype == 9:
card = "9"
elif cardtype == 10:
card = "10"
elif cardtype == 11:
card = "J"
elif cardtype == 12:
card = "Q"
else:
card = "K"
cardandsuit = (card + suit)
if cardandsuit not in listy:
listy.append(cardandsuit)
cardsindeck = cardsindeck + 1
return listy
def dealdeck(listy):
list1 = []
list2 = []
list3 = []
for i in range(len(listy)):
if i % 3 == 0:
list1.append(listy[i])
elif i % 3 == 1:
list2.append(listy[i])
else:
list3.append(listy[i])
return[list1, list2, list3]
def makepiles(pile1,pile2,pile3):
print("Pile 1\t\tPile 2\t\t Pile 3\t\t")
for i in range(7):
print(pile1[i],"\t\t",pile2[i],"\t\t",pile3[i],"\t\t")
def usercardpile():
userinput = input("What pile is your card in?")
if userinput == "1" or userinput.title() == "One":
return 1
elif userinput == "2" or userinput.title() == "Two":
return 2
elif userinput == "3" or userinput.title() == "Three":
return 3
else:
print("Please only write 1, 2 or 3")
return usercardpile()
listy = makedeck()
pile1, pile2, pile3 = dealdeck(listy)
for i in range(1,4):
newlisty = makepiles(pile1,pile2,pile3)
userspile = usercardpile()
if userspile == 1:
newlisty = (pile2,pile1,pile3)
elif userspile == 2:
newlisty = (pile1,pile2,pile3)
else:
newlisty = (pile1,pile3,pile2)
pile1, pile2, pile3 = dealdeck(newlisty)
print("Your card is",newlisty[10])
One issue is with this line of code:
newlisty = makepiles(pile1, pile2, pile3)
You're expecting makepiles to return 3 lists, whereas it returns None (no explicit item returned).
I imagine if you were to return the piles from that function, it'd work.
The other thing is, You are doing this:
newlisty = (pileX, pileY, pileZ)
This will create a tuple of lists, and you will iterate over the entire lists rather than the individual cards. I believe you want
newlisty = pile1 + pile3 + pile2`
This'll create a composite list of 21 elements by linearly combining the smaller piles.
Other comments:
Consider storing your decktype and card type in dicts. That way, you can quickly lookup and generate your piles without having to write a long set of if statements. Example:
You can reduce
cardtype = random.randint(1,13)
if cardtype == 1:
card = "A"
elif cardtype == 2:
card = "2"
elif cardtype == 3:
card = "3"
elif cardtype == 4:
card = "4"
elif cardtype == 5:
card = "5"
elif cardtype == 6:
card = "6"
elif cardtype == 7:
card = "7"
elif cardtype == 8:
card = "8"
elif cardtype == 9:
card = "9"
elif cardtype == 10:
card = "10"
elif cardtype == 11:
card = "J"
elif cardtype == 12:
card = "Q"
else:
card = "K"
To...
cardtype_lookup = { 1 : 'A', 2 : '2', 3 : '3', .... 12 : 'K' }
card = cardtype_lookup[random.randint(1, 13)]
...And so on.
I think you are hitting a few issues with your code beyond just the final iterations. Below are some suggestions along with comments that I believe accomplishes your purpose.
from random import shuffle
# Function for generating 21 random cards
def makedeck():
# Create 52 cards by suit and cardtype
listy = [card + suit for card in ['A','2','3','4','5','6','7','8','9','10','J','Q','K'] for suit in ['D','H','S','C']]
# Shuffle the list
shuffle(listy)
# Choose only the first 21 items of that list
listy = listy[:21]
return listy
# Function for dividing 21-card deck into 3 equally-sized piles
def dealdeck(listy):
# Iterate over listy, stepping by 3, starting with the first, second, and third item
list1 = listy[::3]
list2 = listy[1::3]
list3 = listy[2::3]
# Return the three lists as three items to correspond to the three piles of the call
return list1, list2, list3
# This works
def makepiles(pile1,pile2,pile3):
print("Pile 1\t\tPile 2\t\t Pile 3\t\t")
for i in range(7):
print(pile1[i],"\t\t",pile2[i],"\t\t",pile3[i],"\t\t")
# This works
def usercardpile():
userinput = input("What pile is your card in?")
if userinput == "1" or userinput.title() == "One":
return 1
elif userinput == "2" or userinput.title() == "Two":
return 2
elif userinput == "3" or userinput.title() == "Three":
return 3
else:
print("Please only write 1, 2 or 3")
return usercardpile()
listy = makedeck()
pile1, pile2, pile3 = dealdeck(listy)
for i in range(1,4):
# Because this function does not return anything, it should be run on its own, and not assigned to a variable
makepiles(pile1,pile2,pile3)
userspile = usercardpile()
# Now you want to re-order the piles based on user input. Because these are lists, you can simply add them together in a new order to create a newly arranged list
if userspile == 1:
newlisty = pile2 + pile1 + pile3
elif userspile == 2:
newlisty = pile1 + pile2 + pile3
else:
newlisty = pile1 + pile3 + pile2
# Now you create new piles based on the re-sorted list and re-iterate
pile1, pile2, pile3 = dealdeck(newlisty)
# Uses .format method instead
print("Your card is {}".format(newlisty[10]))
I have code here for moving a card from the deck to the foundation pile. I've imported the necessary details, etc. My problem is, it's too long. Is there any way to make it shorter? How? Thanks :)
def dtof():
suit = raw_input("enter suit: ")
v = trash.pop()
if suit == "D":
if card.suitNumber[v.suit] == 1:
if card.rankNumber[v.rank] == 0:
Diamond.append(v)
elif card.rankNumber[v.rank] == card.rankNumber[Diamond[-1].rank] + 1:
Diamond.append(v)
else:
trash.append(v)
return Diamond[-1]
else:
trash.append(v)
elif suit == "H":
if card.suitNumber[v.suit] == 2:
if card.rankNumber[v.rank] == 0:
Heart.append(v)
elif card.rankNumber[v.rank] == card.rankNumber[Heart[-1].rank] + 1:
Heart.append(v)
else:
trash.append(v)
return Heart[-1]
else:
trash.append(v)
elif suit == "C":
if card.suitNumber[v.suit] == 4:
if card.rankNumber[v.rank] == 0:
Clubs.append(v)
elif card.rankNumber[v.rank] == card.rankNumber[Clubs[-1].rank] + 1:
Clubs.append(v)
else:
trash.append(v)
return Clubs[-1]
else:
trash.append(v)
elif suit == "S":
if card.suitNumber[v.suit] == 3:
if card.rankNumber[v.rank] == 0:
Spade.append(v)
elif card.rankNumber[v.rank] == card.rankNumber[Spade[-1].rank] + 1:
Spade.append(v)
else:
trash.append(v)
return Spade[-1]
else:
trash.append(v)
else:
trash.append(v)
Consider merging Diamond, Heart, Clubs and Spade into a single dictionary, with the key being suit.
Newbie python here. How can I break out of the second while loop if a user selects "Q" for "Quit?"
If I hit "m," it goes to the main menu and there I can quit hitting the "Q" key.
while loop == 1:
choice = main_menu()
if choice == "1":
os.system("clear")
while loop == 1:
choice = app_menu()
if choice == "1":
source = '%s/%s/external' % (app_help_path,app_version_10)
target = '%s/%s' % (target_app_help_path,app_version_10)
elif choice == "2":
source = '%s/%s/external' % (app_help_path,app_version_8)
target = '%s/%s' % (target_app_help_path,app_version_8)
elif choice.lower() == "m":
break
loop = 0
elif choice.lower() == "q":
break
loop = 0
sendfiles(source, target)
# Internal files
elif choice == "q":
loop = 0
App menu method:
def app_menu()
print "Select APP version"
print "-------------------"
print "1) 11"
print "2) 10"
print "3) 8"
print "m) Main Menu"
print "q) Quit"
print
return raw_input("Select an option: ")
You nearly have it; you just need to swap these two lines.
elif choice.lower() == "m":
break
loop = 0
elif choice.lower() == "m":
loop = 0
break
You break out of the nested loop before setting loop. :)
Change
break
loop = 0
to
loop = 0
break
in your elif blocks.
Use an exception.
class Quit( Exception ): pass
running= True
while running:
choice = main_menu()
if choice == "1":
os.system("clear")
try:
while True:
choice = app_menu()
if choice == "1":
elif choice == "2":
elif choice.lower() == "m":
break
# No statement after break is ever executed.
elif choice.lower() == "q":
raise Quit
sendfiles(source, target)
except Quit:
running= False
elif choice == "q":
running= False
Use two distinct variables for both loops, eg loop1 and loop2.
When you first press m in the inner loop you just break outside, and then you can handle q separately.
By the way you shouldn't need the inner variable to keep looping, just go with an infinite loop until key 'm' is pressed. Then you break out from inner loop while keeping first one.
Rename your top loop to something like mainloop, and set mainloop = 0 when q is received.
while mainloop == 1:
choice = main_menu()
if choice == "1":
os.system("clear")
while loop == 1:
choice = app_menu()
if choice == "1":
source = '%s/%s/external' % (app_help_path,app_version_10)
target = '%s/%s' % (target_app_help_path,app_version_10)
elif choice == "2":
source = '%s/%s/external' % (app_help_path,app_version_8)
target = '%s/%s' % (target_app_help_path,app_version_8)
elif choice.lower() == "m":
loop = 0
break
elif choice.lower() == "q":
mainloop = 0break
break
sendfiles(source, target)
# Internal files
elif choice == "q":
mainloop = 0
You could put this into a function and return:
import os.path
def do_whatever():
while True:
choice = main_menu()
if choice == "1":
os.system("clear")
while True:
choice = app_menu()
if choice in ("1", "2"):
app_version = app_version_10 if choice == "1" else app_version_8
source = os.path.join(app_help_path, app_version, "external")
target = os.path.join(target_app_help_path, app_version)
sendfiles(source, target)
elif choice.lower() == "m":
break
elif choice.lower() == "q":
return
Admittedly, I don't quite get when you want to break the inner loop and when you want to quit both loops, but this will give you the idea.