Modifying a dictionary inside of an if statement - python

I've been trying to make a basic text game in Python, and I'm using dictionaries to contain the player's information. I want to make it so that when a player's health reaches 0, the code will stop running. I've had trouble making that happen. My dictionary, which is at the beginning of my code, looks like this:
playerAtt = {}
playerAtt["Weapon"] = "Baseball bat"
playerAtt["Party"] = "Empty"
playerAtt["Health"] = 15
playerAtt["Cash"] = "$100"
print(playerAtt)
if playerAtt['Health'] <= 0:
exit()
The bottom section is what I wrote to try and make the code stop running when the player's health reached zero, but it doesn't seem to work. In one path of my game, your health gets set to zero and the game is supposed to end, but the program continues to run:
townChoice = raw_input("You met a traveler in the town. 'Yo. I'm Bob. Let's be friends.' Will you invite him to your party? Y/N\n")
if townChoice == 'y' or townChoice == 'Y':
print("That kind traveler was not such a kind traveler. He stabbed you with a machete. RIP " + Name + '.')
playerAtt['Health'] == 0
When you reach this part of the game, all it does is print the message, and moves on to the next decision. In this situation, I could just manually end the program by doing exit() under the print command, but there are circumstances where the player only loses a fraction of their health, and they would eventually reach zero. Sorry if this is a stupid question, I've only been working on Python for a few days.

You have two "=" when you set the player's health to 0

I had put 2 == instead of 1 = when defining
playerAtt["Health"].
Also, I needed to make sure it was constantly checking if the player's health was zero, so I used a while loop. I used
while playerAtt["Health"] = 0:
deathmsg()
exit()
to fix it. deathMsg was a function I made to display a random death message, for more information.

Related

Python Tkinter Tic Tac Toe AI

I am trying to make a Tic Tac Toe in tkinter however I am running into some problems with the AI system. What I'm trying to do is that if the middle spot isn't taken it will chose it and if it isn't it will pick a random number and map out all the routes it can take to win and all the routes the player will use and for it to block them however I am running into this problem. My code:
def click1():
if isTaken1 == False:
Button1.config(text = "O")
pTurn1 = True
Button1 = Button(root, command = click1)
Button1.config(width = "5", height = "3")
Button1.place(x = 100, y = 30)
#I have nine of these however I can't show them all as it will make this post very long
I am trying to add it when the player takes a turn (The pTurn variable) it will make the AI act however, I have no idea where to put the AI code.
I am trying to do something like:
If isTaken5 == False: #Checking if the middle spot is taken
Button5.config(text = "X") #Player is O and AI is X
else:
AIChoice = random.randint(1,8)
if AIChoice == 1:
Button1.config(text = "X")
So you get the basic idea for it, but I have no idea where to put the cod as if statements put after where you change it don't work.
In a turn-based game, you can call the AI function immediately after the user takes their turn. For example, let's start with a function for the computer's turn. This is where your ai exists:
def computer_turn():
<your logic to pick an empty square>
Ideally you'll also want to check for the case where the computer picked the last place, but I've left that out now to keep the example simple.
Next, we have a function for the player's turn. In this example, it takes a row and column that was clicked on. This will select the button that was clicked, check to see if the game is over, and call computer_turn if the game isn't over yet.
It would look something like this:
def player_turn(row, column):
<your logic to select the given row and column>
if not is_game_over():
computer_turn()
This isn't the only way to handle the game logic. You could create a small state machine, for example. However, for a game as simple as tic-tac-toe, this turn-based system is good enough.

Can I make a print statement run before a module I imported?

