8

I was thinking about making a deck of cards for a card game. I could make a list of all of the cards (I don't really care about the suits), but I was wondering if there was a much easier way to do this.

cards = ['1','1','1','1'....]

I'm positive you could make a for loop to create 4 cards of the same value and add it to a list, but I was wondering if that was the best solution. I am not advanced enough to know about or create a Class which I have seen to be offered as other solutions, but I am open to explanations.

I have already made a dictionary defining the card values.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Mushy0364
  • 157
  • 1
  • 1
  • 7

13 Answers13

16

I propose you a solution with a basic class usage.

First, let's make a Card class:

class Card:
    def __init__(self, value, color):
        self.value = value
        self.color = color

Then, let's make a list of colors:

colors = ['heart', 'diamonds', 'spades', 'clubs']

Finally, let's build your deck with a list comprehension:

deck = [Card(value, color) for value in range(1, 14) for color in colors]

The Card class is only a wrapper, just to manipulate cards instead of tuples, which feels more natural.

In this current state, it's almost equivalent to renaming the tuple type... Basically, it only consists in a constructor, __init__, that sets the attributes of the instance.

So when I call Card(value, color) in the list comprehension, so for example Card(11, 'spades'), a new instance of the Card class is created, which has its value attribute set to 11, and its color attribute set to 'spades'.

I recommend you read some tutorial about OOP for an in-depth understanding of the concepts.


Now, you can try and improve this idea, for instance by using a more detailed values list instead of the range(1, 14):

values = ['ace', '2', ..., 'king']
Right leg
  • 16,080
  • 7
  • 48
  • 81
  • 1
    Do you think you could elaborate a little more on the `class` part of it? I am afraid I do not understand how it works, although I think your answer is great! – Mushy0364 Feb 01 '17 at 02:18
  • @Mushy0364 I edited my post :) Also, I don't like to do advertising for my own posts, but here is a strongly related question about what I think OOP can bring: [Python OO program structure planning](http://stackoverflow.com/q/41660924/7051394). – Right leg Feb 01 '17 at 02:26
  • Great thanks for clearing everything up, I will be sure to try this out. I have already made a dictionary with values being stored such as `values = {1:"Ace",etc.)` I will definitely take your recommendation of reading the OOP tutorial. Thank you for the assistance. – Mushy0364 Feb 01 '17 at 02:30
9

Another approach can be done using namedtuple from collections module, like this example:

from collections import namedtuple

Card = namedtuple('Card', ['value', 'suit'])
suits = ['hearts', 'diamonds', 'spades', 'clubs']
cards = [Card(value, suit) for value in range(1, 14) for suit in suits]

And you can access to the values like this:

print(cards[0])
>>> Card(value=1, suit='hearts')
print(cards[0].value, cards[0].suit)
>>> 1 hearts
Chiheb Nexus
  • 9,104
  • 4
  • 30
  • 43
7

You can represent your deck as a list of tuples. Which is a lighter weight alternative to classes. In dynamic languages like python, you will often do this to avoid the boilerplate code incurred by defining your own classes.

import itertools
import random

vals = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'jack', 'queen', 'king', 'ace']
suits = ['spades', 'clubs', 'hearts', 'diamonds']

deck = list(itertools.product(vals, suits))

random.shuffle(deck)

for val, suit in deck:
    print('The %s of %s' % (val, suit))

You may wish to represent the card values by an integer, this could easily be achieved by altering the input list.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
4
values = ['2','3','4','5','6','7','8','9','10','Jack','Queen','King','Ace']
suites = ['Hearts', 'Clubs', 'Diamonds', 'Spades']
deck = [[v + ' of ' + s,v] for s in suites for v in values]
sgk525
  • 132
  • 2
  • 13
2

This solution uses enum class (package enum34).

Two enum classes represent the Suit and the Number with a custom str function. The Card class takes a Suit + a Number

from enum import Enum          
from enum import unique        

@unique
class Suit(Enum):              
    Spade = 1
    Heart = 2
    Dimond = 3 
    Club = 4

    def __str__(self):
        return self.name

@unique
class Number(Enum):
    N1 = 1
    N2 = 2
    N3 = 3
    N4 = 4
    N5 = 5
    N6 = 6
    N7 = 7
    N8 = 8
    N9 = 9
    N10 = 10
    J = 11
    Q = 12
    K = 13 

    def __str__(self):
        if self.value <= 10:
            return str(self.value)          
        return self.name

class Card(object):
    def __init__(self, suit, number):
        self.suit = suit
        self.number = number

    def __str__(self):
        return '{} {}'.format(self.suit, self.number)

cards = [ Card(suit, number) for suit in Suit for number in Number ]
for card in cards:
    print card
greedy52
  • 1,345
  • 9
  • 8
2

First some utility functions:

import random
from random import shuffle

