How do I avoid a variable resetting at the beginning of a function?
I'm new to python so I'm sorry if the code is very bad. But, I am making a basic slot machine game and I'm trying to implement a credit system. You start off with 50 credits and it requires 25 to spin. It works, but the problem is, my spin is in a function. And, because it is in a function it resets the credits each time it spins again. I am using an if statement to calculate the credits after a spin.
Important to note, I am using a variable named totalcredits
to calculate the actual credits. This is because if I try to use the credits
variable in my if statement I get the error: UnboundLocalError: local variable 'credits' referenced before assignment
.
This makes sense because I am in effect creating a loophole of credits, at least I think. So I've been trying to think of a workaround to stop resetting the credits but it is outside my range of knowledge. I've tried global variables and a few other things that didn't work. Here is my code:
import random
credits = 50
spindeduct = 25
win1 = 10
win2 = 40
win3 = 30
#win1, which is temporarily a "X" is worth 10 credits. So if the slots landed "X:X:X" you would get 10 credits. win2 is worth 40 credits (a "7"), and win 3 is worth 30 credits (a "Cherry"). Each spin deducts 25 from your credits
def spin():
z = random.randint(1, 3)
x = random.randint(1, 3)
y = random.randint(1, 3)
#1 = X
#2 = 7
#3 = Cherry
print("\n")
print(z)
print(x)
print(y)
#this chunky if statement calculates the amount of credits the player should have, it technically works but the credits is reset every time
if z == 1 and x == 1 and y == 1:
print("\nYou got a small win! + 10 Credits!")
totalcredits = credits - spindeduct + win1
elif z == 2 and x == 2 and y == 2:
print("\nYou won! + 40 Credits!")
totalcredits = credits - spindeduct + win2
elif z == 3 and x == 3 and y == 3:
print("\nYou won! + 30 Credits!")
totalcredits = credits - spindeduct + win3
else:
print("\nYou lost!")
totalcredits = credits - spindeduct
#printcredits is a janky workaround to prevent errors when telling the user the amount of credits they have
printcredits = totalcredits
print("You have " + str(printcredits) + " credits.")
v = input("\nWould you like to spin again? Y/N: ")
#if the player doesn't have enough credits to spin, they can no longer play
if totalcredits >= 25:
print("\nYou have enough credits to spin again!")
else:
print("You do not have enough credits to spin again!")
quit()
if v == "Y":
spin()
elif v == "y":
spin()
else:
print("Stopped")
quit()
print("Slot Simulator")
a = input("Would to like to spin some slots? (50 Credits) Y/N: ")
if a == "y":
spin()
elif a == "Y":
spin()
else:
print(Stopped)
Solution 1:
It's not a big deal to "use a global variable", especially in a small file (i.e. a Python module) -- it automatically gets namespaced to that module.
gamestate = {'credits': 0}
def increment():
gamestate['credits'] += 1
increment()
print(gamestate)
# gamestate == {'credits': 1}
This has its limits as code grows larger & more complex though, e.g. multiple modules. An alternative would be to pass state into your functions:
gamestate = {'credits': 0}
def increment(state):
state['credits'] += 1
increment(gamestate)
print(gamestate)
# {'credits': 1}
And sometimes the state changes get so complex and hard to keep track of that it helps to avoid mutations by creating new copies instead:
gamestate = {'credits': 0}
def increment(state):
return {'credits': state['credits'] + 1}
new_state = increment(gamestate)
print(gamestate)
# {'credits': 0}
print(new_state)
# {'credits': 1}
gamestate = new_state # can still mutate in the end, in a single place
print(gamestate)
# {'credits': 1}
A word about why I'm using a dict
"gamestate
":
credits = 0 # I could use a global int
# but global variables normally can't be modified inside functions:
def wont_work():
credits = credits + 1
def declare_global():
global credits # you could declare that it's global for modification
credits += 1 # same as credits = credits + 1
other_num = 10
# but many lines of code later, it can get confusing
# just looking at these two lines, can you tell which is global?
other_num += 1 # only changes inside this function
credits += 1 # affects other functions using the same variable!
# dicts are naturally modifiable (i.e. mutable) containers
gamestate = {'credits': 0} # a dict holding an int
# note that global var `gamestate` isn't changing
def increment():
other_num = 10
# It's pretty clear which is making a change "somewhere else"
other_num += 1
gamestate['credits'] += 1 # changes contents of `dict`