BlackJack Game Main Script Trouble (Classes Already Done) - python

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.

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()

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 do I swap which function runs at the beginning of my while loop?

I have just starting learning Python and I am writing a rudimentary Blackjack game. I have got the basic stuff working but I want to add a little bit of finesse here and there. I am looking for a way in which my introduction function at the beginning of my while loop is substituted for my new_round function.
My idea was that I could have a round counter running at the top which would dictate which function would run through and if/elif statement.
Suffice it to say, it doesn't work. Firstly, I would like to know why it doesn't and secondly would like a way to do it!
import random
suits = ('Hearts', 'Diamonds', 'Spades', 'Clubs')
ranks = ('Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace')
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}
player_name = ''
playing = True
class Card:
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return f'{self.rank} of {self.suit}'
class Deck:
def __init__(self):
self.deck = []
for suit in suits:
for rank in ranks:
self.deck.append(Card(suit,rank))
def __str__(self):
deck_comp = ''
for card in self.deck:
deck_comp += '\n '+card.__str__()
return 'The deck has:' + deck_comp
def shuffle(self):
random.shuffle(self.deck)
def deal(self):
single_card = self.deck.pop()
return single_card
class Hand:
def __init__(self):
self.cards = []
self.value = 0
self.aces = 0
def add_card(self,card):
self.cards.append(card)
self.value += values[card.rank]
if card.rank == 'Ace':
self.aces += 1
def adjust_for_ace(self):
#if value of players hand is over 21 and includes an ace then the player will automatically have the ace value reduced to 1
#also track ace counter will revert to 0
while self.value > 21 and self.aces > 0:
self.value -= 10
self.aces -= 1
class Chips:
def __init__(self,total):
self.total = total
self.bet = 0
def win_bet(self):
self.total += self.bet
def lose_bet(self):
self.total -= self.bet
def take_bet(chips):
while True:
try:
player_chips.bet = int(input('How many chips would you like to bet?: '))
except ValueError:
print('\nSorry, the number of chips must be a number!')
else:
if player_chips.bet > player_chips.total:
print(f"\nSorry guy, your bet can't exceed {player_chips.total} chips.")
else:
print(f"\nYour bet of {player_chips.bet} chips has been accepted - good luck!")
break
def introduction():
global player_name
print("\nWelcome to BlackJack! Get as close to 21 as you can without busting.\n\nThe Dealer will hit up to 17, Face cards count as 10 and Aces are 1/11.")
player_name=input("The first round is about to begin, what is your name friend?: ")
def next_round():
global player_name
print("Hey ho, let's go another round!")
def chip_count():
global player_name
print(f"{player_name}, your current chip count stands at {player_chips.total}")
def play_again():
global player_name
global playing
while True:
replay = input(f"{player_name}, would you like to play another round?: ").upper()
if replay[0] == 'Y':
return True
elif replay[0] == 'N':
print(f"\nThanks for playing - you leave the table with {player_chips.total} chips.")
break
else:
print("Sorry, I don't understand what you are saying, do you want to play the next round, or not? Y or N!: ")
continue
def total():
global player_name
while True:
try:
total = int(input(f'Hello {player_name}, how many chips will you be using this game?: '))
except ValueError:
print('\nSorry, the number of chips must be a number!')
else:
return total
print(f"\nWelcome to the table - you currently have {total} chips to play with.")
def hit(deck,hand):
#run the add card function within the Hand Class with the card argument being generated by the deal function within the Deck Class.
hand.add_card(deck.deal())
hand.adjust_for_ace()
def hit_or_stand(deck,hand):
global player_name
global playing
while True:
response = input(f"{player_name}, Would you like to hit or stand?: ")
if response[0].upper() == 'H':
hit(deck,hand)
elif response[0].upper() == 'S':
print(f"{player_name} stands. It is the Dealer's turn")
playing = False
else:
print("\nI can't understand what you are saying - are you hitting or standing?!")
continue
break
def show_some(player,dealer):
print("\nDealer's Hand:")
print("<card hidden>")
print(dealer.cards[1])
print("\nPlayer's Hand: ",*player.cards, sep='\n')
print("Value of your cards: ",player.value)
def show_all(player,dealer):
print("\nDealer's Hand: ",*dealer.cards, sep='\n')
print("Dealer's Hand = ",dealer.value)
print("\nPlayer's Hand: ",*player.cards, sep='\n')
print("Player's Hand = ",player.value)
def player_busts(player,dealer,chips):
global player_name
print(f"{player_name} busts!")
chips.lose_bet()
def player_wins(player,dealer,chips):
global player_name
print(f"{player_name} wins the round!")
chips.win_bet()
def dealer_busts(player,dealer,chips):
print("Dealer busts!")
chips.win_bet()
def dealer_wins(player,dealer,chips):
print("Dealer wins!")
chips.lose_bet()
def push(player,dealer,chips):
print("You have tied with the Dealer! It's a push, your chips have been refunded.")
############################################################################################################################################################
while True:
counter = 0
if counter > 0:
next_round()
elif counter == 0:
introduction()
#Create & shuffle the deck, deal 2 cards to each player.
deck = Deck()
deck.shuffle()
player_hand = Hand()
player_hand.add_card(deck.deal())
player_hand.add_card(deck.deal())
dealer_hand = Hand()
dealer_hand.add_card(deck.deal())
dealer_hand.add_card(deck.deal())
#Set up Player's chips
player_chips = Chips(total())
#Prompt the Player for their bet
take_bet(player_chips)
#Show cards (keep one dealer card hidden)
show_some(player_hand,dealer_hand)
while playing == True:
#Prompt for player hit or stand
hit_or_stand(deck,player_hand)
#show cards (keep one dealer card hidden)
show_some(player_hand,dealer_hand)
#if player's hand exceeds 21, player busts - break loop
if player_hand.value > 21:
player_busts(player_hand,dealer_hand,player_chips)
break
#if player hasn't bust, play dealer's hand until dealer reaches 17 or busts.
if player_hand.value <= 21:
while dealer_hand.value < 17:
hit(deck,dealer_hand)
#show all cards
show_all(player_hand,dealer_hand)
#run different winning scenarios
if dealer_hand.value > 21:
dealer_busts(player_hand,dealer_hand,player_chips)
elif dealer_hand.value > player_hand.value:
dealer_wins(player_hand,dealer_hand,player_chips)
elif dealer_hand.value < player_hand.value:
player_wins(player_hand,dealer_hand,player_chips)
else:
push(player_hand,dealer_hand,player_chips)
#inform player of their current chip count.
chip_count()
counter += 1
#play another round?
if play_again() == True:
continue
else:
break
You are resetting counter to 0 at the start of every loop.
You probably meant to set it to 0 before the loop started, then have it increase every loop.
Instead of:
while True:
counter = 0
if counter > 0:
try:
counter = 0
while True:
if counter > 0:
The issue in your code is that each time you loop through your While True: loop, you are setting the variable counter back to zero.... So even though you increment counter at the end of your loop, it is then immediately set back to zero as the loop restarts.
A different way to accomplish what you are looking for would be to run your introduction() function just before your While True: loop, and then edit the final lines of your code to call the next_round() function, as such:
if play_again() == True:
next_round()
continue

