Converting globals to class - python

I have been using global variables for a little text game in python and have come across a lot of articles saying that global variables are a no no in python. I have been trying to understand how to get what I have below (just a health variable and being able to change it and print it) working using classes but I am confused how I can converted something like this in a class. Any help, example, point in the right direction would be great.
Here is an example of me using variables.
import sys
import time
health = 100
b = 1
def intro():
print("You will die after two moves")
def exittro():
time.sleep(1)
print("Thanks for playing!")
sys.exit()
def move():
global health
global b
health -= 50
if health <= 51 and b >0:
print("almost dead")
b = b - 1
def death():
if health == 0 or health <= 0:
print("...")
time.sleep(1)
print("You died\n")
time.sleep(2)
print("Dont worry, this game sucks anyway\n")
exittro()
intro()
a = 1
while a == 1:
input("Press Enter to move")
move()
death()
Thank you
Edit: this is the kind of thing I have been trying to do...
class Test:
def __init__(self):
number = 100
def __call__(self):
return number
def reduceNum(self):
number -=10
def printNum(self):
print(number)
a = 1
while a == 1:
input("Enter")
Test.self.reduceNum()
Test.self.printNum()

I would avoid classes for this, as classes are generally slower. You could make the function return the new value for the health variable.
I would also suggest making a main controller function to take the return value and apply it to other functions. This prevents global variables outside of a function's scope.
import time
def intro():
print("You will die after two moves")
def outro():
time.sleep(1)
print("Thanks for playing!")
# sys.exit() # You can avoid this now by just stopping the program normally
def move(health):
health -= 50
if health <= 51:
print("almost dead")
return health # Return the new health to be stored in a variable
def death(health):
if health <= 0:
print("...")
time.sleep(1)
print("You died\n")
time.sleep(2)
print("Dont worry, this game sucks anyway\n")
return True # Died
return False # Didn't die
def main():
health = 100 # You start with 100 health
intro()
while not death(health):
# While the death function doesn't return `True` (i.e., you didn't die) ...
input("Press enter to move")
health = move(health) # `health` is the new health value
outro()
If you want to use classes, you need to actually instantiate the class (Make a new object from it) by doing instance = Test(). You also need to store variables as attributes of self (so self.number = number) as any local variables are different from each other.
class Test:
def __init__(self):
self.number = 100
def __call__(self):
return self.number
def reduceNum(self):
self.number -= 10
def printNum(self):
print(self.number)
a = 1
game = Test()
while a == 1:
input("Enter")
game.reduceNum()
game.printNum()
# Or:
print(game())
# As you've changed `__call__` to return the number as well.

Related

how to avoid infinite loop when using a constructor function to create an object