I am a beginner to python and coding in general and I was wondering how I can make a print statement run before a module I imported. I am making a number guessing game and in my main file where I combine all the modules, I have a general function for running all the code together. It would be best if I show my code so you guys will have a better understanding of what I am dealing with:
import random
import lvl1
import time
level1 = lvl1.Level_1_activated()
# This is the main file combining everything together to make this game playable
introduction = """
Hello and welcome to NumGuess by Sava. Here is a little bit about the game:
The game works by having 3 levels, each where you must pick a number between a range of
1-10 (level 1), 1-20 (level 2), and 1-50 (level 3).
You are given 5 attempts in the first level, 10 in the second level, and 20 in the final one.
You can also access a hint by typing ‘hint’. You win the game by picking the right number in each level.
You lose the game when you run out of tries. You can get a free bonus with 5 extra tries if you type ‘hlp’.
"""
def start_game(time, lvl1):
print(introduction)
level1
start_game(time, lvl1)
This is just the code for the main module, I have the code for lvl1 (which is the first level of my 'game'), and I have a class which has all the functions which then take part in the while loop. I will also show that file:
import random
import time
# I will fist make variables for the time breaks. S is for short, M is for medium and L is for long
S = 0.2
M = 0.7
L = 1.1
class Level_1_activated():
def get_name(self):
# This function simply asks the name of the player
name = input("Before we start, what is your name? ")
time.sleep(S)
print("You said your name was: " + name)
def try_again(self):
# This asks the player if they want to try again, and shows the progress of the level
answer = (input("Do you want to try again? "))
time.sleep(M)
if answer == "yes":
print("Alright!, well I am going to guess that you want to play again")
time.sleep(M)
print("You have used up: " + str(tries) + " Of your tries. Remember, when you use 5 tries without getting the correct number, the game ends")
# Return statement for if the player wants to play again
return True
else:
print("Thank you for playing the game, I hope you have better luck next time")
# This is the return statement that stops the while loop
return False
def find_rand_num(self, random):
# This is the core of the level, where the player just chooses numbers between 1 and 10
time.sleep(S)
print("The computer is choosing a random number between 1 and 10... beep beep boop")
time.sleep(L)
# The list of numbers for the level that the player is on at the moment
num_list = [1,10]
number = random.choice(num_list)
ques = (input("guess your number, since this is the first level you need to choose a number between 1 and 10 "))
print(ques)
if ques == str(number):
time.sleep(S)
print("Congratulations! You got the number correct!")
# Yet another return statement for the while loop
return "Found"
elif input != number:
time.sleep(M)
print("Oops, you got the number wrong")
# This variable is fairly self-explanatory; it is what controls how many itterations there are in the while loop
tries = 1
while tries < 6:
if tries < 2:
Level_1_activated().get_name()
res = Level_1_activated().find_rand_num(random)
if res == "Found":
break
checker = Level_1_activated().try_again()
if checker is False:
break
tries += 1
If you go back to this function in the main file:
def start_game(time, lvl1):
print(introduction)
level1
I intentionally put the print statement before the module to make it run first, and I have tried different approaches to this and still can't seem to get a grasp on what I'm doing wrong here. Thank you for taking the time to read the code and I would be very grateful if any of you have a possible solution to this.
there are number of thing you can do, one is encapsulate your code into functions that only run when you ask for it
lvl1
... #all the previous code
def run_game():
tries = 1
while tries < 6:
...
tries += 1
you can also make a distinction between being executed directly vs being imported, to do that is simple, you include the following check (usually at the end of the file)
if __name__ == "__main__":
#if true it mean that you're executing this module directly, otherwise it was imported
#and you include here whatever you want that happens when you execute the module directly but not when is imported, like for example running a game
run_game()
__name__ is a special variable and python will assigned the value "__main__" if executed directly, otherwise it will be the name of the file, like "lvl1" for example
And in your main you can import it and do stuff like
import lvl1
...
def start_game():
print(introduction)
lvl1.run_game()

How to get rid of the global variables

