Trouble giving values to deck of cards - python

(Cards numbered 2-10 should be valued from 2-10, respectively. J,Q, and K should be 10, and A should be either 1 or 11, depending on the value of the hand).
How do I assign the deck these values? Also, the game needs to be 3 rounds. The way I did it is only one round. How do I make the game go three times, while keeping track of the players wins/losses?
Could someone please explain how I can do this a simple way?

here is a complete implementation for you
look at hand.Score
import random
class Card:
def __init__(self,rank,suite):
self.rank = rank
self.suite = suite
def Rank(self):
return "Ace Two Three Four Five Six Seven Eight Nine Ten Jack Queen King".split()[self.rank]
def Suite(self):
return "Hearts Spades Clubs Diamonds".split()[self.suite]
def __str__(self):
#print "Get Self:",type(self)
#print "Dir:",dir(self)
#return "OF"
return self.Rank()+" of "+ self.Suite()
class Hand:
def __init__(self):
self.cards = []
def Score(self):
aces_ct = 0
score = 0
for c in self.cards:
if c.rank == 0:
aces_ct += 1
score += 11
if 0 < c.rank < 9:
score += c.rank+1
else:
score += 10
while score > 21 and aces_ct > 0:
score -= 10
aces_ct -= 1
return score
def add(self,card):
self.cards.append(card)
def Show(self,show_only=None):
if not show_only:
for k in self.cards:
print "%s"%k
else:
if isinstance(show_only,int):
print "%s"%self.cards[show_only]
elif isinstance(show_only,(list,tuple)):
for idx in show_only:
print "%s"%self.cards[idx]
class deck:
def __init__(self):
self.cards = []
for i in range(4):
for j in range(13):
self.cards.append(Card(j,i))
random.shuffle(self.cards)
def shuffle(self):
random.shuffle(self.cards)
def pop(self):
return self.cards.pop()
if __name__ == "__main__":
d = deck()
player_hand = Hand()
dealer_hand = Hand()
player_hand.add(d.pop())
dealer_hand.add(d.pop())
player_hand.add(d.pop())
dealer_hand.add(d.pop())
print "Player Score :",player_hand.Score()
player_hand.Show()
print "\n\nDealer Score :",dealer_hand.Score()
dealer_hand.Show()

You can represent cars as tuples: a character indicating suit, and a number indicating value. I would also add a third value to the tuple, its blackjack value (e.g. a king and a queen both count as a 10).
card = ('D', 11, 10) # card is queen of diamonds
You could also make your own class to represent cards.
class Card(object):
def __init__(self, suit, number):
self.suit = suit
self.number = number
self.value = (number if 2 <= number <= 9 else 10)
You will have to special-case the value of the ace, of course.

You should probably calculate the total dynamically. Also, you need some kind of way to store the money of each individual player. Right now, there is no way of knowing the distribution of money since you only have one total.

Related

Making card game, how do I give the face cards value