def RANKS(): return [ "Ace", "2", "3", "4", "5", "6", "7","8", "9", "10", "Jack", "Queen", "King" ]
def SUITS(): return [ "Clubs", "Diamonds", "Hearts", "Spades" ]

Then a Card class:

class Card:

    def __init__( self, rank, suit ):
        self.rank = rank
        self.suit = suit

    def __str__( self ):
        return self.rank + " of " + self.suit

Then a Deck class:

class Deck:

    def __init__( self ):
        self.contents = []
        self.contents = [ Card( rank, suit ) for rank in RANKS() for suit in SUITS() ]
        random.shuffle( self.contents )
wasabi
  • 29
  • 1
2

I found a very useful tutorial for this:

https://projects.raspberrypi.org/en/projects/deck-of-cards

It may look childish but it contains some really good-quality code

The code it contains looks something like this:

class Card:

    """
    The Card class represents a single playing card and is initialised by passing a suit and number.
    """

    def __init__(self, suit, number):
        self._suit = suit
        self._number = number

    def __repr__(self):
        return self._number + " of " + self._suit

    @property
    def suit(self):

        """
        Gets or sets the suit of a card
        """

        return self._suit

    @suit.setter
    def suit(self, suit):
        if suit in ["hearts", "clubs", "diamonds", "spades"]:
            self._suit = suit
        else:
            print("That's not a suit!")

    @property
    def number(self):
        """
        Gets or sets the number of a card
        """
        return self._number

    @number.setter
    def number(self, number):
        valid = [str(n) for n in range(2,11)] + ["J", "Q", "K", "A"]
        if number in valid:
            self._number = number
        else:
            print("That's not a valid number")
JohanC
  • 71,591
  • 8
  • 33
  • 66
bps
  • 21
  • 1
0

I think you're right, a for loop would get the job done but might not be the most elegant solution. I've never programmed in Python so I don't know the exact syntax but I could give you a psuedo code rundown of a class that would get the job done.

fatalError
  • 305
  • 2
  • 4
  • 17
0

Could also do this:

card_deck = []

for i in range(3,11):
    card_deck.extend([i]*4)

for c in ['Jack', 'Queen', 'King', 'Ace']:
    card_deck.extend([c]*4)
Gene Burinsky
  • 9,478
  • 2
  • 21
  • 28
0

This code makes a deck of 40 card with two for loops. The deck is made of 40 strings in witch the last caracter [-1] is the color among c b s d (coppe, bastoni, spade and denari in an italian type of card deck). As the 10th card got 2 digit for the value number it is a good practise to get the value of the card using [:-1] so that it will take 1,2,3... until 9 and 10 when there is this card with 2 digit.

class Cards:
    def __init__(self):
        self.deck = []                  # the deck is empty
        for n in range(1,11):           # numbers
            for c in "cbsd":            # colors
                self.deck.append(str(n) + c)  # a string for each card


deck = Cards()
deck.deck

output:

['1c', '1b', '1s', '1d', '2c', '2b', '2s', '2d', '3c', '3b', '3s', '3d', '4c', '4b', '4s', '4d', '5c', '5b', '5s', '5d', '6c', '6b', '6s', '6d', '7c', '7b', '7s', '7d', '8c', '8b', '8s', '8d', '9c', '9b', '9s', '9d', '10c', '10b', '10s', '10d']

PythonProgrammi
  • 22,305
  • 3
  • 41
  • 34
0

"simple code, deck list with 52 card combinations":

card_type=['Diamond', 'Heart', 'Spade', 'Clover']
card_number=['1','2','3','4', '5', '6', '7', '8', '9', 'J', 'Q', 'K']
for c in card_type:
    ...:     for n in card_number:
    ...:         deck.append([c,n])
dejanualex
  • 3,872
  • 6
  • 22
  • 37
0

An option is to create one card for each rank and suit using "for loops" and then attributing values, and having all the data on a tuple for each card, and retaining all cards in a list.

I used the following code to create a deck of cards without using class: (please not that the values I had attributed were for a blackjack game, but you can change it as you please)

ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
suits = ["Clubs", "Diamonds", "Hearts", "Spades"]
cards = []
def deck_of_cards():
    for rank in ranks:
        for suit in suits:
            a = rank
            b = suit
            if ranks.index(a) == 0:
                c = 11
            elif ranks.index(a) > 9:
                c = 10
            else:
                c = ranks.index(a) + 1
            new_card = (a, b, c)
            cards.append(new_card)

deck_of_cards()
0
cards = ["Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"]

deck = []

suits = ["Spades", "Diamonds", "Clubs", "Hearts"]
suit = 0
for card in range(52):
    if card >= 13 * (suit + 1):
        suit += 1
    deck.append(str(cards[card % 13] + "|" + suits[suit]))
J. M. Arnold
  • 6,261
  • 3
  • 20
  • 38