How to determinate whose turn is? Card game (tkinter) - python

I'm making Palace card game with 4 players, I'm not sure how should I determinate whose on turn for throwing a card? Should I use smoething like counter or what ?

Use a simple counter modulo the number of players.
class Game(object):
def __init__(self):
self.count = 4
self.current_player = 0
def next_turn(self):
self.current_player += 1
self.current_player %= self.count

Since different cards may lead to different players having the next turn, and to the game switching between going clockwise and counterclockwise, I suggest you leave the decision to the card object.
from abc import ABCMeta, abstractmethod
class Card(object):
__metaclass__ = ABCMeta
def __init__(self, color, value):
"""
Color is either "r", "b", "g", or "y". Value is 0-9.
"""
self.color = color
self.value = value
def is_valid(self, color, value=None):
return color in self.color or value == self.value
#abstractmethod
def card_effect(self, game):
pass
This base class for all cards is the "contract" that a class has to fulfill to be considered a card. Since we're not planning on instantiating this class we make it an abstract class.
class Normal(Card):
def card_effect(self, game):
game.increment_player_index(1)
class Skip(Card):
def __init__(self, color):
super(Skip, self).__init__(color, "skip")
def card_effect(self, game):
game.increment_player_index(2)
class Turn(Card):
def __init__(self, color):
super(Turn, self).__init__(color, "turn")
def card_effect(self, game):
game.toggle_direction()
game.increment_player_index(2)
class PlusTwo(Card):
def __init__(self, color):
super(PlusTwo, self).__init__(color, "+2")
def card_effect(self, game):
game.increment_player_index(1)
game.current_player().punish(2)
game.increment_player_index(1)
For the black cards we do it like this:
class PlusFour(Card):
def __init__(self):
super(PlusFour, self).__init__("rbgy", "+4")
def card_effect(self, game):
color = game.current_player().choose_color()
game.set_color(color)
game.increment_player_index(1)
game.current_player().punish(4)
game.increment_player_index(1)

Related

