Reputation: 21
I'm making a multi-player game of blackjack and having been encountering issues getting the code (in python) to deal unique cards to multiple players. The code below has been dealing the same set of cards to all players.
An example of the results for 2 players is as follow:
Player1's first card is Four of Hearts. Player1's second card is Nine of Clubs. Player2's first card is Four of Hearts. Player2's second card is Nine of Clubs.
I have been reviewing the code and making amendments to the function of dealingcards, e.g. by using a while loop to go through each player and appending two cards to their hand. However, the result is no different.
Will anyone be able to advise where the error in the code lies? Thank you.
Code as shown below:
"""This is a game of Blackjack."""
import random
"""Defining the attributes of the cards"""
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
"""Class class must be able to understand the Suit and Rank of a card"""
class Card:
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.rank + " of " + self.suit
"""Deck class must be able to:
Instantiate a new deck and hold as a list of card objects;
Shuffle a deck through a method call; and
Deal cards from the deck."""
class Deck:
def __init__(self):
self.all_cards = []
for suit in suits:
for rank in ranks:
created_card = Card(suit,rank)
self.all_cards.append(created_card)
def shuffle(self):
random.shuffle(self.all_cards)
def deal_one(self):
return self.all_cards.pop()
def __str__(self):
statement = ""
for card in self.all_cards:
statement = statement + card.rank + " of " + card.suit + "\n"
return statement
"""Hand class must be able to:
Store the hands of the player;
Compute the value of each hand"""
class Playerhand:
def __init__(self,name,hands=[[],[],[],[]]):
self.name = name
self.hands = hands
def num_of_hands(self):
num_of_hands = 0
for hand in self.hands:
if hand != []:
num_of_hands += 1
else:
pass
return num_of_hands
def show_first_card(self):
print("{}'s first card is {}".format(self.name,self.hands[0][0]))
print("{}'s second card is {}".format(self.name,self.hands[0][1]))
def value_of_hands(self):
value_of_hands = []
for hand in self.hands:
total_value = 0
values = {'Two':2, 'Three':3, 'Four':4, 'Five':5, 'Six':6, 'Seven':7, 'Eight':8, 'Nine':9, 'Ten':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':11}
check_for_aces = []
for card in hand:
if card.suit == 'Ace':
check_for_aces.append('Ace')
else:
pass
for card in hand:
total_value = total_value + values[card.rank]
for item in range(0,len(check_for_aces)):
if total_value > 21:
total_value = total_value - 10
else:
pass
value_of_hands.append(total_value)
return value_of_hands
"""Pre-game:
Asking for the number of players to CREATE A LIST OF PLAYERS ['Dealer', 'P1', 'P2', etc.] and a DICTIONARY OF WAGERS {"P1": $X, "P2": $Y, etc.}"""
def number_of_players():
number_of_players = input("How many players are we expecting? Please enter 1 to 7: ")
while number_of_players.isdigit() == False or int(number_of_players) not in range(1,8):
number_of_players = input("Only accepting integer values between 1 to 7. Please enter 1 to 7: ")
return int(number_of_players)
def check_float(potential_float):
try:
float(potential_float)
return True
except:
return False
def playername(no_of_players):
print("We are expecting {} player(s). We are going to start collecting information on player names and wager!".format(no_of_players))
player_list = ['Dealer']
for number in range(1,no_of_players+1):
name = input("Player {}, what is your name? ".format(number))
while name in player_list:
name = input("Player {}, your chosen name has been taken. Please give us an alternative: ")
player_list.append(name)
return player_list
def playerwager(player_list):
player_wager = {}
for number in range(1, len(player_list)):
wager = input("{}, how much are you betting? Please input number: $ ".format(player_list[number]))
while check_float(wager) is False:
wager = input("{}, please input a valid wager in number: $ ".format(player_list[number]))
wager = float(wager)
player_wager[player_list[number]] = wager
player_wager["Dealer"] = 0
return player_wager
def dealingcards(player_list):
newdeck = Deck()
newdeck.shuffle()
print(newdeck) # Remove in due course.
for player in player_list:
for item in range(0,2):
Playerhand(player).hands[0].append(newdeck.deal_one())
Playerhand(player).show_first_card()
#GAME ON
x = number_of_players()
playerlist = playername(x)
playerwager(playerlist)
dealingcards(playerlist)
Upvotes: 2
Views: 820
Reputation: 127
This part of the code is wrong:
for player in player_list:
for item in range(0,2):
Playerhand(player).hands[0].append(newdeck.deal_one())
Playerhand(player).show_first_card()
You have to store the playerhand and not redefine it when showing the first card:
playerhands = []
for player in player_list:
playerhands.append(Playerhand(player,hands=[[],[],[],[]]))
for item in range(0,2):
playerhands[-1].hands[0].append(newdeck.deal_one())
playerhands[-1].show_first_card()
EDIT: This is the true source of the problem "Least Astonishment" and the Mutable Default Argument
Upvotes: 1
Reputation: 329
While Heiner is on the right track, I went through with a debugger and found that doing:
ph = Playerhand(player)
Mysteriously wasn't clearing the hand. The data seems to almost be static. However, a simple bandaid fix is as follows:
for player in player_list:
ph = Playerhand(player)
ph.hands[0] = []
for item in range(0, 2):
card = newdeck.deal_one()
ph.hands[0].append(card)
ph.show_first_card()
The hands were never clearing and that's why they kept outputting the same hand.
Upvotes: 0