i have this code:
class PLAYER:
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1
#print(self.score)
i want to calling self.score from outside the PLAYER class
You need to add a constructor (the init method) as done below, and within the constructor you must define self.score, as well as all the other fields you want your PLAYER class to have. In the code below I am assuming that when you are initializing a PLAYER object that you are providing the new_block, direction, and body information, however you defined these fields, which is unclear from the question.
class PLAYER:
def __init__(self, new_block,direction,body):
self.score = 0
self.new_block = new_block
self.direction = direction
self.body = body
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1
Related
I need help to be more clear how to make my code correctly. Now it's work but I still think the code logic not correct :)
I have one class with several attributes:
class Game:
def __init__(self, player1, player2, player3, player4, score_pair1, score_pair2):
self.player1 = player1
self.player2 = player2
self.player3 = player3
self.player4 = player4
self.score_pair1 = score_pair1
self.score_pair2 = score_pair2
self.Online_Players_Dict = []
self.Temp_Players_Dict = []
self.Temp_import_players = []
I have method inside of this class for work with all attributes:
def create_temp_players(self):
for i in ('player1', 'player2', 'player3', 'player4'):
temp = self.__getattribute__(i)
if not isinstance(temp, Player):
for ii in self.Temp_import_players:
if ii['name'] == self.__getattribute__(i):
self.__setattr__(i, Player(self.__getattribute__(i), ii['score'], ii['daily_score']))
b = self.__getattribute__(i)
a = dict(name=b.name, score=b.score, daily_score=b.daily_score)
self.Online_Players_Dict.append(a)
temp = self.__getattribute__(i)
if not isinstance(temp, Player):
self.__setattr__(i, Player(self.__getattribute__(i)))
b = self.__getattribute__(i)
a = dict(name=b.name, score=b.score, daily_score=b.daily_score)
self.Online_Players_Dict.append(a)
self.Temp_Players_Dict.append(a)
And everything work correct, but I think not right to use (getattribute) and (setattr) here. But I can't find other way to correct interaction attributes in the code.
Do you have any idea how to make it better?
PS: Class Player also has attribute:
class Player:
def __init__(self, name, score=500, daily_score=0):
self.name = name
self.score = score
self.daily_score = daily_score
I changed code like this
for player, i in zip(self.players, (0, 1, 2, 3)):
if not isinstance(self.players[i], Player):
for ii in self.Temp_import_players:
if ii['name'] == self.players[i]:
self.players[i] = Player(self.players[i], ii['score'], ii['daily_score'])
a = dict(name=self.players[i].name, score=self.players[i].score, daily_score=self.players[i].daily_score)
self.Online_Players_Dict.append(a)
if not isinstance(self.players[i], Player):
self.players[i] = Player(self.players[i])
a = dict(name=self.players[i].name, score=self.players[i].score, daily_score=self.players[i].daily_score)
self.Online_Players_Dict.append(a)
self.Temp_Players_Dict.append(a)
Later will refactoring all self.playerX to self.player[X]
I recently try to code a text based game. I want to change player proficiency when player level up. How should I change my code for this?
class Player:
def __init__(self,name,_class,_race):
self.name = name
self.level = 1
self.proficiency = (int(self.level/3)+1)*2
self.inventory = 0
self.skills = returnSkills()
self.stats = returnStats()
self._class = _class
self._race = _race
self.exp = 0
def levelUp(self):
self.level+=1
newPlayer = Player("Player","Barbarian","Human")
print(newPlayer.level)
for i in range(10):
print(newPlayer.level)
print(newPlayer.proficiency)
newPlayer.levelUp()
You can recalculate the proficiency attribute directly in the levelUp() function. Once you have updated the level attribute, that new value of level will be used to calculate the new proficiency.
def levelUp(self):
self.level+=1
self.proficiency = (int(self.level/3)+1)*2
You could make proficiency a property, so it is calculated from the current level each time it is referenced.
class Player:
def __init__(self,name,_class,_race):
self.name = name
self.level = 1
self.inventory = 0
self.skills = returnSkills()
self.stats = returnStats()
self._class = _class
self._race = _race
self.exp = 0
#property
def proficiency(self):
return (int(self.level/3)+1)*2
...
or you could leave it as a plain attribute, and recalculate it inside your levelUp method.
I'm trying to create two subclasses based on the same parent class, so that they each have their own versions of the same variables defined in the parent object. However I realized that changing these variables in one of these subclasses will cause the versions in the other subclass to change as well. I know I am probably not fully understanding the idea of Inheritance. Please help!
import random
class PlayerParent():
id = 1
# Cooperate: True; Betrayal: False
opponent_moves_history = {}
self_moves_history = {}
def append_opponent_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.opponent_moves_history[round_num] = c_true
def append_self_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.self_moves_history[round_num] = c_true
score = int(0)
def score_keeper(self, round_num):
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == False):
self.score += 7
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == True):
self.score += 5
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == True):
self.score += 1
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == False):
self.score += 2
def get_score(self):
return self.score
class TitForTat(PlayerParent):
def rule(self, round_num):
if len(self.opponent_moves_history) == 0:
return True
else:
return self.opponent_moves_history[round_num - 1]
class Random(PlayerParent):
def rule(self, round_num):
random_num = random.uniform(0, 1)
if random_num >= 0.5:
return True
else:
return False
Random = Random()
Random.id = 1
TitForTat = TitForTat()
TitForTat.id = 2
def match(a, b):
game_counter = 1
# while game_counter <= 10:
#a_result = a.rule(game_counter)
# b_result = b.rule(game_counter)
# print(a_result, b_result)
# a.append_self_history(game_counter, a_result)
# b.append_opponent_history(game_counter, a_result)
# b.append_self_history(game_counter, b_result)
# a.append_opponent_history(game_counter, b_result)
# a.score_keeper(game_counter)
# b.score_keeper(game_counter)
# game_counter += 1
# print(a.get_score(), b.get_score())
a.self_moves_history[1] = True
print(a.self_moves_history, '\n', b.self_moves_history)
match(Random, TitForTat)
Resulting a.self_moves_history and b.self_moves_history is identical even though no alteration has been done to the b class variable.
I commented out chunks of the codes just to test where went wrong.
You are making opponent_moves_history a class variable, so naturally any change to it is class-wide.
In your case you should make opponent_moves_history, along with self_moves_history and id instance variables instead, so that changes made to them are specific to the instances.
class PlayerParent():
def __init__(self):
self.id = 1
self.opponent_moves_history = {}
self.self_moves_history = {}
I think this question has been asked before but I have not found an answer suited to my problem. I basically have a class for different characters, which each have a cost. When creating a character, I want to take their cost away from the players score.
Here is an example of a class:
class Assassin(pygame.sprite.Sprite):
def __init__(self, x, y, row, column):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("assassin.png")
self.x = x
self.type = "assassin"
self.y = y
self.rect = self.image.get_rect(center=(self.x, self.y))
self.damage = 60
self.health = 40
self.speed = 2
self.move = False
self.cost = 4
self.row = row
self.column = column
And here is the code where I would want to use the variable:
if assassin.collidepoint(pygame.mouse.get_pos()) and mouseDown[0]:
for block in blockGroup:
if block.team1Taken == False and block.column ==1:
team1.add(Assassin(block.team1[0], block.team1[1], block.row, block.column))
block.team1Taken = True
score -= Assassin.__init__.cost #Example of what I think you would do
break
I hope I have explained this well enough to understand what I want.
You can't call score -= Assassin.__init__.cost in python.
The init method is the constructor of the Class and should be used to do so.
The value that you want is inside the object that you created, so you could call assassin.cost directly, assuming that assassin is the object.
So, you just need to change to:
if assassin.collidepoint(pygame.mouse.get_pos()) and mouseDown[0]:
for block in blockGroup:
if block.team1Taken == False and block.column ==1:
current_assassin = Assassin(block.team1[0], block.team1[1], block.row, block.column)
team1.add(current_assassin)
block.team1Taken = True
score -= current_assassin.cost
break
You will need to keep a reference to the Assassin instance you create and then access its cost attribute:
if assassin.collidepoint(pygame.mouse.get_pos()) and mouseDown[0]:
for block in blockGroup:
if block.team1Taken == False and block.column == 1:
new_assassin = Assassin(block.team1[0], block.team1[1],
block.row, block.column)
team1.add(new_assassin)
block.team1Taken = True
score -= new_assassin.cost
break
I'm new to OOP and am practicing putting together a little bit more complex programs using various classes and implementing principles like Inheritance. I've created a Ping-Pong simulation that has a Player class which contains the probability that the player will win their serve. Then I have a PingPong class which is a subclass of the super class RacquetSports. Each instance is a single game, with the ability to change server, and record who won, and whether or not it was a shut-out. Finally, I have a SimStats class whose purpose is to record the stats across "n" number of games.
My problem is that it seems like my play_game function is not correctly firing, when I place a print statement in there it never triggers. My current result when running the whole program is that Player1 has 10 wins no shutouts, and Player2 has zero of both.
Finally, any suggestions on better OO practice would also be appreciated. Here is my player class:
from random import random
class Player(object):
def __init__(self, prob_win):
self.prob = prob_win
self.points = 0
def wins_serve(self):
return self.prob >= random()
def add_point(self):
self.points += 1
def get_score(self):
return self.points
My RacquetSports class:
from abc import ABCMeta, abstractmethod
from player import Player
class RacquetSport(object):
__metaclass__ = ABCMeta
def __init__(self, prob1, prob2):
self.player1 = Player(prob1)
self.player2 = Player(prob2)
self.server = self.player1
def play_game(self):
while not self.game_over():
self.sim_point()
#abstractmethod
def type(self):
pass
def chg_server(self):
if self.server == self.player1:
self.server = self.player2
else:
self.server = self.player1
def sim_point(self):
if self.server.wins_serve():
self.server.add_point()
else:
self.chg_server()
#abstractmethod
def game_over(self):
pass
def get_scores(self):
return self.player1.get_score(), \
self.player2.get_score()
def return_stats(self):
p1_score, p2_score = self.get_scores()
print(p1_score, p2_score)
won = 'p1'
if p2_score > p1_score:
won = 'p2'
return won, self.__shutout(p1_score, p2_score)
#staticmethod
#abstractmethod
def __shutout(score1, score2):
pass
My PingPong and SimStats classes, as well as my calling code:
from racquet import RacquetSport
class PingPong(RacquetSport):
def type(self):
return 'Ping Pong'
def game_over(self):
return self.player1.get_score == 11 or \
self.player2.get_score == 11
#staticmethod
def __shutout(score1, score2):
return abs(score1 - score2) == 11
class SimStats(object):
def __init__(self):
# First field is games won, second is shutouts.
self.gms_won_p1 = [0] * 2
self.gms_won_p2 = [0] * 2
def update(self, game):
won, shutout = game.return_stats()
if won == 'p1':
self.gms_won_p1[0] += 1
if shutout:
self.gms_won_p1[1] += 1
else:
self.gms_won_p2[0] += 1
if shutout:
self.gms_won_p2[1] += 1
def print_results(self):
tot_games = self.gms_won_p1 + self.gms_won_p2
print('Wins for Player 1 = {} Shutouts = {}\n'
'Wins for Player 2 = {} Shutouts = {}'.format(*tot_games))
if __name__ == '__main__':
stats = SimStats()
for x in range(1, 11):
game = PingPong(.5, .5)
stats.update(game)
stats.print_results()
Your first problem is that you never call play_game. My guess is that you intend it to work like this:
if __name__ == '__main__':
stats = SimStats()
for x in range(1, 11):
game = PingPong(.5, .5)
game.play_game()
stats.update(game)
stats.print_results()
Next, you have a bug that will cause the entire game to last forever. Take a look at these lines:
def game_over(self):
return self.player1.get_score == 11 or \
self.player2.get_score == 11
get_score is a function, so you need to call it:
def game_over(self):
return self.player1.get_score() == 11 or \
self.player2.get_score() == 11