Is it possible to use a variable then later redefine it? - python

I´m making a project for school and it is a dice game. This snippet of my code is like a catch 22.
I need to define a variable otherwise it flags, so I do this but then every time the button is run it changes the value to zero instead of increasing it.
if Rollnop1 == 0 :
Userscore1 = Randomnumber
print ("User 1 ",Userscore1 )
Rollnop1 = Rollnop1+1 #But this changes it so it will go to the next players roll, every
#time the button is pressed it changes the variable back to 0
def gamerun():
global Player
global usernamestr
global passwordstr
global usernamestr2
global passwordstr2
Rollnop1 = 0
def roll2():
Rollnop2 = 0
Randomnumber = random.randint(2,12)
print ("Console: Random Number 2 = ",Randomnumber)
if Rollnop2 == 0 :
Userscore2 = Randomnumber
print ("User 2 ",Userscore2 )
def roll1():
Rollnop1 = 0 #Need to define this here otherwise It wont work
Randomnumber = random.randint(2,12)
print ("Console: Random Number = ",Randomnumber)
if Rollnop1 == 0 :
Userscore1 = Randomnumber
print ("User 1 ",Userscore1 )
Rollnop1 = Rollnop1+1 #But this changes it so it will go to the next players roll, every
#time the button is pressed it changes the variable back to 0
else:
roll2()
actdicegame = Tk()
gamerunl0 = Label(actdicegame, text = usernamestr, fg = "black")
gamerunl0.pack()
gamerunl1 = Label(actdicegame, text = "Roll The Dice", fg = "black")
gamerunl1.pack()
gamerunb1 = Button(actdicegame, text="ROLL",fg="Black", command=roll1)#Register Butto
gamerunb1.pack()
actdicegame.geometry("350x500")
print ("Console: GUI RUNNING 1")
actdicegame.mainloop()
snippet https://pastebin.com/FSWwBGpA

Use an option where you provide the player as part of the roll, that way you say which player is playing at any given time. The function below plays for the provided player and returns who is playing next
def roll(Rollnop=0):
UserScore = random.randint(2,12)
print ("Console: Random Number 2 = ", UserScore)
if Rollnop == 0 :
print ("User 1 ", UserScore)
return 1
else:
print ("User 2 ", UserScore)
return 0

This could answer your question: nested function change variable in an outside function not working. Basically you need to assign Rollnop1 = 0 and Rollnop2 = 0 in gamerun and declare them as nonlocal inside roll1 & roll2 before attempting to change their value.
– DarrylG Thank You so much and to everyone else who helped.
More here
nested function change variable in an outside function not working

Related

Simple Function Problem. Trying to make a simple dice roll race game that tracks the position when they roll the dice

