I'm building a deck of cards that has shuffling function. I'm using random.shuffle, but it is not shuffling at all. When I run the following codes, the whole deck is printed out in good order. Please have a look, thanks!
import random
class Card(object):
def __init__(self, suit, value):
self.suit = suit
self.value = value
def show(self):
print("{} of {}".format(self.value, self.suit))
return self.value
class Deck(object):
def __init__(self):
self.cards = []
self.build()
def build(self):
for s in ["Spades", "Clubs", "Diamonds", "Hearts"]:
for v in range(1, 14):
self.cards.append(Card(s, v))
print("{} of {}". format(v, s))
def show(self):
for cards in self.cards:
print(cards.show())
def shuffle(self):
random.shuffle(self.cards)
return self.cards
def draw_card(self):
return self.cards.pop()
deck = Deck()
deck.shuffle()
I just tried your code, the console output messages you are seeing in good order are created from the self.build() function, if you call deck.show() at the end, you will see the shuffled messages.
deck = Deck()
deck.shuffle()
deck.show()
Related
This question already has answers here:
How to print instances of a class using print()?
(12 answers)
Closed 2 years ago.
Python prints memory location instead of list.
My code:
import random
class Card:
def __init__(self, value, suit):
self.value = value
self.suit = suit
def show_card(self):
print(self.value, self.suit)
def get_value(self):
if self.value > 10:
return 10
return int(self.value)
class Deck:
def __init__(self):
self.cards = []
self.build()
def build(self):
for suit in ["♣", "♦", "♥", "♠"]:
for value in range(2, 15):
self.cards.append(Card(suit, value))
return self.cards
def shuffle_deck(self):
random.shuffle(self.cards)
return self.cards
Deck().build()
deck = Deck().shuffle_deck()
print(deck)
The problem is when I append "Card" object to "cards" list.
How could I print "cards" list elements instead of memory locations?
It could be achieved through __repr__ magic method. Add this method:
def __repr__(self):
return f'{self.value} {self.suit}'
into your Card class.
Just add a repr function to the card class
class Card:
# your implementation
def __repr__(self):
return f'({self.value},{self.suit})'
Ok guys I'm doing a Deck class and I want to make my deck so that when card are dealt, I can restore the deck when shuffling. I thought that it could work recalling the class with the same class name but python raise "TypeError: restore_deck() missing 1 required positional argument: 'self'"
class Card:
def __init__(self, value, suit):
self.value = value
self.suit = suit
class Deck:
def __init__(self):
suits = ["Hearts", "Diamonds", "Clubs", "Spades"]
values = ['A','2','3','4','5','6','7','8','9','10','J','Q','K']
self.cards = [Card(value, suit) for suit in suits for value in values]
def shuffle(self):
def restore_deck(self):
self = Deck()
if self.count() < 52: # |here is the problem!
restore_deck(self)# |
shuffle(self.cards)
return self
I take it that you mean you remove cards from the list of cards in Deck and what you would like to do is shuffle all 52 cards, to do this what we can do is import the module random and when we would like to shuffle the cards we can just recreate the list of cards then shuffle the full list. I added repr method just so you could see output clearly. If you would not like to regenerate the whole list you could instead store the cards "removed" and add them back into the list before shuffling.
import random
class Card:
def __init__(self, value, suit):
self.value = value
self.suit = suit
def __repr__(self):
return str((self.suit, self.value))
class Deck:
def __init__(self):
self.suits = ["Hearts", "Diamonds", "Clubs", "Spades"]
self.values = ['A', '2', '3', '4', '5', '6',' 7', '8', '9', '10', 'J', 'Q', 'K']
self.cards = [Card(value, suit) for suit in self.suits for value in self.values]
def shuffle(self):
self.cards = [Card(value, suit) for suit in self.suits for value in self.values]
random.shuffle(self.cards)
d = Deck()
print(d.cards)
d.shuffle()
print(d.cards)
I'm self-learning Python 2 and I'm currently working on a OOP Blackjack game. I want to properly reference a variable in a class for use within another class. So far I have assigned d = Deck(), p = PlayerHand(), and dealt a card using d.deal(), but I can't seem to execute p.hit(). The exception is telling me that the variable single_card is not defined.
import random
rank = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace']
suit = ['Diamonds', 'Clubs', 'Hearts', 'Spade']
card_val = {'2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':1}
class Card(object):
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __str__(self):
return str(self.rank) + ' of ' + str(self.suit)
def grab_suit(self):
return self.suit
def grab_rank(self):
return self.rank
def draw(self):
print(self.suit + self.rank)
class Deck(object):
def __init__(self):
self.cards = []
for i in rank:
for j in suit:
self.cards.append(Card(i,j))
def __str__(self):
return str([str(card) for card in self.cards])
def shuffle(self):
random.shuffle(self.cards)
def deal(self):
single_card = self.cards.pop()
return single_card
class PlayerHand(object):
def __init__(self):
self.value = []
def hit(self):
self.hit = self.value.append(single_card)
With your current design, you could grab the single card from an instance of Deck and pass in that card to the player's hand hit method.
deck = Deck()
card = deck.deal()
hand = PlayerHand()
hand.hit(card)
And change PlayerHand.hit to this:
class PlayerHand(object):
...
def hit(self, card):
self.value.append(card)
In the case of Blackjack, you could define a Dealer class that holds the Deck and a list of players
Then, in the Deck class, or preferably in the Dealer class, you can deal into a PlayersHand
def deal(self, hand):
single_card = self.cards.pop() # or self.deck.deal()
if hand: # pass None to this function to draw without dealing
hand.value.append(single_card)
return single_card
d = Deck()
p = PlayerHand()
d.deal(hand)
Alternatively, give the deck to the Player class functions to have it draw
I would like to repeat a class method several times (26 to be exact) so that I can split a deck of cards to two separate decks. I tried [:26] and [26:] (obviously for lists only) in addition to d1=Deck() then deck1 = d1.deal()*26 and they both did not work. I just learned how to create Classes.
Desired output is deck1=["""26 random cards"""] and deck2=["""26 random cards"""].
Relevant code:
import random
suits = ['H','C','S','D']
ranks = ['A']+list(map(str,range(2,10)))+['X','J','Q','K']
values = [14]+list(range(2,14))
class Card:
def __init__(self,suit,rank):
self.suit=suit
self.rank=rank
self.value=values[ranks.index(self.rank)]
def __str__(self):
return "*------*\n|{0}{1} |\n| |\n| {0}{1}|\n*------*".format(self.rank,self.suit)
def __gt__(self,other):
return self.value > other.value
def __lt__(self,other):
return self.value < other.value
def __eq__(self,other):
return self.value == other.value
class Deck:
"""This class is for creating deck"""
def __init__(self):
self.deck=[]
for suit in suits:
for rank in ranks:
self.deck.append(Card(suit,rank))
self.shuffle()
def __str__ (self):
tmp=''
for card in self.deck:
tmp+=str(card)+'\n'
return tmp
def shuffle(self):
random.shuffle(self.deck)
def deal(self):
return self.deck.pop()
So the order of operations is going to execute your function once, then repeat the result 26 times. You probably want something more like:
deck1 = [d1.deal() for _ in range(26)]
Whenever you want to repeat an action a certain number of times, use a for loop.
d2 = []
for i in range(26):
d2.append(d1.deal())
There's no way for your code at the moment to create an empty deck. Maybe you should have a __init__ that creates an empty deck and then a separate method to make a full deck? Just a thought.
I have created a carddeck and every player is assigned a hand. I would like the players to be able to arrange their hand with the lowest value first and then print out this hand. I would like to think this can be done with .sort() but atm I'm getting a message
TypeError: unorderable types: NumberedCard() < NumberedCard()
I got a tip from the net that if I defined how .sort() is to work through a correct def __lt__(self, other): then I wouldn't be having this problem. So help me programmers figure this one out. Every card is defined by value and suit.
My code looks like this:
import random
suitlist=["Hearts","Spades","Clubs","Diamonds"]
class NumberedCard():
def __init__(self,value,suit):
self.value=value
self.suit=suit
def __str__(self):
return '%s of %s' %(self.value,suitlist[self.suit])
class JackCard():
def __init__(self,suit):
self.suit=suit
self.value=11
def __str__(self):
return 'Jack of %s' %(suitlist[self.suit])
class QueenCard():
def __init__(self,suit):
self.suit=suit
self.value=12
def __str__(self):
return 'Queen of %s' %(suitlist[self.suit])
class KingCard():
def __init__(self,suit):
self.suit=suit
self.value=13
def __str__(self):
return 'King of %s' %(suitlist[self.suit])
class AceCard():
def __init__(self,suit):
self.suit=suit
self.value=14
def __str__(self):
return 'Ace of %s' %(suitlist[self.suit])
class StandardDeck():
"""A class that creates a deck of 52 different cards, that also gives options to do matching operations with them"""
def __init__(self):
self.deck = []
for suit in range(4):
for value in range(2,11):
card = NumberedCard(value,suit)
self.deck.append(card)
self.deck.append(JackCard(suit))
self.deck.append(QueenCard(suit))
self.deck.append(KingCard(suit))
self.deck.append(AceCard(suit))
#for k in range(52):
# print(self.deck[k])
def shuffle(self):
"""Shake n' bake with the cards."""
random.shuffle(self.deck)
def take_card(self):
return self.deck.pop()
def deal_cards(self, hand,num):
for i in range(num):
hand.add_card(self.take_card())
class Hand:
"""A class to do the usual poker things during the game. Ie pick up cards, drop cards etc."""
def __init__(self):
self.hand = []
def __str__(self):
Handen=""
for card in self.hand:
Handen+=str(card) + "\n"
return Handen
def add_card(self,card):
self.hand.append(card)
def sort_cards(self):
self.hand.sort()
####Testing the program
deck=StandardDeck()
deck.shuffle()
hand=Hand()
hand.add_card(deck.take_card())
hand.add_card(deck.take_card())
print(hand)
hand.sort_cards() # <---- This is the part not working
So how is it done and where should it be put?
The best way to salvage this would be to create a class Card which would have a value and the __lt__ or __gt__ and a __eq__ defined method. And then proliferate those method by having all the other cards inherit from that parent class.
The proposed methods could be as simple as just compairing values of value which is an int and python knows how to do it himself.
Something like this:
>>> class Card(object):
def __init__(self, value):
self.value = value
def __lt__(self, other):
if other.value > self.value:
return True
return False
>>> class Ace(Card):
def __init__(self, value):
super().__init__(value)
>>> class NumCard(Card):
def __init(self, value):
super().__init__(value)
>>> jack = Ace(12)
>>> n = NumCard(7)
>>> jack > n
True
>>> n > jack
False
If you only want to sort the list in self.hand why not just use the key argument for sort to create a function to return the value to sort on?
self.hand.sort(key=lambda x: x.value)
This link should provide some info on sorting techniques