Home > Blockchain >  List.pop() doesnt work as expected as a function argument
List.pop() doesnt work as expected as a function argument

Time:12-29

Really weird I make a card game and made this function:

def draw_card_from_top(destination, departure): 
    if len(departure.cards) > 0:   
        destination.add_card(departure.cards.pop(0))

it works as expected if I put in a destination deck and a departure deck. The destination deck gets the card from the top of the departure deck.

But I also made this function which should deal 8 cards to every player:

def deal_new_game(players, departure):
    for i in range(len(players)):
        for j in range(CARDS_PER_ROUND):
            draw_card_from_top(players[i].deck, departure) 

Now I have the following problem; each player should add 8 cards from the departure deck to his own, the destination deck. But for some reason each of the players now has a complete copy of the deck, so 1 instead of 8 all 32 cards and 2. Everyone has the same order

------ Complete source -------

main.py:

import _card, _deck, _player, game

is_invalid = True
while is_invalid:
    try:
        player_count = int(input('How many players? (3 or 4): '))
        if player_count == 3 or player_count == 4:
            is_invalid = False
    except ValueError:
        pass

player = []
for i in range(player_count):
    player.append(_player.Player())

game_deck = _deck.Deck(game.create_new_deck())
game_deck.shuffle_deck()

_player.py:

import _deck

class Player():
    def __init__(self):
        self.deck = _deck.Deck()
        self.score = 0

_deck.py:

from random import shuffle

class Deck():
    # Ein Deck ist eine Ansammlung von einer oder mehreren Karten ('Card()''s)
    def __init__(self, _cards=[]):
        self.cards = _cards
    
    def print_deck(self):
        for i in range(0, len(self.cards)):
            print(self.cards[i].term)

    def shuffle_deck(self):
        shuffle(self.cards)
    
    def deck_size(self):
        return len(self.cards)

    def add_card(self, card):
        self.cards.append(card)

_card.py:

class Card():
    # Eine Karte besteht aus folgenden 3 Attributen:
        # 1. color, die Color gibt an, um welche Farbe es sich handelt, 'Kreuz', 'Pik', 'Herz', 'Raute'
        # 2. value, die Value gibt an, welchen Wert eine Karte hat. ZB hat die Herz 10 die value 10 und ein Kreuz Bube die value 11
        # 3. term, der Term gibt an wie die Karte im Spiel bereichnet wird, so ist die Herz 7 die 'H7' oder die Pik Dame 'PQ'
    def __init__(self, _color, _value, _term):
        self.color = _color
        self.value = _value
        self.term = _term

game.py:

import _card

CARDS_PER_ROUND = 8

def create_new_deck():
    cards = []
    for i in range(4):
        if i == 0:
            color = 'Kreuz'
            term_color = 'K'
        if i == 1:
            color = 'Pik'
            term_color = 'P'
        if i == 2:
            color = 'Herz'
            term_color = 'H'
        if i == 3:
            color = 'Raute'
            term_color = 'R'
        
        for value in range(7, 15):
            if value <= 10:
                term_value = str(value)
            if value == 11:
                term_value = 'B'
            if value == 12:
                term_value = 'D'
            if value == 13:
                term_value = 'K'
            if value == 14:
                term_value = "A"

            cards.append(_card.Card(color, value, term_color   term_value))    
    return cards

def draw_card_from_top(destination, departure): 
    if len(departure.cards) > 0:   
        destination.add_card(departure.cards.pop(0))

def draw_card_by_index(destination, departure, index): 
    if len(departure.cards) >= index:   
        destination.add_card(departure.cards.pop(index))

def deal_new_game(players, departure):
    for i in range(len(players)):
        for j in range(CARDS_PER_ROUND):
            draw_card_from_top(players[i].deck, departure) 
            
            # TODO irgendwas buggt hier voll rum. Spieler-Decks bestehen nach Aufruf der Funktion komplett aus vollständigen Decks.

CodePudding user response:

The problem caused by the mutable default parameter in your _deck.py module.

When you create a new Deck(), its self.card attribute is the same for all instances (because of card=[] in the init definition).

If you change it to this, it should work properly:

def __init__(self, _cards=None):
    self.cards = [] if _cards is None else _cards

The idea is to avoid using a mutable default for a parameter. Depending on what you want the Deck to do when it is created with a card list (make a copy or use the reference), you may need to implement this differently.

The first example uses a reference to the _cards list. To use a copy, you could keep the mutable default since you're not going to save it in the object instance:

def __init__(self, _cards=[]):
    self.cards = _cards.copy()
  • Related