Trying to figure out why the program won't run.
This is the error code I am getting:
update_position (random_roll_1, random_roll_2)
builtins.NameError: name 'random_roll_1' is not defined
I thought I had all the correct parameters but I guess not. Any help would be really appreciated
import random
from random import randint
#both of the players are able to roll out their turs
this is the function where the players can roll their dice and receive a random number
def roll_die(p1_move,p2_move):
if p1_move is True:
input('Press enter to roll the die for player 1')
random_roll_1 = randint(1,6)
random_roll_1 = str(random_roll_1)
print('Player 1 rolled ' + random_roll_1)
random_roll_1 = int(random_roll_1)
return random_roll_1
elif p2_move is true:
input('Press enter to roll the die for player 2')
random_roll_2 = randint(1,6)
random_roll_2 = str(random_roll_2)
print('Player 2 rolled ' + random_roll_2)
random_roll_2 = int(random_roll_2)
return random_roll_2
This part updates the position on where each player is after it rolls the dice. The players have to roll exactly 8 in order to win. Anything higher than that will cause the player to stay in its position
def update_position(random_roll_1, random_roll_2):
player_1_position = 0
player_2_position = 0
max_score = 8
if player_1_position < max_score:
if player_1_position + random_roll_1 > 8:
print('The roll was too high, player 1 stays in the same spot')
else:
player_1_position += random_roll_1
print('Player 1 moved up ' + random_roll_1 + ' spots!')
return player_1_position
elif player_2_position < max_score:
if player_2_position + random_roll_2 > 8:
print(' The roll was too high, player 2 stays in the same spot')
else:
player_2_position += random_roll_2
print('Player 2 moved up ' + random_roll_2 + ' spots!')
return player_2_position
this function checks to see if one of the players hit 8 as their score
#checks to see if any of the players have managed to reach the end of the game
def check_game_over(player_1_position, player_2_position):
if player_1_position == 8:
print('Player 1 has won!')
print('Thank you for playing!')
continue_game = False
return continue_game
elif player_2_position == 8:
print('Player 2 has won!')
print('Thank you for playing!')
continue_game = False
return continue_game
This function is what controls who's turn it is. I added in the roll dice function along with the update spot function as it would be easier to include them in one whole function together. This is where I am getting my problem.
#random_roll_1,random_roll_2, player_1_position, player_2_position
#change the turn over to the next player
def opponent():
p1_move = True
p2_move = False
if p1_move is True:
roll_die (p1_move, p2_move)
update_position (random_roll_1, random_roll_2)
p1_move = False
p2_move = True
return p1_move, p2_move
elif p2_move is True:
roll_die(p1_move, p2_move)
update_position (random_roll_1, random_roll_2)
p1_move = True
p2_move = False
return p1_move, p2_move
This function basically shows the user which location they are currently sitting at.
def display_state (player_1_position, player_2_position, p1_move, p2_move):
if p1_move is True:
player_1_position = str(player_1_position)
print('Player 1 is in ' + player_1_position + ' spot')
player_1_position = int(player_1_position)
elif p2_move is True:
player_2_position = str(player_2_positon)
print('Player 2 is in ' + player_2_position + ' spot')
player_2_position = int(player_2_position)
Not entirely sure if this function is right at all because I still don't understand main functions completely so not sure if this main function works
def main():
#display instructions
continue_game = True
while continue_game:
opponent()
display_state (player_1_position, player_2_position, p1_move, p2_move)
check_game_over(player_1_position, player_2_position)
main()
So there are a few errors in your program above. The runtime error you stated above is caused when you try to pass 2 variables into the update_position function before they have been defined.
roll_die (p1_move, p2_move)
## random_roll_1 and random_roll_2 have not been defined
update_position (random_roll_1, random_roll_2)
However, before you deal with this error, there is a key programming concept to understand. Global and Local variables.
A Global variable is one which the entire program can use. They are normally defined at the top of your program:
p1_move = True
p2_move = False
def roll_die(): ...
def main(): ...
etc
A Local variable is one which can only be used inside of the function it was created in.
def foo():
x = 10
y = 5
return x + y
In this example, the variables x and y are local variables and cannot be used in other functions of your program (as they only exist inside the function foo).
One thing to note, in the case where you pass a variable as a functional argument, then modify that variable in the function without returning the modified variable. That variable will only be modified inside that function, no where else. This is true for primitive data types (variables not passed by reference).
def foo(z):
z += 1
z = 5
foo(z)
print(z)
In this example, the output would be 5, not 6 as the modified z variable in the function foo has not been returned.
For this reason alone, global variables may seem like the better option, however in general global variables are a bad idea and it is recommended that you stick to using local variables.
More information about Global and Local variables.
With this knowledge, some of your errors may seem more obvious.
For example, in your function roll_die, you define 2 variables random_roll_1 and random_roll_2. However you try to use these variables in other functions, update_position for example.
I realise that you have tried to return each random_roll variable independently from the roll_die function, however you do not store these returned values.
# Original
roll_die (p1_move, p2_move)
# Correctly returned
random_roll = roll_die(p1_move, p2_move)
In the next line, you then try to use both random_roll_1 and random_roll_2 variables, even though you only know 1 of those variables at that stage.
# Original
update_position (random_roll_1, random_roll_2)
# Possible Correction
update_position(random_roll)
You would then have to redefine the update_position function, thinking about each player's go as if it happened one after another, and not both at the same time.
I would also like to emphasize the importance of reducing the amount of duplicate code in your program.
Your opponent function could instead be written as:
def opponent(p1_move, p2_move):
random_roll = roll_die(p1_move, p2_move)
update_position(random_roll)
p1_move = not p1_move
p2_move = not p2_move
return p1_move, p2_move
This refactoring has changed a few details, most importantly, the use of the not. This operator will turn True->False and False->True. For example, if p1_move is false, not p1_move is True.
In addition, the function has parameters p1_move, p2_move, as these variables will be required in other parts of your program, you should define them outside of this functions scope, and pass them as arguments into your other functions. And don't forget to store the return values!
Just to note, this function refactoring is an example of how to reduce duplicate code, and is designed to be used with your modified program.
There are a few more modifications required to make your program run, but I will let you work them out for yourself.

How to Add Win/Loss Counter to Rock Paper Scissors Program

