patternpythonMinor
Command-line blackjack for up to 6 players in Python
Viewed 0 times
lineplayersforpythoncommandblackjack
Problem
Here is command-line blackjack for up to 6 players (not including dealer). Would love any and all feedback!
```
"""
This is the code for a blackjack game.
"""
from random import shuffle
from time import sleep
def get_valid_response(query, valid_responses):
response = raw_input(query)
if response.lower() not in [r.lower() for r in valid_responses]:
print "That is not a valid response. Try again."
response = get_valid_response(query, valid_responses)
return response
class Player:
def __init__(self, name, game):
self.cards = []
self.name = name
self.busted = False
self.game = game
def receive_card(self, card, is_face_up = True):
card.is_face_up = is_face_up
self.cards.append(card)
def cards_string(self):
return [card.to_string() for card in self.cards]
def raw_points(self):
return sum([card.points() for card in self.cards])
def points(self):
total = self.raw_points()
# Check if we should reduce the value of aces
if total > 21:
ace_indices = [index for index, card in enumerate(self.cards) if card.rank == 'A']
for ace_index in ace_indices:
self.cards[ace_index].secondary_value = True
if self.raw_points() <= 21:
return self.raw_points()
return total
def ask_for_decision(self):
return get_valid_response("\nAttention {}!\nYou have {}. This totals {} points.\nWould you like to 'hit' or 'stay'? ".
format(self.name, self.cards_string(), self.points()),
["hit", "stay"])
def bust(self):
print "\n{}, you have busted with {}. This totals {}!\n".format(self.name, self.cards_string(), self.points())
self.busted = True
def hit(self):
self.game.deck.deal_card_to(self)
if self.points() <= 21:
self.play()
else:
```
"""
This is the code for a blackjack game.
"""
from random import shuffle
from time import sleep
def get_valid_response(query, valid_responses):
response = raw_input(query)
if response.lower() not in [r.lower() for r in valid_responses]:
print "That is not a valid response. Try again."
response = get_valid_response(query, valid_responses)
return response
class Player:
def __init__(self, name, game):
self.cards = []
self.name = name
self.busted = False
self.game = game
def receive_card(self, card, is_face_up = True):
card.is_face_up = is_face_up
self.cards.append(card)
def cards_string(self):
return [card.to_string() for card in self.cards]
def raw_points(self):
return sum([card.points() for card in self.cards])
def points(self):
total = self.raw_points()
# Check if we should reduce the value of aces
if total > 21:
ace_indices = [index for index, card in enumerate(self.cards) if card.rank == 'A']
for ace_index in ace_indices:
self.cards[ace_index].secondary_value = True
if self.raw_points() <= 21:
return self.raw_points()
return total
def ask_for_decision(self):
return get_valid_response("\nAttention {}!\nYou have {}. This totals {} points.\nWould you like to 'hit' or 'stay'? ".
format(self.name, self.cards_string(), self.points()),
["hit", "stay"])
def bust(self):
print "\n{}, you have busted with {}. This totals {}!\n".format(self.name, self.cards_string(), self.points())
self.busted = True
def hit(self):
self.game.deck.deal_card_to(self)
if self.points() <= 21:
self.play()
else:
Solution
Code gives good overall impression.
Some micro-level suggestions:
Regarding object decomposition, classes, especially the
To decouple logic and presentation, well-known design approaches can be used, for example (but not necessarily!), MVC or similar. In short and oversimplifying, there will be VC-classes, dedicated to user interfaces (input/output), and M-classes, holding the model - mostly current classes, stripped of prints/inputs and representation concerns. You can also go four-tier (if it does not feel as overkill): presentation, business logic, data access, database. Specific choice depends on the larger system you think your software will be part of. It may well be that 2 layers are enough for your purposes for now (presentation + the rest).
For concrete example, instead of doing
Some micro-level suggestions:
- get rid of recursion in
get_valid_response: all that will be safer withwhile-loop and break, usual pattern in Python
- remove
[]insum: generator will work just fine unless you are using very old Python.
- it's better to inherit from
object. Your code uses classic classes at the moment.
- conversions to lower case at the border (near the input) will make your code cleaner.
- there are some PEP8 code style violations (eg, spaces around keyword argument) - check with a tool
Regarding object decomposition, classes, especially the
Game class, mixes logic and presentation. But may be it's not a problem if the game is not intended to be part of a larger system, where other UI modalities will be used.To decouple logic and presentation, well-known design approaches can be used, for example (but not necessarily!), MVC or similar. In short and oversimplifying, there will be VC-classes, dedicated to user interfaces (input/output), and M-classes, holding the model - mostly current classes, stripped of prints/inputs and representation concerns. You can also go four-tier (if it does not feel as overkill): presentation, business logic, data access, database. Specific choice depends on the larger system you think your software will be part of. It may well be that 2 layers are enough for your purposes for now (presentation + the rest).
For concrete example, instead of doing
print, call i/o class methods, concerned with game communication. This way, specific way your code does it will not be tightly coupled with the rest of the game logic. You will be able to do, say, client-server for your game. Of course, which way communication is initiated, who pushes and who pulls data, will require some thinking. May well be in your architecture, that UI will call underlying game model objects.Context
StackExchange Code Review Q#148900, answer score: 3
Revisions (0)
No revisions yet.