Im making a card game for a project for my high school class. I'm making black jack but with changed rules and new features. I am using the random plugin to randomize the numbers. I am not using suits but am using face cards. How do I make it so if a user gets a face card like 'King' the program knows the value of the face card and able to calculate the total.
For example if one user gets a 3 card and a King card their total will be 13 as King = 10. How will I make the face cards have values and put it into a list with the normal cards
Here is my code so far, I know how to deal more cards later, just want to know how to add face cards and their value to shuffle. Thanks
while len(dealer_cards) != 2:
dealer_cards.append(random.randint(2, 10))
if len(dealer_cards) == 2:
print("The Dealer has:", dealer_cards)
# Players cards
while len(player_cards) != 2:
player_cards.append(random.randint(2, 10))
if len(player_cards) == 2:
print("You have:", player_cards)
One way is to define the card as an object (dictionary)
Note that this is just a way to build your logic: This doesn't take into effect other rules (like how many total cards and if the same card gets dealt out twice. You need more rules and house-keeping for that
card = {
"face": "K", # This indicates what is printed on the face
"value": 10, # This indicates the value (used internally)
"suite": "spade", # will be one of ["spade", "jack", "clubs", "hearts"]
}
define a function to get a random card:
def getRandomCard():
# list of possible cards with their values
cards = [("1", 1), ("2", 2).. ("J", <value>), ("Q", <value>), ("K", <value>), ("A", <value>)]
randIdx = <Get random number>
randomCard, randomCardValue = cards[randIdx % len(cards)] #
suits = ["spade", "jack", "clubs", "hearts"]
randomSuite = <similarly pick a random suite>
return {
"face": randomCard,
"value": randomCardValue,
"suite": randomSuite
}
Now rest of your code deals with the card object.
you get the idea..
I quickly wrote this bare bones blackjack game. It doesn't have betting, splitting, or even the logic to say if who wins but it does the basic game play. I hope you can look at this example of Object Oriented programming and maybe learn something.
import random
class Card:
suits = {0:"Spades",
1:"Heaarts",
2:"Clubs",
3:"Dimods"}
names = {1:"Ace",
2:"Duce",
3:"Three",
4:"Four",
5:"Five",
6:"Six",
7:"Seven",
8:"Eight",
9:"Nine",
10:"Ten",
11:"Jack",
12:"Queen",
0:"King"}
def __init__(self,id):
self.id = id
self.name = id%13
self.suit = int((id-1)/13)
def announce(self):
return Card.names[self.name]+" of "+Card.suits[self.suit]
def value(self):
if self.name > 10:
return 10
if self.name == 1:
return 0
else:
return self.name
class Deck:
def __init__(self):
self.cards=[int(k) for k in range(1,53)]
def restock(self):
self.cards = range(1,53)
def deal(self):
cardIndex = random.choice(range(len(self.cards)))
cardId = self.cards[cardIndex]
del self.cards[cardIndex]
return Card(cardId)
def evaluate(hand):
total = 0
aces = 0
for c in hand:
v = c.value()
if v:
total+= v
else:
aces+=1
while aces > 0:
aces-=1
if total<11-aces:
total+=11
else:
total+=1
return 0 if total>21 else total
class Player:
deck = Deck()
def __init__(self):
self.hand = []
def getCard(self):
self.hand.append(self.deck.deal())
def discard(self):
self.hand = []
def play(self):
print("Player has:")
print(self.hand[0].announce())
print(self.hand[1].announce())
hitOrStand="hit"
v = evaluate(self.hand)
while hitOrStand != "stand" and v:
hitOrStand = input("hit or stand:")
if hitOrStand not in ["hit","stand"]:
print("please enter `hit` or `stand`.")
continue
if hitOrStand == "hit":
self.getCard()
print(self.hand[-1].announce())
v = evaluate(self.hand)
print(v if v else "bust")
class Dealer(Player):
def hits(self):
v = evaluate(self.hand)
return True if v<17 and v else False
def play(self):
print("Dealer has:")
print(self.hand[0].announce())
print(self.hand[1].announce())
while self.hits():
print("And gets:")
self.getCard()
print(self.hand[-1].announce())
v = evaluate(self.hand)
v = evaluate(self.hand)
print(v if v else "bust")
def restock(self):
Player.deck.restock()
class Game:
def __init__(self):
self.player = Player()
self.dealer = Dealer()
def playRound(self):
self.player.getCard()
self.dealer.getCard()
self.player.getCard()
self.dealer.getCard()
self.player.play()
self.dealer.play()
self.player.discard()
self.dealer.discard()
self.dealer.restock()
g = Game()
g.playRound()

Python 3: How can I display what cards the dealer and players have in my game of black jack?

