patternpythonModerate
ASCII-fication of playing cards
Viewed 0 times
playingcardsasciification
Problem
I am making a small Blackjack game in Python 3. The part of the code I am unsure about is that which allows me to print nice
What the program does:
I am not seeking advice on the implementation of the
The basic idea of the code is that there are 9 lines of output, and we iterate over all of the card (input) and create the appropriate version of that line for that card. Then we add that line to a master line. In the end we have 9 master lines which are our output.
Since some of the ASCII art is rendered strangely in the browser here is a dpaste.
```
class Card(object):
card_values = {
'Ace': 11, # value of the ace is high until it needs to be low
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'10': 10,
'Jack': 10,
'Queen': 10,
'King': 10
}
def __init__(self, suit, rank):
"""
:param suit: The face of the card, e.g. Spade or Diamond
:param rank: The value of the card, e.g 3 or King
"""
self.suit = suit.capitalize()
self.rank = rank
self.points = self.card_values[rank]
def ascii_version_of_card(*cards, return_string=True):
"""
Instead of a boring text version of the card we render an ASCII image of the card.
:param cards: One or more card objects
:param return_string: By default we return the string version of the card, but the dealer hide the 1st card and we
keep it as a list so that the dealer can add a hidden card in front of the list
"""
# we will use this to prints the appropriate icons for each card
suits_name = ['Spades', 'Diamonds', 'Hearts', 'Clubs']
suits_symbols = ['♠', '♦', '♥', '♣']
# create an empty list of list, each sublist is a line
lin
ASCII versions of the card. ascii_version_of_card() and ascii_version_of_hidden_card().What the program does:
I am not seeking advice on the implementation of the
Card() class. Only on ascii_version_of_card() and ascii_version_of_hidden_card().The basic idea of the code is that there are 9 lines of output, and we iterate over all of the card (input) and create the appropriate version of that line for that card. Then we add that line to a master line. In the end we have 9 master lines which are our output.
Since some of the ASCII art is rendered strangely in the browser here is a dpaste.
```
class Card(object):
card_values = {
'Ace': 11, # value of the ace is high until it needs to be low
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'10': 10,
'Jack': 10,
'Queen': 10,
'King': 10
}
def __init__(self, suit, rank):
"""
:param suit: The face of the card, e.g. Spade or Diamond
:param rank: The value of the card, e.g 3 or King
"""
self.suit = suit.capitalize()
self.rank = rank
self.points = self.card_values[rank]
def ascii_version_of_card(*cards, return_string=True):
"""
Instead of a boring text version of the card we render an ASCII image of the card.
:param cards: One or more card objects
:param return_string: By default we return the string version of the card, but the dealer hide the 1st card and we
keep it as a list so that the dealer can add a hidden card in front of the list
"""
# we will use this to prints the appropriate icons for each card
suits_name = ['Spades', 'Diamonds', 'Hearts', 'Clubs']
suits_symbols = ['♠', '♦', '♥', '♣']
# create an empty list of list, each sublist is a line
lin
Solution
I know you're not seeking advice about
I would remove the
Your
should probably be tuples:
but they're only ever used as a mapping:
Your
looks a bit ugly, but I can see why you did that. What might be better is making an auxillary function to stack lines of strings first:
And then do:
Since the formatting of the card matters for prettiness, I'd be tempted to do:
Of course, since
This removes the need for
The calls to
and doing:
Here's the full thing:
```
CARD = """\
┌─────────┐
│{} │
│ │
│ │
│ {} │
│ │
│ │
│ {}│
└─────────┘
""".format('{rank: 2}')
HIDDEN_CARD = """\
┌─────────┐
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
└─────────┘
"""
def join_lines(strings):
"""
Stack strings horizontally.
This doesn't keep lines aligned unless the preceding lines have the same length.
:param strings: Strings to stack
:return: String consisting of the horizontally stacked input
"""
liness = [string.splitlines() for string in strings]
return '\n'.join(''.join(lines) for lines in zip(*liness))
def ascii_version_of_card(*cards):
"""
Instead of a boring text version of the card we render an ASCII image of the card.
:param cards: One or more card objects
:return: A string, the nice ascii version of cards
"""
# we will use this to prints the appropriate icons for each card
name_to_symbol = {
'Spades': '♠',
'Diamonds': '♦',
'Hearts': '♥',
'Clubs': '♣',
}
def card_to_string(card):
# 10 is the only card with a 2-char rank abbreviation
rank = card.rank if card.rank == '10' else card.rank[0]
# add the individual card on a line by line basis
return CARD.format(rank=rank, suit=name_to_symbol[card.
Card, but I feel I should point out that you don't need to inherit from object in Python 3.I would remove the
return_string option; if someone wants a list they should just call splitlines.Your
suits_name = ['Spades', 'Diamonds', 'Hearts', 'Clubs']
suits_symbols = ['♠', '♦', '♥', '♣']should probably be tuples:
suits_name = 'Spades', 'Diamonds', 'Hearts', 'Clubs'
suits_symbols = '♠', '♦', '♥', '♣'but they're only ever used as a mapping:
name_to_symbol = {
'Spades': '♠',
'Diamonds': '♦',
'Hearts': '♥',
'Clubs': '♣',
}Your
# add the individual card on a line by line basis
lines[0].append('┌─────────┐')
lines[1].append('│{}{} │'.format(rank, space)) # use two {} one for char, one for space or char
lines[2].append('│ │')
lines[3].append('│ │')
lines[4].append('│ {} │'.format(suit))
lines[5].append('│ │')
lines[6].append('│ │')
lines[7].append('│ {}{}│'.format(space, rank))
lines[8].append('└─────────┘')looks a bit ugly, but I can see why you did that. What might be better is making an auxillary function to stack lines of strings first:
def join_lines(strings):
string_lines = [string.splitlines() for string in strings]
return '\n'.join(''.join(out_line) for out_line in zip(*string_lines))And then do:
card = (
'┌─────────┐\n'
'│{r}{_} │\n'
'│ │\n'
'│ │\n'
'│ {s} │\n'
'│ │\n'
'│ │\n'
'│ {_}{r}│\n'
'└─────────┘\n'
).format(r=rank, _=space, s=suit)
card_strings.append(card)Since the formatting of the card matters for prettiness, I'd be tempted to do:
card = (
'┌─────────┐\n'
'│{} │\n'
'│ │\n'
'│ │\n'
'│ {} │\n'
'│ │\n'
'│ │\n'
'│ {}│\n'
'└─────────┘\n'
).format(
format(card.rank, ' 2')
)Of course, since
card is from a static, you can move it out to get justcard = CARD.format(
format(rank, ' 2')
)This removes the need for
space. You can then make the main loop a comprehension if you make a function, and stick it inside the join_lines call:def card_to_string(card):
# 10 is the only card with a 2-char rank abbreviation
rank = card.rank if card.rank == '10' else card.rank[0]
suit = name_to_symbol[card.suit]
# add the individual card on a line by line basis
return CARD.format(
format(rank, ' 2')
)
return join_lines(map(card_to_string, cards))The calls to
format can be removed by making card like:CARD = """\
┌─────────┐
│{} │
│ │
│ │
│ {} │
│ │
│ │
│ {}│
└─────────┘
""".format('{rank: 2}')and doing:
def card_to_string(card):
# 10 is the only card with a 2-char rank abbreviation
rank = card.rank if card.rank == '10' else card.rank[0]
# add the individual card on a line by line basis
return CARD.format(rank=rank, suit=name_to_symbol[card.suit])ascii_version_of_hidden_card can then be just:def ascii_version_of_hidden_card(*cards):
"""
Essentially the dealers method of print ascii cards. This method hides the first card, shows it flipped over
:param cards: A list of card objects, the first will be hidden
:return: A string, the nice ascii version of cards
"""
return join_lines((HIDDEN_CARD, ascii_version_of_card(*cards[1:])))Here's the full thing:
```
CARD = """\
┌─────────┐
│{} │
│ │
│ │
│ {} │
│ │
│ │
│ {}│
└─────────┘
""".format('{rank: 2}')
HIDDEN_CARD = """\
┌─────────┐
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
│░░░░░░░░░│
└─────────┘
"""
def join_lines(strings):
"""
Stack strings horizontally.
This doesn't keep lines aligned unless the preceding lines have the same length.
:param strings: Strings to stack
:return: String consisting of the horizontally stacked input
"""
liness = [string.splitlines() for string in strings]
return '\n'.join(''.join(lines) for lines in zip(*liness))
def ascii_version_of_card(*cards):
"""
Instead of a boring text version of the card we render an ASCII image of the card.
:param cards: One or more card objects
:return: A string, the nice ascii version of cards
"""
# we will use this to prints the appropriate icons for each card
name_to_symbol = {
'Spades': '♠',
'Diamonds': '♦',
'Hearts': '♥',
'Clubs': '♣',
}
def card_to_string(card):
# 10 is the only card with a 2-char rank abbreviation
rank = card.rank if card.rank == '10' else card.rank[0]
# add the individual card on a line by line basis
return CARD.format(rank=rank, suit=name_to_symbol[card.
Code Snippets
suits_name = ['Spades', 'Diamonds', 'Hearts', 'Clubs']
suits_symbols = ['♠', '♦', '♥', '♣']suits_name = 'Spades', 'Diamonds', 'Hearts', 'Clubs'
suits_symbols = '♠', '♦', '♥', '♣'name_to_symbol = {
'Spades': '♠',
'Diamonds': '♦',
'Hearts': '♥',
'Clubs': '♣',
}# add the individual card on a line by line basis
lines[0].append('┌─────────┐')
lines[1].append('│{}{} │'.format(rank, space)) # use two {} one for char, one for space or char
lines[2].append('│ │')
lines[3].append('│ │')
lines[4].append('│ {} │'.format(suit))
lines[5].append('│ │')
lines[6].append('│ │')
lines[7].append('│ {}{}│'.format(space, rank))
lines[8].append('└─────────┘')def join_lines(strings):
string_lines = [string.splitlines() for string in strings]
return '\n'.join(''.join(out_line) for out_line in zip(*string_lines))Context
StackExchange Code Review Q#82103, answer score: 10
Revisions (0)
No revisions yet.