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
Related
In this code I tried to make that when you type "work", you get any number from 1 to 50 and it adds itself to the total balance (5 times). But when I do this, the previous amount of the variable resets to the new amount.
import random
balance = 0
def work(balance):
earned_money = random.randint(1, 50)
balance += earned_money
print(balance)
for x in range(5):
user_input = input()
if user_input == "work":
work(balance)
Even though the global keyword solves your problem, depending on who you ask, global variables are considered bad practice in Python. I try to avoid them unless there's absolutely no other way, and in this case, it's quite easy to come up with a solution that doesn't need globals:
import random
balance = 0
def work(balance):
earned_money = random.randint(1, 50)
return balance + earned_money
for x in range(5):
user_input = input()
if user_input == "work":
balance = work(balance)
print(balance)
I recommend learning more about variable scope.
Here is working code. You need to declare it as global.
import random
balance = 0
def work():
global balance
earned_money = random.randint(1, 50)
balance += earned_money
print(balance)
for x in range(5):
user_input = input()
if user_input == "work":
work()
The outer balance variable is in global scoping whereas the balance variable inside function is in local scoping.
If you want to make local scope variable global then you need to use global keyword inside your function.
import random
balance = 0
def work():
global balance # This makes balance variable global.
earned_money = random.randint(1, 50)
balance += earned_money
print(balance)
for x in range(5):
user_input = input()
if user_input == "work":
work()
class Hero:
def __init__(self,name,hitpoint,damage,sp):
self.name=name
self.hitpoint=hitpoint
self.damage=damage
self.sp=sp
class Enemy:
def __init__(self,name,hitpoint,damage):
self.name=name
self.hitpoint=hitpoint
self.damage=damage
hero=Hero("mostafa", 100, 20 , 40)
enemy=Enemy("vice-T", 210, 30 )
def hero_attack():
enemy.hitpoint=enemy.hitpoint-hero.damage
if enemy.hitpoint>=0:
print (enemy.name," is still alive", enemy.name, "'s life is now ", enemy.hitpoint)
else:
print (enemy.name," is dead congrats you win ")
def enemy_attack():
hero.hitpoint=hero.hitpoint-enemy.damage
if hero.hitpoint>=0:
print (hero.name," is still alive", hero.name, "'s life is now ", hero.hitpoint)
else:
print (hero.name," is dead Enemy Win ")
enemy_attack()
hero_attack()
here i want to random attack between enemy_attack() and hero_attack() function. suppose i will declare a variable called attack which gives me either enemy_attack() or hero_attack(). plz help
Use random module of python that choose a random value. Just Try below code:
import random
enemy_attack() if random.randint(0,1) == 0 else hero_attack()
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
from random import randint
from time import sleep
pminatk = 0
pmaxatk = 4
playerhp = 15
def atk(minatk, maxatk):
return randint(minatk, maxatk)
def playerAtk(monsterhp):
dmg = atk(pminatk, pmaxatk)
monsterhp -= dmg
print ("Du gjorde %i skade. Monsteret har nå %i liv igjen" % (dmg, monsterhp))
sleep(1)
return monsterhp
def monsterAtk(mminatk, mmaxatk):
global playerhp
dmg = atk(mminatk, mmaxatk)
playerhp -= dmg
print ("Monsteret gjorde %i skade. Du har nå %i liv igjen" % (dmg, playerhp))
sleep(1)
def fight(monsterhp, mminatk, mmaxatk):
global playerhp
while monsterhp > 0 and playerhp > 0:
playerAtk(monsterhp)
if monsterhp > 0:
monsterAtk(mminatk, mmaxatk)
if playerhp > 0:
print ("Gratulerer! Du beseiret monsteret!")
else:
print ("Du døde!")
fight(5, 1, 2)
fight(6, 0, 2)
This is supposed to be a simple battle system in a text based adventure. Now my problem is that monsterhp always goes back to its original valye after playerAtk is executed. If I choose to have monsterhp as a global variable it will remain 0 after fight() is finished, leaving the hp of all OTHER monster equal to zero as well. Now i could have more than one variable to assign different hp-values to different monster, but is there any way I can do this using parameters to the fight() function?
Your immediate problem is in your while loop when you call playerAtk(), you return monsterhp from it, but do not actually use it in that loop and that is why you see monster's health points to go back up to the original value. Line 28 needs to read:
monsterhp = playerAtk(monsterhp)
instead of:
playerAtk(monsterhp)
As it was suggested in a comment though, It's worth looking into defining your custom classes. I've thrown together following example based on your code to whet your appetite:
from random import randint
from time import sleep
PLAYERNAME = "Player1"
PLAYERHP = 15
PMINATK = 0
PMAXATK = 4
class CharacterDied(Exception):
def __init__(self, msg):
self.msg = msg
class Character:
def __init__(self, name, initial_hp, minatk, maxatk):
self.name = name
self.hp = initial_hp
self.minatk = minatk
self.maxatk = maxatk
def take_damage(self, damage_hp):
self.hp -= damage_hp
msg = "{} takes {:d}HP damage and has {:d} left."
print(msg.format(self.name, damage_hp, self.hp))
if self.hp < 0:
msg = "{} died."
raise CharacterDied(msg.format(self.name))
def attack(self, other):
dmg = randint(self.minatk, self.maxatk)
sleep(1)
other.take_damage(dmg)
def fight(char1, char2):
try:
while True:
char1.attack(char2)
char2.attack(char1)
except CharacterDied as death_exception:
print(death_exception.msg)
if __name__ == "__main__":
player = Character(PLAYERNAME, PLAYERHP, PMINATK, PMAXATK)
fight(player, Character("Monster1", 5, 1, 2))
if player.hp > 0:
fight(player, Character("Monster2", 6, 0, 2))
There are many ways to do this. For simplicity, I've written just one generic Character class we can use for player and monsters, but even if we started customizing them with subclasses, for instance the fight is now a bit more generic and we can also have a monster attack the player as it just became function of two fighting characters.
To your original question though the benefit sought after here is that attributes are kept and persistent with their instance objects which is generally much easier to follow than to try to deal with and track global variables.
I am new to python and trying to make a simple game using simplegui in python. In this game, a number is guessed between either 0-100 or 0-1000 (depending upon user's choice) and then the user guess that number. The user gets maximum 7 attempts. The new game starts after the user lose or guess the correct number. The game should run continously.
Problem: When the first game finishes...second game normally and then third game starts which prints the message You lose!.
My code is following:
import simplegui
import random
import math
# initialize global variables used in your code
numOfTurns = 0
numberThought = 2000
maxAllowedTurns = 0
flag = 0 # 1: range is (0, 100] and 2: range is (0,1000]
# define event handlers for control panel
def range100():
# button that changes range to range [0,100) and restarts
global flag
flag = 1
new_game()
def range1000():
# button that changes range to range [0,1000) and restarts
global flag
flag = 2
new_game()
def input_guess(string_guess):
guess = int(string_guess)
global numberThought , numOfTurns, maxAllowedTurns, flag
numOfTurns = numOfTurns + 1
if ( numberThought > 1000 ):
print "Please Select the Range First"
print
return
# main game logic goes here
guessLeft = maxAllowedTurns - numOfTurns
if(numberThought < guess):
print "Your guess was = ", guess
print "Number of Guesses remaining = ", (maxAllowedTurns - numOfTurns)
print "Lower !"
print
if (guessLeft == 0):
print "You Lose!!"
print "The Number was = ", numberThought
print "<<<<<<<<<<<<<<<<<<<<<<<<",">>>>>>>>>>>>>>>>>>>>"
print
print
new_game()
elif (guess < numberThought):
print "Your guess was = ", guess
print "Number of Guesses remaining = ", (maxAllowedTurns - numOfTurns)
print "Higher !"
print
if (guessLeft == 0):
print "You Lose!!"
print "The Number was = ", numberThought
print "<<<<<<<<<<<<<<<<<<<<<<<<",">>>>>>>>>>>>>>>>>>>>"
print
print
new_game()
elif (guess == numberThought):
print "Your guess was = ", guess
print "Correct !"
print
new_game()
if (guessLeft == 0):
print "You Lose!!"
print "The Number was = ", numberThought
print "<<<<<<<<<<<<<<<<<<<<<<<<",">>>>>>>>>>>>>>>>>>>>"
print
print
new_game()
# create frame
frame = simplegui.create_frame("Guess The Number", 300, 300)
# register event handlers for control elements
frame.add_button("range (0,100]", range100)
frame.add_button("range (0,1000]", range1000)
frame.add_input("Enter",input_guess, 100)
# call new_game and start frame
# helper function to start and restart the game
def new_game():
global numberThought , numOfTurns , flag, maxAllowedTurns
numOfTurns = 0
print "<<<<<<<<<<<<<<<<<<<<<<<<",">>>>>>>>>>>>>>>>>>>>"
print "NEW GAME !!!!"
# Defining the number of turns allowed based upon the range type
if(flag == 1):
maxAllowedTurns = 7
numberThought = random.randrange(0,100)
print "Range is from 0 - 100"
print "Max allowed turns = " , maxAllowedTurns
print "Number of Guesses remaining = " , maxAllowedTurns-numOfTurns
print
elif(flag == 2):
maxAllowedTurns = 10
numberThought = random.randrange(0,1000)
print "Range is from 0 - 1000"
print "Max allowed turns = " , maxAllowedTurns
print
frame.start()
(Copy-pasted comment)
I only looked at the code, I didn't test it (didn't want to install simplegui), but I think it prints you lose when you guess the correct number using exactly the allowed turns. Try removing the if block "if (guessLeft == 0): ... " in the last elif block in input_guess.