How do I get an output of? I have the bottom two lines.
Dealer: 9 of Diamonds; 4 of Hearts;
Alice: 2 of Diamonds; Jack of Diamonds;
Bob: 7 of Clubs; 9 of Spades;
Alice lost. Alice now has $95
Bob won! Bob now has $55
I don't know how Im supposed to call my str methods to display what cards the dealer has and what cards the two players have. I need it in that exact format but I'm not sure how to call it from main. Please let me know what could work!
import random
class Card():
# initialize the card class
def __init__(self, suit, value):
self.suit = suit
self.__value = value
def __str__(self):
if self.__value == 11:
return "Jack of " + self.suit
if self.__value == 12:
return "Queen of " + self.suit
if self.__value == 13:
return "King of " + self.suit
if self.__value == 14:
return "Ace of " + self.suit
else:
return str(self.__value) + " of " + self.suit
def get_value(self):
if(self.__value <= 10):
return self.__value
elif self.__value <= 13:
return 10
else:
return 14
class DeckOfCards():
# initialize the deck of cards class
def __init__(self):
self.deck = []
suits = ["Hearts", "Diamonds", "Clubs", "Spades"]
for i in range(len(suits)):
for j in range(2, 15):
self.deck.append(Card(suits[i],j))
def print_deck(self):
for i in range(len(self.deck)):
print(self.deck[i])
def shuffle(self):
random.shuffle(self.deck)
def draw_card(self):
return self.deck.pop()
class Dealer():
def __init__(self, name = "Dealer"):
self.name = name
self.hand = []
def __str__(self):
string = self.name + ": "
for i in range(len(self.hand) - 1):
string += self.hand[i] + ": "
string += self.hand[len(self.hand) - 1]
return string
class Player():
def __init__(self, name, amount):
self.name = name
self.amount = amount
self.hand = []
def __str__(self):
string = self.name + ": "
for i in range(len(self.hand) - 1):
string += self.hand[i] + ": "
string += self.hand[len(self.hand) - 1]
return string
def main():
deck = DeckOfCards()
dealer = Dealer()
players = []
players.append(Player("Alice", 100))
players.append(Player("Bob", 50))
deck.shuffle()
dealer.hand.append(deck.draw_card())
dealer.hand.append(deck.draw_card())
for i in range(len(players)):
players[i].hand.append(deck.draw_card())
players[i].hand.append(deck.draw_card())
dealerHand=0
for i in range(len(dealer.hand)):
dealerHand += dealer.hand[i].get_value()
for i in range(len(players)):
playerHand = 0
for j in range(len(players[i].hand)):
playerHand =+ players[i].hand[i].get_value()
if dealerHand > playerHand:
players[i].amount -= 5
print(players[i].name + " lost. " + players[i].name + \
" has now $" + str(players[i].amount))
else:
players[i].amount += 5
print(players[i].name + " won! " + players[i].name + \
" has now $" + str(players[i].amount))
if __name__ == "__main__":
main()
You have two issues. The first is that you're not trying to print out the hands at all in the main function. You just go immediately on to finding what score each hand is worth and announcing who won. Fixing that is pretty easy, you just need to print(dealer) and add another loop over the players printing each one in turn. You're generally going the long-way around by using for i in range(len(players)), you can just iterate directly on the list of players instead:
# add this either just above or just below the `dealerHand` loop.
print(dealer)
for p in players:
print(p)
The second issue you have is that your code creating the output in Player.__str__ and the identical Dealer.__str__ method doesn't actually convert the Card objects it's trying to format into strings. You need to add a str call anywhere you're looking up self.hand[whatever]:
def __str__(self):
string = self.name + ": "
for i in range(len(self.hand) - 1):
string += str(self.hand[i]) + ": "
string += str(self.hand[len(self.hand) - 1])
return string
A few other notes, unrelated to your errors:
As I mentioned, you don't always need to loop over a range. A lot of the time, you don't need the index at all, so just loop over the values in a list, instead of indexing. For the loop in the __str__ methods, you arguably do need the index since you want to treat the last value differently (not appending a semicolon), but there's a much better solution using str.join. Just call "; ".join(str(c) for c in self.hand).
Another suggestion is to use string formatting methods, like str.format or the newer f-strings (which do more or less the same thing with dedicated syntax) instead of concatenating lots of strings together with +. The latter is much less efficient, and often prone to error, as you had in your code.
And finally, it's a bad idea to have two nearly identical classes, as you currently have with Player and Dealer (which differ exclusively in the default argument that Dealer provides for name, as far as I can tell). Either you should only have one class, or you should have two classes where one inherits most of its behavior from the other class (or possibly where two child classes inherit common behavior from a third base class).
for i in range(len(players)):
for card in players[i].hand:
print(card)

How to sum a list that contains letters by changing certain letters in a list with integers?

Just started learning Python and I am trying to create a blackjack game. I want to find the sum of the card values in a player's hand. My approach was to change the letters "J", "Q","K" into values of 10 and change "A" to value of 11. I have defined the class Card but when I run the code, I get an error saying "type object 'Card' has no attribute 'value'"
import random
DEFAULT_SUITS = ("Clubs","Hearts","Diamonds","Spades")
DEFAULT_VALUES = ("A",2,3,4,5,6,7,8,9,10,"J","Q","K")
class Card():
def __init__ (self, suit, value):
self.suit = suit
self.value = value
def show(self):
print(self.value, self.suit)
class Shoes():
def __init__(self, decks, suits=DEFAULT_SUITS, values=DEFAULT_VALUES):
self.cards = []
for deck in range(decks):
for suit in suits:
for value in values:
self.cards.append(Card(suit,value))
random.shuffle(self.cards)
def show(self):
for card in self.cards:
card.show()
def drawcard(self):
return self.cards.pop()
class Player():
def __init__ (self, name):
self.name = name
self.hand = []
def drawcard(self, shoes):
self.hand.append(shoes.drawcard())
return self
def totalvalue(self):
for card in self.hand:
if Card.value == "J":
self.hand = [10 if card=="J" else card for card in cards]
if Card.value == "Q":
self.hand = [10 if card=="Q" else card for card in cards]
if Card.value == "K":
self.hand = [10 if card=="K" else card for card in cards]
if Card.value == "A":
self.hand = [11 if card=="A" else card for card in cards]
self.totalvalue = sum(self.hand(Card.value))
def showhand(self):
for card in self.hand:
card.show()
shoe = Shoes(int(input("Enter the number of deck used in a shoes: ")))
bob = Player("bob")
bob.drawcard(shoe)
bob.showhand()
bob.totalvalue()
How can I change the values "J","Q","K","A" in hand and sum it up to get the total value?
you have used Card.value, where Card is a class instace, just change Card to card in totalvalue function.
and next thing, i will suggest to make a dictionary;
and take every value from that even numbers too.
dict = {'A':1, '2':2,.......}
and so on, like this
def totalvalue(self):
self.totalvalue =0;
dict = {'A':1, '2':2,.......};
for card in self.hand:
self.totalvalue = self.totalvalue +dict[card.value]
I see there is some confusion in using the list of Cards. Here what you should be doing
def totalvalue(self):
total = 0
for card in self.hand:
if card.value in ["J", "Q", "K"]:
total = total + 10
elif card.value == "A":
total = total + 11
else:
total = total + card.value
self.totalvalue = total
Code can be further simplified using the list comprehension as follows
def totalvalue(self):
return sum([10 if card.value in ['J', 'Q', 'K'] else 11 if card.value == 'A' else card.value for card in self.hand])