I have pretty much finished this Rock Paper Scissors program, but one of the final steps is to add a counter to print the Win, Loss, and Tie ratio after the user is done playing.
I tried in the count_win_loss() function to enumerate the messages index that I pass to it in the play_game() function, but all it is returning zeros
import random
def count_win_loss(messages_from_result):
player_wins = 0
cpu_wins = 0
ties = 0
#This is supposed to get the index value position of this list, which
should be defined at the end of `play_game()` function.
for index in enumerate(messages_from_result):
new_index = index
#NOT WORKING NEEDS TO BE FIXED
if new_index == 0:
ties += 1
elif new_index == 1:
player_wins += 1
elif new_index == 2:
cpu_wins += 1
else:
ties += 0
player_wins += 0
cpu_wins += 0
#NOT WORKING NEEDS TO BE FIXED
print(player_wins)
print(cpu_wins)
print(ties)
#print('\nHuman Wins: %d, Computer Wins: %d, Ties: %d' % (player_wins, cpu_wins, ties))
This elif statement appears at the end of my game function. It executes when a user inputs '2' which ends the loop.
#Creates a format that can be passed to the results matrix.
#Additionally creates an index 3 that I will reference as the error value.
guesses_index = guess_dict.get(user_guess, 3)
computer_index = guess_dict.get(computer_guess)
result_index = results[guesses_index][computer_index]
final_result = result_messages[result_index]
elif play_again == '2':
count_win_loss(result_messages) #NOT WORKING NEED HELP
print('Thanks for playing!')
continue_loop = False
I pass it this messages list:
result_messages = [
"You tied!",
"You win!",
"The Computer won. :(",
"Invalid weapon, please try again."
]
As mentioned in the title, I need a win/loss counter, which I thought my calc_win_loss() would do
New_Index variable is not defined inside this function, therefore global to where ever you defining the value and get in the starting of this function
For ex:-
def a():
b = 2
def c(): . print(b) . Whenever you will call c() it will cause an error because b is a local variable
in side function a() however if you do
def a():
global b
b = 2
def c():
print(b)
Now when you call a() and then c(). Th error will go away

Command function for button "resets"

So in my tkinter python program I am calling on a command when a button is clicked. When that happens it runs a function but in the function I have it set a label to something on the first time the button is clicked and after that it should only update the said label. Basically after the attempt it changes the attempt to 1 ensuring the if statement will see that and not allow it to pass. However it keeps resetting and I don't know how to stop it. When you click the button no matter first or third the button resets and proof of that occurs because the h gets printed. It's as if the function restarts but it shouldn't since it's a loop for the GUI.
def fight(): #Sees which one is stronger if user is stronger he gets win if no he gets loss also displays enemy stats and removes used characters after round is finished
try:
attempt=0
namel = ""
namer=""
left = lbox.curselection()[0]
right = rbox.curselection()[0]
totalleft = 0
totalright = 0
if left == 0:
namel = "Rash"
totalleft = Rash.total
elif left==1:
namel = "Untss"
totalleft = Untss.total
elif left==2:
namel = "Illora"
totalleft = 60+35+80
if right == 0:
namer = "Zys"
totalright = Zys.total
elif right==1:
namer = "Eentha"
totalright = Eentha.total
elif right==2:
namer = "Dant"
totalright = Dant.total
lbox.delete(lbox.curselection()[0])
rbox.delete(rbox.curselection()[0])
print(namel)
print(namer)
if attempt == 0:
wins.set("Wins")
loss.set("Loss")
print("h")
attempt=1
if (totalleft>totalright):
wins.set(wins.get()+"\n"+namel)
loss.set(loss.get()+"\n"+namer)
else:
wins.set(wins.get()+"\n"+namer)
loss.set(loss.get()+"\n"+namel)
except IndexError:
pass
Also for those of you who saw my previous question I still need help with that I just also want to fix this bug too.
At beginning of function fight you set attempt = 0 so you reset it.
Besides attempt is local variable. It is created when you execute function fight and it is deleted when you leave function fight. You have to use global variable (or global IntVar)
attempt = 0
def fight():
global attempt
BTW: of you use only values 0/1 in attempt then you can use True/False.
attempt = False
def fight():
global attempt
...
if not attempt:
attempt = True

Handling default values with global variables in python