# Import Modules
from Dice import dice
d10 = dice(10,1)
d4 = dice(4,1)
# Assign Classes
class Player_Character:
def __init__(self, hp, maxhp, ac, THAC0, Surprise_Adjustment, Initiative_Adjustment):
self.hp = int(hp)
self.maxhp = int(maxhp)
self.ac = int(ac)
self.THAC0 = int(THAC0)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
def attack(self, goblin):
Player_Character_Damage = d10.die_roll()
goblin.hp -= Player_Character_Damage
if (goblin.hp <= 0):
print("congratulations you killed the goblin")
def flee(self):
print("you run away ")
quit()
def heal(self, Player_Character):
Player_Character.hp += d10.die_roll()
if Player_Character.hp >= Player_Character.maxhp:
Player_Character.hp = Player_Character.maxhp
class goblin:
def __init__(self, hp, maxhp, ac, THAC0, Surprise_Adjustment, Initiative_Adjustment):
self.hp = int(hp)
self.maxhp = int(maxhp)
self.ac = int(ac)
self.THAC0 = int(THAC0)
self.Surprise_Adjustment = int(Surprise_Adjustment)
self.Initiative_Adjustment = int(Initiative_Adjustment)
def attack(self, Player_Character):
goblin_damage = d4.die_roll()
Player_Character.hp -= goblin_damage
if (Player_Character.hp <= 0):
print("oh dear you have died")
del Player_Character
MrHezy = Player_Character(10, 20, 10, 15, 0, 2)
def spawn_goblin(goblin):
G1 = goblin(5, 10, 8, 18, 0, 0)
return G1
goblin1 = spawn_goblin(goblin)
def battle(goblin1):
# user input
player_initiative_adjustment = MrHezy.Initiative_Adjustment
monster_initiative_adjustment = goblin1.Initiative_Adjustment
#define while loop for the battle
battle_not_over = 'yes'
while battle_not_over == 'yes':
#use random.randint(a,b) to generate player and monster base initiative
player_base_initiative = d10.die_roll()
monster_base_initiative = d10.die_roll()
#subtract the adjustment to get player and monster initiative
player_initiative = player_base_initiative - player_initiative_adjustment
monster_initiative = monster_base_initiative - monster_initiative_adjustment
#compare the initiatives and display the results
if (player_initiative < monster_initiative):
attack_flee_heal = input("congratulations you go first. Would you like to attack, flee, or heal?")
while attack_flee_heal != 'attack' or 'flee' or 'heal':
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy)
break
elif attack_flee_heal == 'flee':
MrHezy.flee()
break
else:
print("uhoh, the monsters go first, they attack!")
goblin1.attack(MrHezy)
attack_flee_heal = input("Would you like to attack, flee, or heal? ")
while attack_flee_heal != 'attack' or 'flee' or 'heal':
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
print("the goblin attacks")
goblin1.attack(MrHezy)
break
elif attack_flee_heal == 'flee':
MrHezy.flee()
break
#main game loop
while True:
spawn_goblin(goblin)
battle(goblin1)
This is a code for a battle simulator that ive been working on. it starts by importing a module that i made which consists of a class called 'dice' which I use for randomly generating numbers. Defining classes is next, with attributes including hp, maxhp, armor class, 'to hit armor class 0', surprise adjustment, and initiative adjustment, and methods including attack which allows you to attack the monsters, flee which exits the battle, and heal which gives your character more hit points. The program moves on to define the spawn_goblin() function which spawns a goblin (this works just fine for the first iteration of the loop). Then it moves on to the battle part which is pretty simple; all it does is check who goes first and then allows you to attack, or flee, or heal yourself. Please ignore the "heal" and "flee" methods, these are working just fine. The problem occurs when I attack the goblin. Instead of killing the goblin and spawning another it creates an infinite loop saying "congratulations you killed the goblin"
while (goblin.hp <= 0):
print("congratulations you killed the goblin")
I think this part of your code is wrong. The while should be if, since you only want to check if the goblin has died, and run some code once. Once the goblin's HP becomes lesser than or equal to 0, the print statement will loop forever since the expression goblin.hp <= 0 will always return True.
EDIT: Now where I think your code is wrong is here:
while attack_flee_heal != 'attack' or 'flee' or 'heal':
if attack_flee_heal == 'attack':
MrHezy.attack(goblin1)
elif attack_flee_heal == 'heal':
MrHezy.heal(MrHezy)
...
I think you have missed the break in the first if (if attack_flee_heal == 'attack'
Also, it would be more appropriate to use an if here rather than a while, since, as I mentioned above, you only want to check once.

How to edit variable in function, than pass it to another function?

I'am new to python, and i decided to make a simple quiz game.
The idea is:
Your base health is 100, every wrong answered question is -25 hp.
If hp equals 0 you lose.
And here lies the problem. I don't know how to pass the variable from function to a second function (in this case, every question in quiz is a different function)
The problem is that in every function, hp resets to its basic number (100).
Sorry if i poorly described my problem but im not very fluent in english.
Already tried to make a function that contains ,,hp = 100", making it global etc. Also tried various stuff with ,,return".
hp = 100
def test1():
test = input("yes no")
if test == "yes":
print("this is hp test")
print(hp - 25) # should be 100 - 25 = 75
test2()
if test == "no":
print("ok")
input("dead end")
def test2():
test2 = input("yes no")
if test2 == "yes":
print("this is second hp test")
print(hp - 25) # should be 75 - 25 = 50
if test2 == "no":
print("ok")
input("another dead end")
input("start")
test1()
I am not really sure what your trying to achieve here.
But i would suggest using a class that will allow you to have better control over your variables.
class Game:
def __init__(self):
self.hp = 100
def takeInput(self):
self.current = input()
self.computeScore()
def computeScore(self):
if self.input ==="Something":
self.hp -= 25
if self.checkValidScore():
self.takeInput()
else:
print "game over"
def checkValidScore(self):
return self.hp < 0
The statement print(hp - 25) simply prints the value of hp minus 25. It does not actually modify the value of hp. You probably want:
hp = hp - 25
print(hp)
Use global inside each function declartion
hp = 100
def test1():
global hp # do this in each of your functions
test = input("yes no")
if test == "yes":
print("this is hp test")
hp -= 25 # which is equivalent to hp = hp - 25
print(hp) # here just print the updated variable
test2()
Keep in mind that using global variables is not considered a good practice because it might make your code very hard to debug. You can read more about it here.
Not sure what you want to achieve. If it keeps that simple you could also go in the following direction...
def test1(hp):
test = input("yes no")
stop_msg = None
if test == "yes":
print("not ok")
hp -= 25
elif test == "no":
print("ok")
stop_msg = "dead end"
else:
raise Exception("Expected input to be 'yes' or 'no'.")
return hp, stop_msg
def test2(hp):
test = input("yes no")
stop_msg = None
if test == "yes":
print("'yes' sucks")
hp -= 25
elif test == "no":
print("ok")
stop_msg = "another dead end"
else:
raise Exception("Expected input to be 'yes' or 'no'.")
return hp, stop_msg
def run_game(hp=100):
print("start...")
tests = [test1, test2]
for test in tests:
hp, stop_msg = test(hp)
print("hp: {}".format(hp))
if stop_msg:
print(stop_msg)
return
if __name__ == "__main__":
run_game()
Remarks:
If you want to implement a more complex decision tree, you could use any simple tree representation.
If you have always the same structure within testX functions, introduce one function with parameters for questions, answer, etc.

How to take away health points when using a class?

I'm working on a game in python and I can't figure out how to take away health once attack function has taken place. I can run the program and the attack function works fine, it shows a random integer between 1 and 50 but doesn't actually take away health from castlehealth = 100
Underneath print("You attacked for " + str(self.attack)) I left the next line blank because I don't know what to type in, I tried a lot of different things and just can't get the attack to take away from castlehealth.
Here is my code:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
You want the following:
self.castlehealth -= attack
Try something like self.castlehealth -= attack. I also fixed some potential indentation issues for you.
Your full code sample could look this this:
import os
import time
from random import randint
class GameActions:
def __init__(self):
castlehealth = 100
self.castlehealth = castlehealth
def health(self):
print("Castle health is: " + str(self.castlehealth))
print()
def attack(self):
attack = randint(0, 50)
self.attack = attack
print("You attacked for " + str(self.attack))
self.castlehealth -= attack
def game():
while True:
game_actions = GameActions()
print("What do you want to do?")
print()
print("attack, view hp")
ans = input()
if ans == "hp":
game_actions.health()
if ans == "attack":
game_actions.attack()
Explanation: self.castlehealth is an instance variable of your GameActions class. The function GameActions.attack() creates a new attack variable as a random integer and then subtracts that value from the instance variable self.castlehealth of the GameActions class. Now self.castlehealth will be the updated value. Consider also tracking the various attacks and resulting healths in a data structure, since every time you have a new attack self.castlehealth and self.attack will change values and you will lose the ability to access the previous values.

how to make a pokemon battle with def

so this is my code( or just a long sample)
from easygui import*
health = 100
ai_h = 100
moves = ['scratch']
class player:
def starter():
starter = buttonbox('what do you want to see?',
choices = ['fjade', 'soarer','mudwet'])
msgbox = ('that is a great choice')
def p_attack():
global ai_h
battle = choicebox('battle, chose your move!',
choices = moves)
if battle == 'scratch':
msgbox('you used scratch')
ai_h = ai_h - 10
msgbox(ai_h)
if health < 0:
msgbox('you failed')
quit()
sys.exit()
def __init__(self):
self.health = health
class ai:
def __init__(self):
self.healtha = ai_h
def attack():
global health
msgbox('the oppenet hit you!')
msgbox('you lost 10 health')
health = health - 10
msgbox(health)
if ai_h < 0:
msgbox('you defeated ai')
class battle:
def __init__():
pass
def war(opponet, opponet_health, your_health):
msgbox('oppent want to battle!')`
that is my code and as you can see the def war(i wanted to use battle)
is not yet finished. I tried many examples but sometimes the ai's health goes to negative something and the program is still going. can anyone help?

While loop ignores print?

Ok so im working on a basic dice game, But when it gets to the while loop it doesnt print the message inside, The message is just a placeholder.
dicenumber = None
numberchoice = None
ready = None
test = "Lol"
class playerClass():
points = 0
class enemyClass():
point = 0
def rolldice():
dicenumber = dicenumber.randint(1,9)
def start():
print("Hello welcome to the dice game.")
print("The goal of the game is to guess what number the dice will land on.")
print("The option are 1 to 6 and the game is won by getting 3 points.")
print()
print("Are you ready to play?")
print("1 - Yes")
print("2 - No")
ready = int(input())
start()
while ready == 1:
print("hello")
Use global inside your start function. Also, as you were trying to put while ready==1, it will be in infinite loop!
dicenumber = None
numberchoice = None
ready = None
test = "Lol"
class playerClass():
points = 0
class enemyClass():
point = 0
def rolldice():
dicenumber = dicenumber.randint(1,9)
def start():
global ready
print("Hello welcome to the dice game.")
print("The goal of the game is to guess what number the dice will land on.")
print("The option are 1 to 6 and the game is won by getting 3 points.")
print()
print("Are you ready to play?")
print("1 - Yes")
print("2 - No")
ready = int(input())
start()
while ready == 1:
print("hello")
When you access ready inside the start() method, you are accessing it as a local variable. Python assumes that all variables you use are local, not global. Put global ready in the start() method before you set the ready variable. This will tell python to access ready as a global variable.
There is a scoping issue. ready variable defined in a global scope is not updated inside the start() function.
Simple demo of what is happening:
>>> ready = None
>>> def start():
... ready = 1
...
>>> start()
>>> print ready
None
Better return ready variable from the start():
def start():
print("Hello welcome to the dice game.")
print("The goal of the game is to guess what number the dice will land on.")
print("The option are 1 to 6 and the game is won by getting 3 points.")
print()
print("Are you ready to play?")
print("1 - Yes")
print("2 - No")
return int(input())
ready = start()
You can also make it global as #S.M. Al Mamun suggested, but i would not recommend it. Global variables are needed for sharing data, state between functions. In this case there is no need for it - your start() function defines a value for the ready variable. It is a single one place where ready is defined - no need to make it global. start() is an entry point and it would be a good idea to return a "state" (ready variable) from it.
See also:
Short Description of the Scoping Rules?
ready is defined in the global scope, but you are setting it in the local scope of the start function. Also, your rolldice function returns a number from 1 to 9 instead of 1 to 6.
from random import randint
class Player:
def __init__(self, name):
self.name = name
self.points = 0
self.won = False
def add_point(self):
self.points += 1
self.won = True
print('''
Hello welcome to the dice game.
The goal of the game is to guess what number the dice will land on.
The options are 1 to 6 and the game is won by getting 3 points.
Are you ready to play?
0 - No
1 - Yes'''
ready = int(input())
if ready:
players = []
number_of_players = int(input('How many players? '))
for i in range(number_of_players):
name = input('What is the name of player {}?'.format(i+1))
players.append(Player(name))
winners = []
while ready:
random_number = randint(1, 6)
for player in players:
guess = int(input('What is your guess, {}?'.format(player.name)))
if guess == random_number:
player.add_point()
if player.won:
winners.append(player.name)
if winners:
print('Winners: {}'.format(', '.join(winners)))
break
You are accessing a variable(ready) which was defined originally as a global variable, then you are accessing it in your start function without mentioning in your code('start' function) that is a global variable and finally in your while loop you are again trying to access a variable which you assume it has a value assigned to it.
The other thing is you while loop. when you set ready==1, you need to some where break from your loop if you don't want it to be infinite loop.

Categories

Resources