How to program blackjack scoring for an ace

I am trying to create a blackjack simulation so I can test various strategies and simulate them indefinitely. The biggest problem I have encountered is how to score an ace card. Ideally if you were dealt an ace, it would look at your score and it will give you 1 or 11 accordingly however I can't avoid if you were dealt a Five(5), Ace(11) and then a Six(6) to giving you a bust when you should have 12.
class Person:
wins = 0
def __init__(self, call):
self.call = call
self.hand = []
def deal(self, cards_dealt):
cards_in_deck = len(deck)
for card in range(0, cards_dealt):
card_position = (random.randint(0, cards_in_deck) - 1)
self.hand.append(deck[card_position])
deck.pop(card_position)
cards_in_deck -= 1
def total(self):
my_total = 0
for x in range(0, len(self.hand)):
if self.hand[x][0] > 10:
my_total += 10
if self.hand[x][0] == 1:
if self.total < 11:
my_total += 11
else:
my_total += 1
else:
my_total += self.hand[x][0]
return my_total
numbers_in_each_suit = 13
suits = ['Spades', 'Hearts', 'Diamonds', 'Clubs']
deck = []
for number in range(0, numbers_in_each_suit):
for suit in suits:
deck.append([(number + 1), suit])
cpu = Person(10)
cpu.deal(2)
cpu.total()
Just use 1 for number for creating ace, add 11 for every ace and count each ace, and then subtract 10 if you bust until you don’t or until you run out of aces to decrement.

BlackJack Game Main Script Trouble (Classes Already Done)

