I have two modules in pygame. One (game_manager) in charge of creating the game and all the activities you can do there. Another (window_manager) in charge of updating the game window and drawing all the elements.
While refactoring the code to create new game modes I ran into a problem.
I want to pass a variable DECK_PLAYER from game_manager to window_manager:
# IN GAME_MANAGER.py
TABLERO = []
DECK_PLAYER = []
<some code>
def set_tablero(size):
global TABLERO
global DECK_PLAYER
TABLERO = class_board.crear_tablero(size)
DECK_PLAYER = class_cards.create_decks()
def get_deck_player():
global DECK_PLAYER
print("get_deck_player() -> ", DECK_PLAYER)
return DECK_PLAYER
if __name__ == "__main__":
board_size = 3
CLOCK.tick(30)
set_tablero(board_size)
print("get_deck_player() -> ", get_deck_player())
game_init()
both of the prints so far print the correct result, DECK_PLAYER as a list with elements. But if I call
# IN WINDOW_MANAGER.py
deck_p = game_manager.get_deck_player()
print(deck_p)
this print returns an empty list ([]), and I don't understand why. Shouldn't get_deck_player return the current value of the variable?
SOLVED IT:
as I was running game_manager as main, the call from window_manager should be:
import __main__
deck_p = __main__.get_deck_player()
to get the correct value of the variable
Related
I just want to make a separate function in the dice class which would allow me to store every 'roll' in the list_of_rolls list in the 'rolls' function. so when 'rolls' is called it would display a list of every 'roll' executed (if any).
I tried using global but it didn't work (maybe i did it wrong), i also heard using global is a bad habit so if there is another way i wouldn't mind. my indents are proper it is just not shown here.
import random
class Dice:
def roll(self):
x = random.randint(1, 6)
y = random.randint(1, 6)
roll_list = (x, y)
return roll_list
def rolls(self):
list_of_rolls = []
final = list_of_rolls.append()
return final
There are a few ways you can do this. However I am just going to suggest the most straight forward way which is to use text file to store your history of rolls within the Dice class itself.
Note that the con will be multiple instances of Dice will be accessing the same history file
However this implementation may not be optimized, as everytime you roll a dice you are opening the file and appending new rolls to it. It may not be ideal if you need millions of rolls. That say I will leave it to you to better/optimize the solution.
import random
class Dice:
list_of_rolls = []
filename = "./roll_history.txt" # a textfile to store history of rolls
def __init__(self):
try: # just to check if file exists if not create one for storing
file = open(self.filename, "r")
except FileNotFoundError:
print("File not found")
file = open(self.filename, "x") #creates file
finally:
file.close()
with open(self.filename, 'r') as opened_file_object:
self.list_of_rolls = opened_file_object.read().splitlines()
print(self.list_of_rolls)
def roll(self):
x = random.randint(1, 6)
y = random.randint(1, 6)
roll_list = (x, y)
self.list_of_rolls.append(roll_list) # updates the array with latest roll
file = open(self.filename, 'a') # 'a' for appending new rolls
# I append a newline so that the rolls are more readable in the text file
file.write('(' + str(x) + ',' + str(y) + ')\n') # appends a newline
return roll_list
def rolls(self):
return self.list_of_rolls
print(Dice().roll()) # append 2 dice rolls here
print(Dice().roll())
print(Dice().rolls()) # you should see 2 dice rolls here
try closing your python program and run it again,
Dice() # you should be able to see past rolls
Declare list_of_rolls as member variable of the class instead of defining it in the function. Create a constructor to initialize it. If you do it after class name than it becomes for the class and not at instance level.
import random
class Dice:
# list_of_rolls = [] # becomes class variable and dont use it
def __init__(self):
self.list_of_rolls = []
def roll(self):
I have a function to return random keys/values from a dict.
def heroes():
hero, attribute = random.choice(list(heroes.items()))
return(hero, attribute)
I call on this function several times throughout my app, I'm looking for a way to guarantee that each call returns a different random value than the previous one, is that possible to do easily?
Here is a function that takes a dictionary and creates a random iterator for it:
import random
def rand_items(d):
def g():
d_items = list(d.items())
random.shuffle(d_items)
for i in d_items:
yield i
return g()
#tested like:
hero = {'batman':'rope','spiderman':'web', 'superman':'cape'}
heroes = rand_items(hero)
for h in heroes:
print(h)
One run:
('spiderman', 'web')
('superman', 'cape')
('batman', 'rope')
You can get heroes one at a time. Initialize with:
heroes = rand_items(hero)
Then whenever you need a hero just use next(heroes) in place of your function call.
I'd prefer to use a decorator. It allows you to loop infinitely through heroes. For example:
import random
# In this version heroes are global
HEROES = {'a':10, 'b':20, 'c':30, 'd':40}
def except_last_one(hero_func):
# storage for the last hero
last_hero = [None]
def new_hero():
# define a new hero (but not the last hero)
last_hero[0] = hero_func([k for k in HEROES.keys() if k != last_hero[0]])[0]
return (last_hero[0], HEROES[last_hero[0]])
return new_hero
#except_last_one
def hero(heroes=HEROES.keys()):
hero = random.choice(heroes)
return (hero, HEROES[hero])
If you comment #except_last_one you obtain function equals to your function heroes(). And I'd maybe add an exception to catch a case when you have just one hero:
try:
last_hero[0] = hero_func([k for k in HEROES.keys() if k != last_hero[0]])[0]
except IndexError:
print 'Sorry, no heroes for you.'
return (None, None)
I have a global dictionary variable and I am trying to call a recursive function that going down a few levels depending on which key it is trying to find and then changes that value.
I am wondering why it isn't changing the global variable when I change a branch of it in my function.
So my recursive function looks like this:
def update_dict_with_edits(base_system_dict, changed_json_dict):
name = changed_json_dict["base_system"]["name"]
if "base_system" not in base_system_dict:
return
sub_dict = base_system_dict["base_system"]
if name == sub_dict["name"]:
print(name)
print("found it and updating")
sub_dict = changed_json_dict
# even if I print out here the_global_dict_object it is unaltered
# print(the_global_dict_object)
return
if "sub_systems" not in sub_dict:
return
for d in sub_dict["sub_systems"]:
update_dict_with_edits(d, changed_json_dict)
And I call it here:
#app.route('/test', methods=['GET', 'POST'])
def test():
if request.method == 'POST':
the_json = request.form.get('json_data', None)
the_json = json.loads(the_json)
update_dict_with_edits(the_global_dict_object, the_json)
# here when I print out the_global_dict_object it is unaltered
# print(the_global_dict_object)
# but here when I render the variable the_json just to view it,
# it is correctly edited but the change just doesn't happen in
# the function
return render_template('testing.html', the_json=the_json)
I'm using flask but I don't think it is all that relevant.
You are changing a name, not mutating a reference:
# Assign a dict to the name `sub_dict`
sub_dict = base_system_dict["base_system"]
if name == sub_dict["name"]:
# Update *that name* to point at a new dictionary
sub_dict = changed_json_dict
Instead, update the reference in base_system_dict:
if name == sub_dict["name"]:
# Update *the reference* to point at a new dictionary
base_system_dict["base_system"] = changed_json_dict
I am trying to write the program battleship. I have two gameboard matrices: one for player, one for computer. These are defined outside of main because I want them to be global variables because several functions manipulate/read them. I am using Python 2.6.1.
#create player game board (10x10 matrix filled with zeros)
playerBoard = [[0]*10 for i in range(10)]
#create computer game board (10x10 matrix filled with zeros)
computerBoard = [[0]*10 for i in range(10)]
Then I define the main function.
#define main function
def main():
global playerBoard
global computerBoard
#keepGoing is true
keepGoing = True
#while keepGoing is true
while keepGoing:
#call main menu function. Set to response.
response = mainMenu()
#if response is 1
if response == "1":
#begin new game
#call clearBoards function
clearBoards()
#call resetCounters function
resetCounters()
#call placeShips function (player)
playerBoard = placeShips(playerBoard, "player")
#call placeShips function (computer)
computerBoard = placeShips(computerBoard, "computer")
#call guessCycler function
guessCycler()
#if response is 2
if response == "2":
#keepGoing is false
keepGoing = False
Despite my declaration of global playerboard and global computerBoard within main PyScripter still says those are local variables. I don't understand this. How can I make sure they are global?
Documents I have already looked at:
Using global variables in a function other than the one that created them
Changing global variables within a function
http://www.python-course.eu/global_vs_local_variables.php
I definitely think you should reconsider if you need them to be global - You don't .-)
The cheap way, is do declare your stuff and the pass them on as parameters to the function
def MyFunc(board1):
print board1
board1 = "Very weak horse"
MyFunc(board1)
The real way to do it is to create a class and then access them using self
class MySuperClass():
def __init__(self):
self.horse = "No way up"
def myRealCoolFunc(self):
print self.horse
uhhh = MySuperClass()
uhhh.myRealCoolFunc()
I get a syntax error when i do this:
p = []
def proc(n):
for i in range(0,n):
C = i
global p.append(C)
Just change it to the following:
def proc(n):
for i in range(0,n):
C = i
p.append(C)
The global statement can only be used at the very top of a function, and it is only necessary when you are assigning to the global variable. If you are just modifying a mutable object it does not need to be used.
Here is an example of the correct usage:
n = 0
def set_n(i):
global n
n = i
Without the global statement in the above function this would just create a local variable in the function instead of modifying the value of the global variable.
The problem is you are trying to print list directly instead convert into a string before printing,and as array is a member of class Student, you need to reference it using 'self'.
The following code works:
class Student:
array = []
def addstudent(self,studentName):
print("New Student is added "+studentName)
self.array.append(studentName)
print(str(self.array))
def removeStudent(self,studentName):
print("Before Removing the Students from the list are "+ str(self.array))
self.array.remove(studentName)
print("After Removing the students from the list are "+ str(self.array))
if __name__ == '__main__':
studata = Student()
studata.addstudent("Yogeeswar")
studata.addstudent("Linga Amara")
studata.addstudent("Mahanti")
studata.removeStudent("Yogeeswar")