Python: a set of doors that can be painted simultaneously or separately [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have to create a code that has set of doors and they can be called to be painted simulateneously or seperately. I have managed to create the code but I need advice on what exact code I need to add in order to change all of the door's colour.
Here is the code:
class Door:
colour = 'brown'
def __init__(self, number, status):
self.number = number
self.status = status
#classmethod
def knock(cls):
print("Knock!")
#classmethod
def paint(cls, colour):
cls.colour = colour
def open(self):
self.status = 'opened'
def close(self):
self.status = 'closed'
class Door2:
colour = 'yellow'
def __init__(self, number, status):
self.number = number
self.status = status
#classmethod
def knock(cls):
print("Knock!")
#classmethod
def paint(cls, colour):
cls.colour = colour
def open(self):
self.status = 'opened'
def close(self):
self.status = 'closed'
class Door3:
colour = 'green'
def __init__(self, number, status):
self.number = number
self.status = status
#classmethod
def knock(cls):
print("Knock!")
#classmethod
def paint(cls, colour):
cls.colour = colour
def open(self):
self.status = 'opened'
def close(self):
self.status = 'closed'
class Door4:
colour = 'red'
def __init__(self, number, status):
self.number = number
self.status = status
#classmethod
def knock(cls):
print("Knock!")
#classmethod
def paint(cls, colour):
cls.colour = colour
def open(self):
self.status = 'opened'
def close(self):
self.status = 'closed'
door1 = Door(1, 'closed')
door2 = Door2(2, 'closed')
door3 = Door3(1, 'closed')
door4 = Door4(2, 'closed')
print(door1.colour)
print(door2.colour)
print(door3.colour)
print(door4.colour)
The output right now:
brown
yellow
green
red
The door colour should be exactly the same kind of thing as its open/closed status: an instance attribute. That eliminates the need to repeat the same class definition four times just for the different colours:
class Door:
def __init__(self, number, status, color):
self.number = number
self.status = status
self.color = color
def knock(self):
print('Knock!')
def paint(self, color):
self.color = color
def open(self):
self.status = 'opened'
def close(self):
self.status = 'closed'
Now just make a list of doors:
doors = [Door(1, 'closed', 'brown'), Door(2, 'closed', 'yellow'), ...]
Then paint them all in a loop:
for door in doors:
print(door.color)
door.paint('red')
print(door.color)

why can't I call my method from within class in python?

I am trying to make a button class for my game, using pygame. But in the button class, I cannot call methods that are contained in the class itself.
I am new to classes so I may be missing something important, I'm sorry
I tried to add self to the isHovering() Method but it still doesn't work.
import pygame
class Button():
def __init__(self, pos, value, img, screen):
self.pos = pos
self.value = value
self.img = img
self.screen = screen
### Getters and Setters ###===============
### Get/Set Value : True/False ###
def setValue(self, value):
self.value = value
def getValue(self):
return self.value
### Get/Set Pos ###
def setPos(self, pos):
self.pos = pos
def getPos(self):
return self.pos
### Get/Set Img ###
def setImg(self, img):
self.img = img
def getImg(self):
return self.img
#==========================================
def isHovering(self):
pos = getPos()
imgRect = pygame.rect(pos[0], pos[1], 105, 105)
if imgRect.collidepoint(pygame.mouse.get_pos()):
return True
else:
return False
def update(self, screen):
if isHovering():
image = pygame.transform.scale(self.img(95, 95))
else:
image = pygame.transform.scale(self.img(105, 105))
screen.blit(image, self.pos)
I thought that when update(screen) was called in my main loop, that it would call isHovering(), and return a True or False, but instead I get this error:
NameError: name 'isHovering' is not defined
In def update(self, screen),
The if statement should be if self.isHovering().
If not, the interpreter will look for a isHovering function somewhere in the current module, like if you had defined it outside your class.
Using the self. prefix will indicate that you are indeed trying to call a method of the instance as JacoblRR already pointed out in a comment.

How would I use multiple classes together without inheritance?

I am currently learning classes and applying it as I go but I have come across an issue I am not sure how to get past:
I do not know how would I define a character having a weapon.
I have looked into the problem elsewhere but it always leads to inheritance which I want to avoid as it would not make sense. Is there any way to do this? I will be showing both the relevant code to the issue and then below, the full code for classes used.
Relevant Code
Weapon Class
class weapon:
def __init__ (self):
<constructor>
def set_attack (self, attack):
self.attack = attack
def get_attack (self):
return self.attack
Character Class
class character:
def __init__ (self):
<constructor>
def set_attack (self, amount):
self.attack = amount
def get_attack (self):
return self.attack
Full Code
Weapon Class
class weapon:
def __init__ (self, name, attack, crit_chance, crit_bonus, rarity, type_bonus):
self.name = name
self.attack = attack
self.crit_chance = crit_chance
self.crit_bonus = crit_bonus
self.rarity = rarity
self.type_bonus = type_bonus
def set_name (self, name):
self.name = name
def set_attack (self, attack):
self.attack = attack
def set_crit_chance (self, crit_chance):
self.crit_chance = crit_chance
def set_crit_bonus (self, crit_bonus):
self.crit_bonus = crit_bonus
def set_rarity (self, rarity):
self.rarity = rarity
def set_type_bonus (self, type_bonus):
self.type_bonus = type_bonus
def get_name (self):
return self.name
def get_attack (self):
return self.attack
def get_crit_chance (self):
return self.crit_chance
def get_crit_bonus (self):
return self.crit_bonus
def get_rarity (self):
return self.rarity
def get_type_bonus (self):
return self.type_bonus
Character Class
class character:
def __init__ (self, name, max_health, current_health, attack):
self.name = name
self.max_health = max_health
self.current_health = current_health
self.attack = attack
def set_name (self, name):
self.name = name
def set_max_health (self, amount):
self.max_amount = amount
def set_current_health (self, amount):
self.current_health = amount
def set_attack (self, amount):
self.attack = amount
def get_name (self):
return self.name
def get_max_health (self):
return self.max_health
def get_current_health (self):
return self.current_health
def get_attack (self):
return self.attack
Player Class Inheriting From Character Class
class player (character):
def __init__ (self, name, max_health, current_health, attack, money, level, xp):
super().__init__(name, max_health, current_health, attack)
self.money = money
self.level = level
self.xp = xp
def set_money (self, amount):
self.money = amount
def set_level (self, amount):
self.level = amount
def set_xp (self, amount):
self.xp = amount
def get_money (self):
return self.money
def get_level (self):
return self.level
def get_xp (self):
return self.xp
I am expecting the player, which inherits from character, to be able to attack using the value of a weapon object tied to that character.
Any info is appreciated.emphasized text
To begin with you can get rid of all those getters and setters and make your classes as
class Weapon:
def __init__ (self, name, attack, crit_chance, crit_bonus, rarity, type_bonus):
self.name = name
self.attack = attack
self.crit_chance = crit_chance
self.crit_bonus = crit_bonus
self.rarity = rarity
self.type_bonus = type_bonus
class Character:
def __init__ (self, name, max_health, current_health, attack):
self.name = name
self.max_health = max_health
self.current_health = current_health
self.attack = attack
Then pass a weapon object to your player class, and use that to attack the player, here weapon represents the Weapon with the player
class Player (character):
def __init__ (self, name, max_health, current_health, attack, money, level, xp, weapon):
super().__init__(name, max_health, current_health, attack)
self.money = money
self.level = level
self.xp = xp
self.weapon = weapon
#For e.g. A weapon attacks and reduces the current health of the player
def attack(self):
self.current_health -= self.weapon.attack
Or pass both a weapon and character class object to your player class, otherplayer is the Player attacked, and weapon is the Weapon with the player
class Player (character):
def __init__ (self, name, max_health, current_health, attack, money, level, xp, otherplayer, weapon):
super().__init__(name, max_health, current_health, attack)
self.money = money
self.level = level
self.xp = xp
self.otherplayer = otherplayer
self.weapon = weapon
def attack(self):
self.otherplayer.current_health -= self.weapon.attack
The Character class would have a field that's an instance of the Weapon class, like this:
class Character:
def __init__ (self, name, max_health, current_health, attack, weapon):
self.name = name
self.max_health = max_health
self.current_health = current_health
self.attack = attack
self.weapon = weapon # this line
def set_name(self, name):
self.name = name
def set_weapon(self, weapon):
self.weapon = weapon
You'd just build a Weapon object and pass it to the Character object when constructing it (or via the setter method):
weapon = Weapon()
character = Character('Char Name', 100, 100, 20, weapon)
Now, as a side note, please name your classes using uppercase for the initial letter, it's a PEP8 convention. It helps differentiating class names from instances, otherwise you wouldn't be able to call the instances weapon and character in my example above.

How update variable within another class

I have these classes :
class Game():
def __init__(self):
self.player = Player("name")
class Turn():
def __init__(self):
pass
def end(self):
#how update xp player
class Player():
def __init__(self, name):
self.name = name
self.xp = 0
And my question is how when turn is terminated, how update the player
If these classes are in the same module you can define a global variable in the module that can be used in both classes. Otherwise you need to explicitly pass the variable on the instances of both classes.
Your Game class appears to have a reference to a player in its self.player attribute. If you want to update that player's xp attribute, you can do something like this:
def end(self):
self.player.xp += 5

How do I add arguments to a subclass in Python 3

class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, color):
self.color = color
fido = Dog(legs = 4, color = "brown")
This would spute out an error message. How would I do something like that where I add parameters to the subclass that doesn't pertain to the superclass.
Try this:
class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, legs, color):
super().__init__(legs)
self.color = color
fido = Dog(legs=4, color="brown")
That's not how inheritance works. When you inherit from another class, the super-class's parameters are not automatically added to the sub-class's parameter list. You must explicitly accept the desired parameters in your sub-class's constructor and pass them on to the super class's constructor:
class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, color, legs):
super().__init__(legs)
self.color = color
fido = Dog(legs = 4, color = "brown")
Here's an example from a tutorial which explains inheritance and shows how to do this. You need to call the parent class's init function as in this similar example from this tutorial:
class Pet(object):
def __init__(self, name, species):
self.name = name
self.species = species
def getName(self):
return self.name
def getSpecies(self):
return self.species
def __str__(self):
return "%s is a %s" % (self.name, self.species)
class Dog(Pet):
def __init__(self, name, chases_cats):
Pet.__init__(self, name, "Dog")
self.chases_cats = chases_cats
def chasesCats(self):
return self.chases_cats
You still have to pass in the legs argument for Dog, and then use super:
class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, color, legs):
super().__init__(legs)
self.color = color
fido = Dog(legs = 4, color = "brown")

Categories