I don't want to use the global-variable, but how do I make this without them?
(I have more functions and so on, so this isn't all)
Players turn. I use the global-variable to make sure the turns are switching, tried some other sulotion however the turns didn't switch...
#Check if the shot hit any computerships
def player_hit_check():
global players_turn
shot = player_shot()
check_if_hit = set(computer_ships) & set(player_turn_shot)
if(check_if_hit == set()):
print("You missed! Switching turns...")
time.sleep(3)
players_turn = 1
else:
print(f"YOU MADE A BIG BANG ON ",player_turn_shot,"!")
computer_ships.remove(shot)
all_player_hits.append(shot)
Computers turn
#Check if the computers shot hit any player ships
def computer_hit_check():
global computers_turn
computer_random_shot = computer_shot()
check_if_hit = set(player_ships) & set(computer_turn_shot)
if(check_if_hit == set()):
print("Computer missed! It's now your turn.")
time.sleep(3)
computers_turn = 1
else:
print(f"COMPUTER MADE A BIG BANG ON ",computer_turn_shot,"!")
player_ships.remove(computer_random_shot)
all_computer_hits.append(computer_random_shot)
The game it self
#Runs the game
while True:
#Players turn
players_turn = 0
while players_turn < 1:
print('\n'.join('\t'.join(row) for row in board.values()))
print("Playerships:",player_ships)
print("Computerships:",computer_ships)
print("You have shot on",all_player_shots,"and has knocked out these ships:",all_player_hits)
print("The computer has shot at these coordinates",all_computer_shots,"and has knocked out these ships:",all_computer_hits)
player_hit_check()
#Computers turn
computers_turn = 0
while computers_turn < 1:
computer_hit_check()
In your case you don't need global variables at all. Your program is not using them to carry information back and forth.
In your case you just need to get information back from your functions. So in the case of player_hit_check():
def player_hit_check():
shot = player_shot()
check_if_hit = set(computer_ships) & set(player_turn_shot)
if(check_if_hit == set()):
print("You missed! Switching turns...")
time.sleep(3)
return 1
else:
print(f"YOU MADE A BIG BANG ON ",player_turn_shot,"!")
computer_ships.remove(shot)
all_player_hits.append(shot)
return 0
And the call site would be like this:
while True:
#Players turn
players_turn = 0
while players_turn < 1:
# prints elided ...
players_turn = player_hit_check()
The problem with global variables is, that they fly around in an unstructured manner.
There are several approaches to solve global variables
One first step to get rid of global variables is to use singletons (https://en.wikipedia.org/wiki/Singleton_pattern). This will bundle similar values into one class. So the values are more structured and easier to track.
Use classes. If the global value is used in an environment that can be associated to a single responsibility, it can be productive to bundle all functions in a class and make the global variable to a class variable or property of the class
Pass it through. In many programs there is the need of settings class or state class. Put everything in there that defines the current state or starting state of the program and pass it through your code. The downside of passing is, that this classes tend to become almighty classes that appear in every constructor.
There are certainly more approaches how to get rid of global variables, but this are some common strategies.

My function is too long. In order to pass class I need < 18 lines

So I am a total beginner yet this is 100% my code and I am proud of it. Now mind you I need a little cleaning up, however it does what I want it too. My issue is this: In order to turn this in for credit, one of the things is that procedures(functions) should not contain more than 18 lines. My function gameCont() has many more. Would anyone have suggestions on how I could shorten it up? Additionally I am obviously challenged when it comes to function parameters so any help is appreciated. Please be gentle as I am BRAND NEW! :)
game1 = "When dealing with SCUBA diving there are many dangers to consider. The very first one is _1_. \
I mean if you take water into your lungs, you are NOT SCUBA diving. Another is rising to the surface too quickly which could \
result in the _2_. Now this is a funny name, as I am sure when it happens, you dont feel 'bendy'. Let's also consider Nitrogen Narcosis.\
If you dont know what that is, well when you are very deep and your body is absorbing more nitrogen than it is used to, you can get \
feeling kinda _3_ feeling as though you just drank not one, but _4_ martinis"
game1_answers = ["drowning", "bends", "drunk", "2"]
game2 = "When you first learn to dive you are taught to do dives within a no DECOmpression limit(NDL). \n This means you do not want to \
stay that deep too long or you will rack up _1_. \n If you DO stay longer than what the NDL allows, you will have an obligation to \
take your time getting to the surface allowing that _2_ gas to leave your body. If you were taking IN gas you may call it \
in-gassing, but when you are decompressing, it may be called _3_-gassing. You are taught also, how to read _4_"
game2_answers = ["deco", "nitrogen", "off", "tables"]
game3 = "Equipment used by cold water divers such as myself are as such. On my head I would wear a _1_. To help regulate the breathing\
pressure from my SCUBA tank I would use a _2_. To help me propel through the water I would place_3_ on my feet. Considering \
we cannot see underwater I need to be wearing a _4_ on my face. Diving in the tropic, many people would use wetsuits, however it's\
very cold where I dive so we wear _5_ suits."
game3_answers = ["hood", "regulator", "fins", "mask", "dry"]
def howManyTries():
gameTries = raw_input("Thanks for giving my quiz a try, how many attempts do you want? ")
return int(gameTries)
def game_choice(): #this function is used to determin which difficulty the user wants and returns the proper game and answer list
user_input = raw_input("Greetings. This is my Udacity project for fill in the blanks. Which one of my options would you like?\
easy, hard, or hardest? Please take note of capitalization ")# this will define the user_input variable to raw input placed in by user
print ("\n" * 20)# just something to clean up the screen
print "Decided to choose " + user_input + '?' " Well " + user_input + " it is"# this confirms to the user which difficulty they chose.
print ""
print ""
if user_input == "easy": #easy returns game1 and game1 answers
return game1, game1_answers
elif user_input == "hard": # hard returns game2 and game2 answers
return game2, game2_answers
elif user_input == "hardest": #hardest returns game3 and game 3 answers
return game3, game3_answers
else:
print "It seems that " + user_input + " is not a valid response" #in case the user doesnt choose or spell choice correctly
def gameCont():
blanks = 1 #this assings blank to 1 which will tell the user which blank they are guessing in below prompt
attempts = howManyTries() #this calls the howManyTries function for a user choice integer
quiz, answers = game_choice() #this returns 2 values (game# and game# answers)
while attempts > 0: #while attempts (called from function) is greater than 0 we will loop this
print quiz #prints the chosen quiz for user updated each time the loop runs with correct answer
print("\n" * 10) #clears some more screen to loook better for the user
guess = raw_input("Reading the above paragraph, What would your guess be for _" + str(blanks) + "_") #asks for guess for current blank which always starts at 1
print("\n" * 10) #clears some more screen to loook better for the user
if guess == answers[blanks - 1]: #because indexing count starts at zero, and blanks start at 1 this will check if answer is equal to blanks - 1
print "As you can see your correct choice has replaced the variable, great job!!"#this will print if the guess is correct
quiz = quiz.replace("_" + str(blanks) +"_", answers[blanks - 1]) # here is the line of code that replaces the blank with the correct guess
blanks += 1 # this adds 1 to the blank which will prompt the user to move to the NEXT blank when loop begins again
if blanks > len(answers):
print ("\n" * 10)
print "YOU DID IT!! Here is the final paragraph with all the correct answers"
print ("\n" * 2)
print quiz
break
elif guess != answers[blanks -1]: #if the answer does not match the list index
attempts = attempts - 1 #then we will subtract 1 from the attempts
print ("\n" * 10)
print "Oops that is not correct, there should be hints in the paragraph" # lets user know they were wrong
print "You have " + str(attempts) + " attempts left." # lets the user know how many attempts they have left
print ""
if attempts < 1:
print "Well it looks like you are out of choices, Try again?"
break
print "Thanks for playing"
gameCont()
All of the printing that you're doing could be done in a separate function
def game_print(newlines_before, text, newlines_after)
print ("\n" * newlines_before + text + "\n" * newlines_after)
Two suggestions:
Delegate tasks that are accomplished by your function to smaller functions. So, for example, if you had a function that needed perform task A and performing that task could be divided into tasks B, C, and D, then create helper functions and call them inside of the function that does task A.
You have long strings, maybe store them somewhere else? Create a class just for constant strings of related functions and access that when you need a particular string. It'll make it less likely that you'll make a mistake when you need to use that string in multiple locations.
class Constants:
str1 = "..."
str2 = "..."
print(Constants.str1)
you can call a function from inside another function. inside an if statement you could call a small new function that just prints some stuff. this should make it easy to get the function size down.
something like this should work:
def correct(quiz, blanks):
print "As you can see your correct choice has replaced the variable, great job!!"
quiz = quiz.replace("_" + str(blanks) +"_", answers[blanks - 1]) # here is the line of code that replaces the blank with the correct guess
blanks += 1 # this adds 1 to the blank which will prompt the user to move to the NEXT blank when loop begins again
if blanks > len(answers):
print ("\n" * 10)
print "YOU DID IT!! Here is the final paragraph with all the correct answers"
print ("\n" * 2)
print quiz`
remember that you still want to break after calling that function in order to exit your loop.

Python programming for card game War

This program is supposed to play the card game War. Okay so I need to be able to prompt the user to keep playing and have them respond by hitting the enter key. I'm not sure how to make this happen. Help?
import cards
# Create a deck of cards
the_deck = cards.Deck()
# Shuffle the deck, then display it in 13 columns
the_deck.shuffle()
print( "===== shuffled deck =====" )
the_deck.display()
def main():
'''This function deals out half the deck to each
player. It sorts the rank so as to solve the problem
with Aces causing an infinite game'''
player1_list=[]
player2_list=[]
for i in range( 26 ):
p1_temp= the_deck.deal()
player1_list.append( p1_temp )
p2_temp= the_deck.deal()
if (p2_temp.rank()==1):
player1_list.append(p2_temp)
player2_list.append(player1_list.pop(0))
else:
player2_list.append(p2_temp)
print()
# Card dealt to Player #1
player1_card = player1_list.pop( 0 )
print( "===== player #1 =====" )
print( "Card dealt to player #1:", player1_card )
print( player1_list )
print()
#Card dealt to Player #2
player2_card=player2_list.pop(0)
print( "===== player #2 =====" )
print("Card dealt to player #2:",player2_card)
print( player2_list )
# Compare the two cards using overloaded operators
print()
if player1_card == player2_card:
print( "Tie:", player1_card, "and", player2_card, "of equal rank" )
elif player1_card > player2_card:
print("Player #1 wins:",player1_card,"of higher rank than",player2_card)
else:
print("Player #2 wins:",player2_card,"of higher rank than",player1_card)
print()
main()
def keep_playing():
'''Determines whether the player wants to continue. If so they press the
Enter key and the function calls main to start all over.'''
still_playing=input('Press "Enter" to continue playing')
Enter=1
while still_playing==Enter:
main()
keep_playing()
Assuming the rest of your main is working (and the imported Deck class): your two main problems are you forgot to call your main and the method you are using to test the variable Enter. Since your taking an input for Enter you just need to test this against an empty string or just test that it is empty - as input strips newlines by default.
def play_hand():
print ("all the play code goes here")
#just a simple exit here no return needed
'''This function deals out half the deck to each
player. It sorts the rank so as to solve the problem
with Aces causing an infinite game
player1_list=[]
player2_list=[] ... etc ...'''
def keep_playing():
'''Determines whether the player wants to continue. If so they press the
Enter key and the function calls main to start all over.'''
return input('Press "Enter" to continue playing')
def main():
# the_deck = Card.Deck() # create deck instance (depending on how shuffle method is written this may need to go in while loop)
still_playing = "" #Set still_playing to empty string to more easily use input
while not still_playing: #this will keep going as long as still_playing is an empty string
print("hello main") # cause it fun :) - also as you can put an intro here or the shuffle so:
# the_deck.shuffle()
# print( "===== shuffled deck =====" )
# the_deck.display()
play_hand()
# Do all your other stuff here
still_playing = keep_playing() #Calls the function and stores returned value (can do this with just input but using return to show an option)
main()
As a secondary note, you need to learn how to isolate the problem within your code. To that end: the following shows a testable instance (and solution) of the enter to continue problem your having. Run this and it will only test (in this case solve) the enter problem, this is what Stack Overflow means by a minimal, complete, verifiable example.
As #IanAuld mentioned, you have not called your Keep_playing() function anywhere. Instead of calling main(), simply call Keep_playing(). If you'd like to just start the game without the "Press Enter to continue playing," just make the first line of the Keep_playing() function a call to main(), so that it runs and then keeps checking if the user wants to continue.
Also, you have an infinite loop in Keep_playing(). Put the input(...) part inside the while loop after you call main(). That way, it will reprompt every loop and change the still_playing variable.
It should look like this:
def keep_playing():
'''Determines whether the player wants to continue. If so they press the
Enter key and the function calls main to start all over.'''
still_playing=""
Enter=""
while still_playing==Enter:
main()
still_playing=input('Press "Enter" to continue playing')
keep_playing()
You can read this SO question to figure out how to implement reading the "enter" key as input (it's quite simple, so don't worry)
Additionally, as a good practice in Python (and most other languages), make variables and function names lowercase, as uppercase names are typically reserved for class use. Even if this isn't going to be spread or maintained around, it's good to get into the habit.

Categories

Resources