For my class project I am to make a BlackJack game that functions properly. It is a water-downed version of the game, (No Betting, Doubling Down , Splitting, etc...). We are to use different classes for the Deck, Hand and Card functions, which I did. The main trouble I am having is how to put it all together in a cohesive program so it can run. Here are my classes
class Card(object):
'''A simple playing card. A Card is characterized by two
components:
rank: an integer value in the range 2-14, inclusive (Two-Ace)
suit: a character in 'cdhs' for clubs, diamonds, hearts, and
spades.'''
#------------------------------------------------------------
SUITS = 'cdhs'
SUIT_NAMES = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
RANKS = range(2,15)
RANK_NAMES = ['Two', 'Three', 'Four', 'Five', 'Six',
'Seven', 'Eight', 'Nine', 'Ten',
'Jack', 'Queen', 'King', 'Ace']
RANK_VALUES = [99, 99, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11]
#------------------------------------------------------------
def __init__(self, rank, suit):
'''Constructor
pre: rank in range(1,14) and suit in 'cdhs'
post: self has the given rank and suit'''
self.rank_num = rank
self.suit_char = suit
#------------------------------------------------------------
def getSuit(self):
'''Card suit
post: Returns the suit of self as a single character'''
return self.suit_char
#------------------------------------------------------------
def getRank(self):
'''Card rank
post: Returns the rank of self as an int'''
return self.rank_num
#------------------------------------------------------------
def getCardValue(self):
value = self.RANK_VALUES[self.rank_num]
return value
#------------------------------------------------------------
def suitName(self):
'''Card suit name
post: Returns one of ('clubs', 'diamonds', 'hearts',
'spades') corrresponding to self's suit.'''
index = self.SUITS.index(self.suit_char)
return self.SUIT_NAMES[index]
#------------------------------------------------------------
def rankName(self):
'''Card rank name
post: Returns one of ('ace', 'two', 'three', ..., 'king')
corresponding to self's rank.'''
index = self.RANKS.index(self.rank_num)
return self.RANK_NAMES[index]
#------------------------------------------------------------
def __str__(self):
'''String representation
post: Returns string representing self, e.g. 'Ace of Spades' '''
return self.rankName() + ' of ' + self.suitName()
#------------------------------------------------------------
from random import randrange
from Card import Card
from Hand import Hand
class Deck(object):
def __init__(self):
'''This creates the deck of cards, un-shuffled.'''
cards = []
for suit in Card.SUITS:
for rank in Card.RANKS:
cards.append(Card(rank,suit))
self.cards = cards
def size(self):
'''How many cards are left.'''
return len(self.cards)
def deal(self):
'''Deals a single card.
Pre: self.size() > 0
Post: Returns the next card in self, and removes it from self.'''
return self.cards.pop()
def shuffle(self):
'''This shuffles the deck so that the cards are in random order.'''
n = self.size()
cards = self.cards
for i,card in enumerate(cards):
pos = randrange(i,n)
cards[i] = cards[pos]
cards[pos] = card
def takeAHit(self, whatHand):
aCard = self.deal()
whatHand.addCard(aCard)
def __str__(self):
if self.size() == 52:
return 'The Deck is Full'
elif self.size() > 0:
return 'The Deck has been Used'
else:
return 'The Deck is Empty'
from Card import Card
class Hand(object):
"""A labeled collection of cards that can be sorted"""
#------------------------------------------------------------
def __init__(self, label=""):
"""Create an empty collection with the given label."""
self.label = label
self.cards = []
#------------------------------------------------------------
def add(self, card):
""" Add card to the hand """
self.cards.append(card)
#------------------------------------------------------------
def totalHand(self):
totalHand = 0
aceAmount = 0
for c in self.cards:
if c.getRank() == 14:
aceAmount += 1
totalHand +=c.getCardValue()
while aceAmount > 0:
if totalHand > 21:
aceAmount -= 1
totalHand -= 10
else:
break
return totalHand
def __str__(self):
if self.cards == []:
return "".join([(self.label), "doesn't have any cards."])
tempStringList = [ self. label, "'s Cards, "]
for c in self.cards:
tempStringList.append(str(c))
tempStringList.append(" , ")
tempStringList.pop()
tempStringList.append(" . ")
return "".join(tempStringList)
Now for the main function I need help on, my professor only helped me a little with part.
from Deck import Deck
from Card import Card
from Hand import Hand
def rules(playerTotal, dealerTotal):
if playerTotal > 21:
print "You busted!"
if dealerTotal == 21:
print 'To make it worse, dealer has 21.'
elif dealerTotal > 21:
print "The Dealer has busted. You win!"
elif playerTotal == 21:
print " You got 21! So you win!"
if dealerTotal == 21:
print "The Dealer also got 21. Tough Break."
elif dealerTotal == 21:
print "The Dealer got 21! Tough Break, you lose!"
else:
if playerTotal > dealerTotal:
print "You beat the Dealer! You got lucky punk."
if playerTotal == dealerTotal:
print "It is a push, no one wins!"
else:
print "Dealer wins! Better luck next time loser."
So I know I have to use the totalHand function from Hand to determine what the values are for playerTotal and dealerTotal, but everytime I try something I get this error.
Player1 = raw_input("What is your name?")
Dealer = "Dealer"
twoCards = Hand(Player1)
print twoCards.totalHand()
which prints out "none" and thats it..
If anyone can help me I would appreciated it, I'm kinda regretting my major choice as of now..
In no particular order:
Your shuffle is biased. Just use Python's random.shuffle(), it's correct and fast.
totalHand is wrong (never adds non-aces to the value), and is way too complicated because you chose to use 11 as the value of aces, and doesn't report whether a total is hard or soft (which you need for proper play). Change the value of aces to 1, and simplify:
*
def totalHand(self):
aceFound, isSoft = false, false
total = 0
for c in self.cards:
total += c.getCardValue()
if c.getCardValue() == 1:
aceFound = true
if aceFound and total < 12:
total += 10
isSoft = true
return total, isSoft
You can't base your results on just card totals. You have to play the hand in proper order:
If dealer has natural, play is over. Players with natural push,
all others lose.
Each player in turn plays his hand. Naturals are paid off and
removed, busts lose and are removed.
Dealer plays his hand. If he busts, all remaining players win,
otherwise players win/lose based on total.

Categories