i am trying the following code:
import simplegui
import random
import math
def new_game():
global secret_number
global low
global high
global n
print "New game. Range is from" ,low ,"-",high
secret_number=random.randrange(low,high)
n=math.ceil(math.log((high-low+1),2))
print "no of guesses",n
print " "
def new_game1():
global secret_number
print "New game. Range is from 0-100"
print " "
secret_number=random.randrange(0,100)
# define event handlers for control panel
def range100():
global low,high
low=0
high=100
new_game()
def range1000():
global low
global high
low=0
high=1000
new_game()
def input_guess(guess):
global secret_number
global n
g=int(guess)
print "Guess was",g
--n
print "no of guesses left",n
if(g>secret_number):
print "Lower"
elif(g<secret_number):
print "Higher"
else:
print "Equal"
frame = simplegui.create_frame('Testing', 200, 200)
button1 = frame.add_button('Range is(0,100)', range100,200)
button2 = frame.add_button('Range is(0,1000)', range1000,200)
inp = frame.add_input('Enter a guess', input_guess,200)
frame.start()
new_game1()
the problem with my above code is that I want to use a single newgame() fn which takes the default value of low as 0 and high as 100 . Right now I have bifurcated that function into newgame1() which is doing computations on the default values
How to rectify this problem? Please help
Instead of having the limits as global variables you could send them as function arguments. You can set the default values to something and override them as needed. new_game() might become something like:
def new_game( low = 0, high = 100 ):
global secret_number, n # Maybe these can be function arguments as well?
print "New game. Range is from" ,low ,"-",high
secret_number=random.randrange(low,high)
n=math.ceil(math.log((high-low+1),2))
print "no of guesses",n
print " "
Your range functions would become:
def range100():
new_game() # high & low take default values of 0,100
def range1000():
new_game(high = 1000) # high is now 1000
# My own function
def rangeMinus1000():
new_game(low = -100, high = 1000) # low is -100 & high is 1000

Problems transferring information from one part of a function to another

While working on my program I have run into a problem where the information stored in Menu option 1 is not being transferred to Menu option 2. As you can see it is correctly stored when in menu one. When it returns to go to menu option 2 its like it never went to option 1.
update #1:
some suggestions I've had is to understand scope? from what I can tell the program is not passing the data along to its parent program even though I've typed out return in each of the definitions.
#Must be able to store at least 4 grades
#Each class can have up to 6 tests and 8 hw's
#Weighted 40%*testavg 40% hw average attendance is 20%
#User must be able to input a minimum grade warning
#after each test the your program must calculate the students average and issue warning if necessary
##Define the Modules##
import math
def menu (a): #2nd thing to happen
menuend = 'a'
while menuend not in 'e':
menuend = raw_input("Type anything other then 'e' to continue:\n")
print "What would you like to do ?"
menudo = 0
print "1 - Enter Courses\n2 - Select Course to Edit\n3 - Save File\n4 - Load File\n5 - Exit\n"
menudo = input("Enter Selection:")
if (menudo == 1):
menuchck = 0
menuchck = raw_input("\nYou have entered #1 (y/n)?:\n")
if menuchck in ["Yes","yes","y","Y"]:
x = m1()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 2):
menuchck1 = 0
menuchck1 = raw_input("\nYou have entered #2 (y/n)?:\n")
if menuchck1 in ["Yes","yes","y","Y"]:
x = m2()
else:
print "I'm sorry,",nam,",for the confusion, lets try again\n"
menu()
elif (menudo == 3):
print "Entered 3"
elif (menudo == 4):
print "Entered 4"
else:
print "Anything Else Entered"
def course(): #3rd thing to happen
b = {}
while True:
while True:
print "\n",name,", please enter your courses below ('e' to end):"
coursename = raw_input("Course Name:")
if (coursename == 'e'):
break
will = None
while will not in ('y','n'):
will = raw_input('Ok for this name : %s ? (y/n)' % coursename)
if will=='y':
b[coursename] = {}
print "\n",name,", current course load:\n",b
coursechck = None
while coursechck not in ('y','n'):
coursechck = raw_input("Are your courses correct (y/n)")
if coursechck =='y':
return b
else:
b = {}
print
##Menu Options##
def m1():
a = course()
return a
def m2():
print "Excellent",name,"lets see what courses your enrolled in\n"
print x
return x
###User Input Section###
name = raw_input("Enter Students Name:\n")
a = {}
menu(a)
raw_input("This is the end, my only friend the end")
In your if-elif blocks in the do==1 case, you write m1(), but for the last case, you write x=m1(). You should have the latter everywhere (by typing m1() you only run the function, but do not store the returned x anywhere).
By the way, you can avoid this if-elif confusion using if chck in ["Yes","yes","Y","y"]:

Categories