I'm trying to write a blackjack game and finding that I'm repeating code a lot.
I know I should construct a for loop but my mind is like mush.
To set up:
import random
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
def deal_card():
return random.sample(cards, 2)
player_cards = deal_card()
computer_cards = deal_card()
Then I'm trying to calculate the score through some stages, including:
if 11 in player_cards and sum(player_cards) > 21:
player_cards = player_cards.remove(11)
player_cards = player_cards.append(1)
if 11 in computer_cards and sum(computer_cards) > 21:
computer_cards = computer_cards.remove(11)
computer_cards = computer_cards.append(1)
I don't want to have to repeat all the code for both players but I'm struggling on the for loop.
Do I create a variable with the two lists (player_cards and computer_cards)?
Do I create a list of lists and loop through that?
Do I use map, zip or another Python tool?
Any ideas would be much appreciated.
CodePudding user response:
Probably the most straightforward way is to define a list of players (including the computer) and then use a dict to store cards. Here, I make separate lists of human and computer players, and then combine them to form the full list of players:
human_players = ["human 1"]
computer_players = ["computer 1"]
players = human_players computer_players
cards = dict()
for p in players:
cards[p] = deal_card()
...
for p in players:
while 11 in cards[p] and sum(cards[p]) > 21:
cards[p].remove(11)
cards[p].append(1)
if p in human_players:
# do any human-only stuff here
if p in computer_players :
# do any computer-only stuff here
Some points to note:
- This approach easily extends to games with more than 2 players.
- Changed your "if" to a "while" because it's possible to have more than one ace in hand. (Probably doesn't matter - I think just about the only time this would make a difference is if you were dealt (10,A) and for some strange reason chose to draw another card, and got another ace. But it's generally best to keep the code close to the underlying logic and not rely on "that case will never come up".)
- Changed the syntax for your remove and append calls.
I assume player_cards = player_cards.remove(11)
is intended to achieve the following:
- retrieve the list named
player_cards
- create a new list, based on the old one but with 11 removed
- overwrite the old
player_cards
with this new one.
But that's not quite how it works. .remove()
is a method that modifies the list and returns no value.
If you try player_cards=player_cards.remove(11)
, it will first remove the 11 as intended, but then it will overwrite player_cards
with that no-value. Similarly for .append()
.
Note that in your current approach, cards dealt to one player are still available to be dealt to other players (and possibly to be dealt to the same player again!) I haven't fixed this, but if that matters, you probably want to keep track of all undealt cards, deal by selection from the remaining undealt cards, and update that "undealt" info as you deal.
CodePudding user response:
You can make a function to sum the cards and just call that on each hand, im not that familliar with the rules of blackjack but using your logic above i get this:
def sum_cards(hand):
if 11 in hand and sum(hand) > 21:
return sum(hand)-11
else:
return sum(hand)
with give this output:
>>> player_hand = [11,10]
>>> computer_hand =[11,11]
>>> sum_cards(player_hand)
21
>>> sum_cards(computer_hand)
11