If-statement does not work(?) - python

I am a happy amateur who tries to create a "more or less" game. I'm not right on point allocation. My if statement is not working properly. I get no error message but everything is running in the "else". The conditions are met never, although K, Q, J, Ace randomly ... Why?
class Card(object):
totPoints = 0
VALUE = {"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}
RANKS = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
SUIT = ["Python/projekt/bilder/hearts.png", "Python/projekt/bilder/spades.png", "Python/projekt/bilder/diamond.png", "Python/projekt/bilder/clubs.png"]
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __str__(self):
rep = self.rank + self.suit
return rep
def draw(self):
bg = ImageTk.PhotoImage(Image.open(self.suit).resize((10, 10)))
cardGraph = Canvas(win, width=70, height=100, bg="White", bd=1, relief='solid', highlightthickness=2)
cardGraph.photo=bg
cardGraph.pack(side = "left", anchor=NW)
class Hand(object):
def __init__(self):
self.cards = []
def __str__ (self):
if self.cards:
rep = ""
for card in self.cards:
rep += str(card) + " "
else:
rep = "<empty>"
return rep
def clear(self):
self.cards = []
def add(self, card):
self.cards.append(card)
def give(self, card, other_hand):
self.cards.remove(card)
other_hand.add(card)
class Deck(Hand):
def populate(self):
for suit in Card.SUIT:
for rank in Card.RANKS:
self.add(Card(rank, suit))
def shuffle(self):
import random
random.shuffle(self.cards)
DrawCard = self.cards[0]
DrawCard.draw()
def deal(self, hands, per_hand = 0):
for rounds in range(per_hand):
for hand in hands:
if self.cards:
top_card = self.cards[0]
self.give(top_card, hand)
else:
print("Cant continue deck. Out of cards!!")
def setValue(self):
if self.cards[0] == "K":
Card.totPoints += 10
print Card.totPoints
elif self.cards[0] == "Q":
Card.totPoints += 10
elif self.cards[0] == "J":
Card.totPoints += 10
elif self.cards[0] == "A":
Card.totPoints += 10
else:
Card.totPoints += self.cards
print Card.totPoints

Your code never represents cards as mere strings. Instead, you are using instances of the class Card():
def populate(self):
for suit in Card.SUIT:
for rank in Card.RANKS:
self.add(Card(rank, suit))
You'll need to test against the .rank attribute instead:
def setValue(self):
if self.cards[0].rank == "K":
Card.totPoints += 10
print Card.totPoints
elif self.cards[0].rank == "Q":
Card.totPoints += 10
elif self.cards[0].rank == "J":
Card.totPoints.rank += 10
elif self.cards[0].rank == "A":
Card.totPoints += 10
else:
Card.totPoints += int(self.cards[0].rank)
Note that .rank is always a string, so you'll need to turn it into an integer when it is a number card. I've assumed that that is the goal of the else: branch, in any case.
Your code in that function can be greatly simplified:
def setValue(self):
rank = self.cards[0].rank
Card.totPoints += 10 if rank in 'KQJA' else int(rank)
Alternatively, you could just use the Class.VALUE mapping you already have:
def setValue(self):
Card.totPoints += Card.VALUE[self.cards[0].rank]

Try restructuring it so that you return after you find the value you want; that makes it less prone to confusion about the order of elifs. Also, it's easier to is 'in' tests for large numbers of values:
def setValue(self):
first_card = self.cards[0]
face_cards = ['K','Q','J','A']
if first_card in face_cards:
card.totPoints += 10
return
card.totPoints += self.cards
As an aside: this will result in a score of 10 if the first card is a face card and the total of all your cards if it's not. Is that what you want?
Lastly, It seems like you're updating the value for the card from the deck object. Perhaps you should just set the card's score in the init so you don't have to do it from the outside?

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

Simple Blackjack game: deck list becomes NoneType [duplicate]

This question already has answers here:
Why does random.shuffle return None?
(5 answers)
Closed 3 years ago.
I tired to make a simple blackjack game in Python. When executing the code, list of cards in deck (self.deck) creates problems - becomes NoneType, when it should be a list.
'''
This is a blackjack game for the project 2
'''
import random
cardsuits = ['Hearts', 'Diamonds', 'Spades', 'Clubs']
cardrank = ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
cardvalues = {'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}
class Card:
#class card has two attributes: suit and rank. asking for string will result in rank of suit response. There is a value calcluated, using cardvalues dictionary.
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.rank + ' of ' + self.suit
#def value(self):
# self.value = cardvalues[self.rank]
# #think about ace here; it can be worth 10 or 1 depending on hand
class Deck:
def __init__(self):
self.deck = []
for suit in cardsuits:
for rank in cardrank:
self.deck.append(Card(suit,rank))
def __str__(self):
deck_comp = ""
for card in self.deck:
deck_comp = deck_comp + "\n" + card.__str__()
return "Deck contains " + deck_comp
def reroll(self):
self.deck = random.shuffle(self.deck)
def take_a_card(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 = self.value + cardvalues[card.rank]
if card.rank == "Ace":
self.aces = self.aces + 1
def ace_adjust(self):
if self.value > 21 and self.aces > 0:
self.value = self.value - 10
self.aces = self.aces -1
class Funds:
def __init__(self):
self.balance= 0
self.bet = 0
def winbet(self):
self.balance = self.balance + self.bet * 2
def losebet(self):
self.bet = 0
def draw(self):
self.balance = self.balance + self.bet
self.bet = 0
def Place_a_Bet():
while True:
placebetamount = int(input(print('Select amount you want to bet.')))
if isinstance(placebetamount, int) == False:
print('Invalid bet type. You have to input a digit.')
continue
elif placebetamount > PlayerFunds.balance:
print('You tried to bet more money than you have available. You cannot bet more than: ' + PlayerFunds.balance)
continue
elif placebetamount <= 0:
print('Invaild Bet. You have to bet a positive number.')
continue
else:
PlayerFunds.balance = PlayerFunds.balance - placebetamount
PlayerFunds.bet = placebetamount
break
def hit(deck,hand):
hand.add_card(CurrentGameDeck.take_a_card())
hand.ace_adjust()
def hit_or_stand(deck, hand):
global playing # to control an upcoming while loop
Decision = input(str(print('Your Turn. Type "Hit" to get another card. Type "Stand" to move onto Dealers move')))
while True:
if Decision == "Hit":
hit(deck,hand)
elif Decision == "Stand":
playing = False
else:
print('just Hit or Stand. Other inputs are invalid')
continue
break
def CardStateGame(PlayerHand, DealerHand):
print('Dealer Shows : ' + DealerHand.cards[0] + ' out of ' + len(DealerHand.cards))
print('Dealer score is :' + DealerHand.value)
print('Your cards are ')
for card in PlayerHand.cards:
print(card)
print('and their value is: ' + PlayerHand.value)
def CardStateEndgame(PlayerHand, DealerHand):
print('Dealer value is ' + DealerHand.value + ' and his cards are: ')
for card in DealerHand.cards:
print(card)
print('Your cards are ')
for card in PlayerHand.cards:
print(card)
print('and their value is: ' + PlayerHand.value)
#end conditions
def player_bust(PlayerHand, PlayerFunds):
print('Value of your cards (' + PlayerHand.value +') exceeds 21. You lose.')
PlayerFunds.losebet()
def player_wins(PlayerFunds):
print('You won.')
PlayerFunds.winbet()
def dealer_bust(DealerHand, PlayerFunds):
print('Dealer loses, because value of his cards (' + DealerHand.value +') exceeds 21')
PlayerFunds.winbet()
def dealer_wins(PlayerFunds):
print('Dealer won.')
PlayerFunds.losebet()
def draw(PlayerFunds):
print('Both participants have same values. Its a draw')
PlayerFunds.draw()
#gameplay
print('This is a game of blackjack. You and the dealer (AI) will try to reach card value of 21, or just higher than your opponent. Scores higher than 21 will lose')
PlayerFunds = Funds()
while True:
startamount = int(input(print('Select the amount of money you enter the game with. Try to keep it plausible')))
if startamount <= 0 or isinstance(startamount, int) == False:
print('You cant play with that amount of money. try again')
continue
else:
PlayerFunds.balance = startamount
break
playing = True
while True:
CurrentGameDeck = Deck()
CurrentGameDeck.reroll()
Place_a_Bet()
DealerHand = Hand()
PlayerHand = Hand()
DealerHand.add_card(CurrentGameDeck.take_a_card())
PlayerHand.add_card(CurrentGameDeck.take_a_card())
DealerHand.add_card(CurrentGameDeck.take_a_card())
PlayerHand.add_card(CurrentGameDeck.take_a_card())
CardStateGame(PlayerHand, DealerHand)
while playing == True:
hit_or_stand(CurrentGameDeck,PlayerHand)
CardStateGame(PlayerHand, DealerHand)
if PlayerHand.value >21:
player_bust(PlayerHand, PlayerFunds)
break
if PlayerHand.value <= 21:
while DealerHand.value <17:
hit(CurrentGameDeck, DealerHand)
CardStateEndgame
if DealerHand.value > 21:
dealer_bust()
elif DealerHand.value > PlayerHand.value:
dealer_wins()
elif PlayerHand.value > DealerHand.value:
player_wins()
elif PlayerHand.value == DealerHand.value:
draw()
newgame = 0
newgame = input(print('Do you want to play again? Type Y or N'))
if newgame.lower() == 'Y' and PlayerFunds.balance >=0:
playing = True
continue
elif newgame.lower() == 'Y' and PlayerFunds.balance < 0:
print('no more funds. GG')
break
else:
print('thanks for playing')
break
I tried to use only
cardsuits = ['Hearts', 'Diamonds', 'Spades', 'Clubs']
cardrank = ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
cardvalues = {'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}
class Card:
#class card has two attributes: suit and rank. asking for string will result in rank of suit response. There is a value calcluated, using cardvalues dictionary.
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
def __str__(self):
return self.rank + ' of ' + self.suit
#def value(self):
# self.value = cardvalues[self.rank]
# #think about ace here; it can be worth 10 or 1 depending on hand
class Deck:
def __init__(self):
self.deck = []
for suit in cardsuits:
for rank in cardrank:
self.deck.append(Card(suit,rank))
def __str__(self):
deck_comp = ""
for card in self.deck:
deck_comp = deck_comp + "\n" + card.__str__()
return "Deck contains " + deck_comp
def reroll(self):
self.deck = random.shuffle(self.deck)
def take_a_card(self):
single_card = self.deck.pop()
return single_card
and then
test = Deck()
allows me to shuffle the deck, and pop a single card out of it - so other parts of the code may be a problem, but I have no idea which, where and why.
In the future you should try to slim your code down to pinpoint the problem. Since the issue was surrounding the deck you only really needed to post that class. The error you are getting is because of this function below:
def reroll(self):
self.deck = random.shuffle(self.deck)
If you take a look at the docs you will see that this function shuffles in place. Change the function to be this instead:
def reroll(self):
random.shuffle(self.deck)

class objects in list all have the same last added value

So I'm trying to learn Python,
I'm trying to make a class representing a whole deck of card.
so when creating the instance it should generate a list with cards.
The card represented with an object “Card” as well.
The problem is when I generate the cards by appending them to a list, all the items get overwritten by the last input
My code should generate 2 of Spades all the way to King of Spades. When printing it - 13 lines of King of Spades are printed.
What am I missing?
Here is my card class:
class Card:
def __init__(self, color, cvalue):
if color.lower() == "s":
self.color = "Spades"
elif color.lower() == "h":
self.color = "Hearts"
elif color.lower() == "d":
self.lower = "Diamond"
else:
self.lower = "Clubs"
if cvalue.isnumeric():
Card.value = int(cvalue)
if cvalue == '11':
Card.card_name = 'Ace'
else:
Card.card_name = cvalue
else:
Card.value = 10
if cvalue.lower() == 'j':
Card.card_name = "Jack"
elif cvalue.lower() == 'q':
Card.card_name = "Queen"
else:
Card.card_name = "King"
def __str__(self):
return f'{Card.card_name} of {self.color}'
This is the DeckOfCards class definition:
class DeckOfCards():
deck = []
def __init__(self):
for x in range(2,12):
DeckOfCards.deck.append(Card('s', str(x)))
DeckOfCards.deck.append(Card('s', 'j'))
DeckOfCards.deck.append(Card('s', 'q'))
DeckOfCards.deck.append(Card('s', 'k'))
This is the test code to show the cards
if __name__ == "__main__":
c = Card('s','11')
d = DeckOfCards()
for x in d.deck:
print(x)

I am receiving an error saying Unexpected EOF while parsing?

I am using a Book called Python programming: An introduction to computer programming and I am stuck in a programming exercise in chapter 10. It asks for a program that displays a playing card after the user inserts the value of the card and its suit. Also, I should be using 3 methods plus two constructors, here they are:
__init__(self, rank, suit):
getRank(self)
getSuit(self)
BJValue(self)
__str__(self)
However, as I run it an error is displayed.....
Here is my work:
from random import randrange
class Card:
def __init__(self, rank, suit):# This constructor creates the corresponding card according to their ranks:
self.rank = rank # "d"=diamonts, "c"=clubs, "h"=hearts, or
"s"=spades
self.suit = suit
def getRank(self):# Returns the rank of the card.
ranks = [None, "Ace", "2", "3",
"4", "5", "6", "7", "8",
"9", "King", "Queen", "Jack"]
self.rank = ranks[self.rank]
return self.rank
def getSuit(self):# Returns the suit of the card.
suits = ["diamons", "heart", "club", "spades"]
# TRY TO MAKE THIS PIECE OF CODE MORE ABSTRACT!!!!
if self.suit[0] == "d":
self.suit = suits[0]
elif self.suit[0] == "h":
self.suit = suits[1]
elif self.suit[0] == "c":
self.suit = suits[2]
elif self.suit[0] == "s":
self.suit = suits[3]
return self.suit# A suit in Blackjack means the symbol of the card.
def BJValue(self):# Returns the Blackjack value of a card.
# For example Aces count as 1 and face cards count as 10.
while 0 < self.rank <= 10:
if self.rank == "Ace":
self.rank = 1
self.bjvalue = self.rank
elif self.rank[0] == "King" or self.rank[0] == "Queen" or self.rank[0] == "Jack":
self.rank = 10
self.bjvalue = self.rank
else:
self.bjvalue = self.rank
return self.bjvalue
def __str__(self):# Returns a string that names the card. For example "Ace of Spade".
print("{0} of {1}".format(self.rank, self.suit)
I'm sorry for my Englis but is not my first language.
You're missing the close parentheses in the final print call.
You've missed to close parenthesis at the end of last line, there is one opening for print method, but not closing at the end.

Categories