Trouble giving values to deck of cards

(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.

BEGINNER: Python Value error: invalid literal for int()

Im making a simple blackjack program in python, but im getting a "ValueError: invalid literal for int() with base 10: ..." In order to get the total value of the player hands, after creating the card object, i try to get the rank of the card:
rank1 = Card.Card.getRank(card1)
heres the classs method:
def getRank(self):
if self.__rank == ('J'):
self.__rank = 10
return self.__rank
elif self.__rank == ('Q'):
self.__rank = 10
return self.__rank
elif self.__rank == ('K'):
self.__rank = 10
return self.__rank
elif self.__rank == ('A'):
self.__rank = 11
return self.__rank
else:
self.__rank = self.__rank
return int(self.__rank)`
the only time it returns the ValueError: invalid literal for int() with base 10 is if the rank is a 'Q' or 'K', it returns 10 for the 'J' and 11 for 'A'. I'm not getting why it returns an error for the 'Q' or 'K' since the code is the same for 'J' and 'A'... any help would be appreciated... if it helps, before that i had
heres the whole class
#Card class
#Class card holds ranks and suits of deck
#
TEN = 10
FOUR = 4
class Card():
#Create rank list
RANK= ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]*FOUR
#Create list with rank names
rankNames=[None, 'Ace', 'Two', 'Three', 'Four', 'Five', 'Six',
'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King']
#Create suit list
suitNames = ['CLUBS','DIAMONDS', 'HEARTS', 'SPADES']
#Takes in rank, suit to create a deck of cards
def __init__(self, rank, suit):
self.__rank = rank
self.__suit = suit
#Returns the rank of card
def getRank(self):
if self.__rank == ('J'):
print (repr(self.__rank))
self.__rank = 10
return self.__rank
elif self.__rank == ('Q'):
self.__rank = 10
print (repr(self.__rank))
return self.__rank
elif self.__rank == ('K'):
print (repr(self.__rank))
self.__rank = 10
return self.__rank
elif self.__rank == ('A'):
print (repr(self.__rank))
self.__rank = 11
return self.__rank
else:
self.rank = self.__rank
print (repr(self.__rank))
return int(self.__rank)
#Returns suit of card
def getSuit(self):
return self.__suit
#Returns number of points the card is worth
def BJVaue(self):
if self.rank < 10:
return self.rank
else:
return TEN
def __str__(self):
return "%s of %s" % ([self.__rank], [self.__suit])
Heres where i create the card objects
#Create a player hand
player = []
#Draw two cards for player add append
player.append(drawCard())
player.append(drawCard())
#Display players cards
print ("You currently have:\n" , player)
#Get the rank of the card
card1 = player[0]
card2 = player[1]
#Update players card status
print (card1)
print (card2)
#Get the total of the hand
rank1 = Card.Card.getRank(card1)
rank2 = Card.Card.getRank(card2)
#Get the ranks of players cards
playerRank = [rank1 , rank2]
#Get total of players hand
totalPlayer = getTotal(playerRank)
#Display players total
print ("Your current total is: ", totalPlayer)
the getTotal function
def getTotal(rank):
#Create and set accumulator to 0
total = 0
#for each value in the rank
for value in rank:
#add to total
total += value
#Return total
return total
hope this helps
This line isn't right:
if self.__rank == ('J' or 'Q' or 'K'):
('J' or 'Q' or 'K') evaluates to 'J', so this line just checks whether self.__rank == 'J'.
You actually want:
if self.__rank in ('J', 'Q', 'K'):
I think your first code example should work. Are you sure that you're actually running the new code? If you try to import the same module into a running Python instance it won't pick up the changes. Also, if you redefine a class, existing instances will still have the old method implementations.
You've got fairly stinky code here - bad indentation, unnecessary brackets (are those strings or tuples?), nasty mix of functional and OO, static calls to non-static methods, etc.
The initial problem, "ValueError: invalid literal for int() with base 10: ..." means you are passing int() a value which it doesn't know how to translate into an integer. The question, then, is: what is that value, and where is it coming from?
Try substituting
VALUE = {
'2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10,
'J':10, 'Q':10, 'K':10, 'A':11
}
def getValue(self):
try:
return Card.VALUE[self.__rank]
except KeyError:
print "%s is not a valid rank" % (self.__rank)
and see what you get. My guess would be that drawCard is generating rank values that Card.getValue doesn't know what to do with.
Other problems with your code:
TEN = 10
FOUR = 4
The whole point of using defined values is to provide semantic meaning and allow a single point of change; yet FOUR is no more contextually meaningful than 4, and I see no case in which changing the value of FOUR or TEN would make sense (indeed, if FOUR were ever to equal 3, it would be actively unhelpful in understanding your code). Try renaming them FACECARD_VALUE and NUMBER_OF_SUITS.
You are using "rank" to mean multiple different things: the character denoting a card and the value of a card to your hand. This will also increase confusion; try using face for one and value for the other!
You seem to be using drawCard() as a stand-alone function; how are you keeping track of what cards have already been dealt? Does it ever make sense to have, for example, two Ace of Spades cards dealt? I would suggest creating a Deck object which initializes 52 canonical cards, shuffles them, and then deck.getCard() returns a card from the list instead of creating it randomly.
See what you think of the following:
import random
class Deck():
def __init__(self):
self.cards = [Card(f,s) for f in Card.FACE for s in Card.SUIT]
self.shuffle()
def shuffle(self):
random.shuffle(self.cards)
def getCard(self):
return self.cards.pop()
class Card():
# Class static data
FACE = ('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K')
NAME = ('Ace', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King')
RANK = (11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10)
SUIT = ('Clubs','Diamonds', 'Hearts', 'Spades')
def __init__(self, face, suit):
ind = Card.FACE.index(face)
self.__face = Card.FACE[ind] # the long way around, but keeps it consistent
self.__name = Card.NAME[ind]
self.__rank = Card.RANK[ind]
ind = Card.SUIT.index(suit)
self.__suit = Card.SUIT[ind]
def getFace(self):
return self.__face
def getName(self):
return self.__name
def getRank(self):
return self.__rank
def getSuit(self):
return self.__suit
def __str__(self):
return "%s of %s" % (self.__name, self.__suit)
def __repr__(self):
return "%s%s" % (self.__face, self.__suit[:1])
class Player():
def __init__(self):
self.cards = []
def drawCard(self, deck):
self.cards.append(deck.getCard())
def drawCards(self, deck, num=2):
for i in range(num):
self.drawCard(deck)
def getRank(self):
return sum( c.getRank() for c in self.cards )
def __str__(self):
cards = ', '.join(str(c) for c in self.cards)
return "%s: %d" % (cards, self.getRank())
def __repr__(self):
return ' '.join([repr(c) for c in self.cards])
class Game():
def __init__(self):
self.deck = Deck()
self.player1 = Player()
self.player2 = Player()
def test(self):
self.player1.drawCards(self.deck, 2)
print "Player 1:", self.player1
self.player2.drawCards(self.deck, 2)
print "Player 2:", self.player2
def main():
g = Game()
g.test()
if __name__=="__main__":
main()
rank1 = Card.Card.getRank(card1)
This looks like you're trying to call the getRank as a static method. getRank is expecting an instance of itself as the first parameter. This usually means you have a Card object, but the way you call it above, you don't have an object to pass it. I'ms urprised it even lets you call it like that. That should give you an incorrect number of arguments error.
Post more code, but it seems like you have serious fundamental problems with your design.
Update:
What's this?
RANK= ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]*FOUR
Why do you need a list of 4 duplicates of your ranks?
Here is another approach to make a deck of cards
from itertools import product
card_values = (
("1", "1", 1),
("2", "2", 2),
("3", "3", 3),
("4", "4", 4),
("5", "5", 5),
("6", "6", 6),
("7", "7", 7),
("8", "8", 8),
("9", "9", 9),
("10" ,"10", 10),
("Jack", "J", 10),
("Queen", "Q", 10),
("King", "K", 10),
("Ace", "A", 11))
card_suits = ("Spades", "Clubs", "Hearts", "Diamonds")
class Card(object):
def __init__(self, name, short_name, rank, suit):
self.name = name
self.short_name = short_name
self.rank = rank
self.suit = suit
cards = []
for (name, short_name, rank), suit in product(card_values, card_suits):
cards.append(Card(name, short_name, rank, suit))
You could reduce the amount and complexity of your code by using a Python dictionary. If you did this, your getRank() function could look something like the following:
class Card(object):
RANK = {"A":1, "2":2, "3": 3, "4":4, "5": 5, "6": 6, "7":7,
"8":8, "9":9, "10":10, "J":10, "Q":10, "K":10}
def __init__(self, draw): # just for example
self.__rank = draw
def getRank(self):
self.__rank = Card.RANK[self.__rank]
return self.__rank
# ...
print Card('A').getRank()
# 1
print Card('4').getRank()
# 4
print Card('J').getRank()
# 10
print Card('K').getRank()
# 10

Categories