We are having trouble getting the gettot() method to work in side of our game class. When it is called inside of our game as a whole it comes back with an error saying that we dont have the correct amount of inputs for the function to operate correctly. Currently the first iteration of the functions is commented out so we could get further in the project without it stopping our game every time that it runs.
this is the gettot method we are having issues with:
The purpose of this method is to get the total of the cards that a player or dealer has in their hand, if there is an ace, it decides whether or not it should be a 1 or an 11 depending on which gets it closer to 21 total points without going over.
def gettot(self,hand):
total=0
for x in self.hand:
if x==Card('H','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('D','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('S','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('C','A'):
b=total+x #changed
if b>21:
total+=1
else:
total+=11
else:
total+=x
return(total)
from random import*
#do we need to address anywhere that all face cards are worth 10?
class Card(object):
def __init__(self,suit,number):
self.number=number
self.suit=suit
def __str__(self):
return '%s %s'%(self.number,self.suit)
class DeckofCards(object):
def __init__(self,deck):
self.deck=deck
self.shuffledeck=self.shuffle()
def shuffle(self):
b=[]
count=0
while count<len(self.deck):
a=randrange(0,len(self.deck))
if a not in b:
b.append(self.deck[a])
count+=1
return(b)
def deal(self):
if len(self.shuffledeck)>0:
return(self.shuffledeck.pop(0))
else:
shuffle(self.deck) #need to refill deck
return(self.shuffledeck.pop(0))
class Player(object):
def __init__(self,name,hand,inout,money,score,bid):
self.name=name
self.hand=hand
self.inout=inout
self.money=money
self.score=score
self.bid=bid
def __str__(self):
x = self.name + ":\t"
x += "Card(s):"
for y in range(len(self.hand)):
x +=self.hand[y].face + self.hand[y].suit + " "
if (self.name != "dealer"):
x += "\t Money: $" + str(self.money)
return(x)
class Game(object):
def __init__(self,deck, player):
self.player=Player(player,[],True,100,0,0)
self.dealer=Player("Dealer",[],True,100,0,0)
self.deck=DeckofCards(deck)
self.blackjack= False
def blackjacksearch(self):
if Game.gettot(self.player.hand)==21:#changed
return True
else:
return False
def firstround(self):
#self.player.inout=True#do we need this since this is above
#self.player.hand=[]#do wee need this....
#self.dealer.hand=[]#do we need this ....
self.player.hand.append(DeckofCards.deal(self.deck))
for card in self.player.hand:
a=card
print(self.player.name + ' ,you were dealt a '+str(a))
self.dealer.hand.append(DeckofCards.deal(self.deck))
for card in self.dealer.hand:
a=card
print('The Dealer has '+str(a))
playerbid=int(input(self.player.name + ' how much would you like to bet? '))
self.player.money-=playerbid
self.player.bid=playerbid
def playturn(self): #should this be changed to inout instead of hit.....we never use inout
#for player in self.player:
# a=player
#print(str(a))
hit=input('Would you like to hit? ') #should input be in loop?
while self.player.inout==True: #and self.blackjack!=True:#changed
#print(self.player.name + ' , your hand has:' + str(self.player.hand)) #do we want to make this gettot? so it prints out the players total instead of a list....if we want it in a list we should print it with out brakets
self.player.hand.append(DeckofCards.deal(self.deck))
for card in self.player.hand:
a=card
print('The card that you just drew is: ' + str(a))
print(self.player.name + ' , your hand has:' + str([str(card) for card in self.player.hand]))
#print(Game.gettot(self.player.hand))
hit=input('Would you like to hit? ')
if hit=='yes':
(self.player.hand.append(DeckofCards.deal(self.deck)))#changed
self.player.inout==True#
else:
(self.player.hand) #changed
self.player.inout==False #changed
if self.player.blackjack==True:
print(self.player.name + " has blackjack ")
if hit=='no':
print (self.player.hand.gettot())
def playdealer(self):
while Game.gettot(self.dealer.hand)<17:#changed
self.dealer.hand.append(DeckofCards.deal(self.deck))
dealerhand=Game.gettot(self.dealer.hand) #changed
print(dealerhand)
if Game.gettot(self.dealer.hand)==21:#changed
self.dealer.blackhjack=True
dealerhand1=Game.gettot(self.dealer.hand)#changed
print(dealerhand1)
def gettot(self,hand):
total=0
for x in self.hand:
if x==Card('H','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('D','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('S','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('C','A'):
b=total+x #changed
if b>21:
total+=1
else:
total+=11
else:
total+=x
return(total)
def playgame(self):
play = "yes"
while (play.lower() == "yes"):
self.firstround()
self.playturn()
if self.player.blackjack == True:
print(self.player.name + " got BLACKJACK! ")
self.player.money += self.player.bid * 1.5
print (self.player.name + " now has " + str(self.player.money))
print("\n")
self.player.inout = False
if self.player.score > 21:
print(self.player.name + " lost with a tot of " + str(self.player.score))
self.player.money -= self.player.bid
print (self.player.name + " now has " + str(self.player.money))
print ("\n\n")
self.player.inout = False
self.playdealer()
if self.dealer.blackjack == True:
print("Dealer got blackjack, dealer wins\n")
self.player.money -= self.player.bid
print("Round\n")
print("\t",self.dealer)
print("\t",self.player)
print("\t Dealer has " + str(self.dealer.score) + ", " + self.player.name + " has " + str(self.player.score))
elif self.player.inout == True:
print("Round\n")
print("\t",self.dealer)
print("\t",self.player)
print("\n\t Dealer has " + str(self.dealer.score) + ", " + self.player.name + " has " + str(self.player.score))
if self.dealer.score > 21:
print("\t Dealer lost with a total of " + str(self.dealer.score))
self.player.money += self.player.bid
print(self.player.name + " now has " + str(self.player.money))
elif self.player.score > self.dealer.score:
print("\t" +self.player.name + " won with a total of " + str(self.player.score))
self.player.money += self.player.bid
print("\t"+self.player.name + " now has " + str(self.player.money))
else:
print("\t Dealer won with a total of " + str(self.dealer.score))
self.player.money -= self.player.bid
print("\t"+self.player.name + " now has " + str(self.player.money))
else:
print("Round")
print("\t",self.dealer)
print("\t",self.player)
if self.player.blackjack == False:
print("\t "+ self.player.name + " lost" )
else:
print("\t "+self.player.name + " Won!")
if self.player.money <= 0:
print(self.player.name + " out of money - out of game ")
play = "no"
else:
play = input("\nAnother round? ")
print("\n\n")
print("\nGame over. ")
print(self.player.name + " ended with " + str(self.player.money) + " dollars.\n")
print("Thanks for playing. Come back soon!")
ls= [Card('H','A'),Card('H','2'),Card('H','3'),Card('H','4'),Card('H','5'),Card('H','6'),Card('H','7'),Card('H','8'),Card('H','9'),Card('H','10'),
Card('H','J'),Card('H','Q'),Card('H','K'),
Card('S','A'),Card('S','2'),Card('S','3'),Card('S','4'),Card('S','5'),
Card('S','6'),Card('S','7'),Card('S','8'),Card('S','9'),Card('S','10'),
Card('S','J'),Card('S','Q'),Card('S','K'),
Card('C','A'),Card('C','2'),Card('C','3'),Card('C','4'),Card('C','5'),
Card('C','6'),Card('C','7'),Card('C','8'),Card('C','9'),Card('C','10'),
Card('C','J'),Card('C','Q'),Card('C','K'),
Card('D','A'),Card('D','2'),Card('D','3'),Card('D','4'),Card('D','5'),
Card('D','6'),Card('D','7'),Card('D','8'),Card('D','9'),Card('D','10'),
Card('D','J'),Card('D','Q'),Card('D','K')]
def main():
x = input("Player's name? ")
blackjack = Game(ls,x)
blackjack.playgame()
main()
TL;DR but one thing I noticed is this: x==Card('H','A').
This won’t work unless you define your Card type to handle equality comparisons in a useful way. By default it will check if they are both the same objects, and as you create a new card, it won’t be the same object as x.
class Card(object):
# ...
def __eq__ (self, other):
return self.number == other.number and self.suit == other.suit
Also, this: b=total+x. If x is a Card object, how do you imagine it being added to a number? You have to define this, or do b = total + x.number instead.
Another thing is that you define gettot to take a hand parameter, but in the function, you iterate over self.hand. So any other hand you pass to the function is quietly ignored and self.hand is used instead.
Also this:
def blackjacksearch(self):
if Game.gettot(self.player.hand)==21:
# ...
This method belongs to the Game type; and it’s an instance method (taking a self parameter). But you actually call it as a static method from the Game type not an instance. It should be something like self.gettot() instead (you can leave out the parameter as per above).
You do the same at some other places too, trying to call instance methods by using TypeName.method. You need to have objects you call them on.
I think you can make your gettot method a lot shorter too:
def gettot(self,hand):
total=0
for x in self.hand:
if x.number == 'A':
if total + 11 > 21:
total += 1
else:
total += 11
elif x.number == 'J' or x.number == 'Q' or x.number == 'K':
pass # what to do with these?
else:
total += x.number
return(total)
Rewriting some parts of your code:
class Card (object):
def __init__ (self, suit, number):
self.suit = suit
self.number = number
def getValue (self):
if self.number in ('J', 'Q', 'K'):
return 10
elif self.number == 'A':
return 11
else
return int(self.number)
def isAce (self):
return self.number == 'A'
def __eq__ (self, other):
return self.suit == other.suit and self.number == other.number
def __str__ (self):
return '%s %s' % (self.number,self.suit)
class DeckOfCards (object):
def __init__ (self, deck):
self.fullDeck = deck
self.shuffle()
def shuffle (self):
self.deck = self.fullDeck[:] # copy the full deck
random.shuffle(self.deck)
def deal (self):
if not len(self.deck): # need to refill deck
self.shuffle()
return self.deck.pop(0)
ls = []
for suit in ('H', 'S', 'C', 'D'):
for number in ('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'):
ls.append(Card(suit, number))
Your gettot method should belong to a player, and would look like this:
def gettot(self):
total = 0
for card in self.hand:
if card.isAce() and total > 10:
total += 1
else:
total += card.getValue()
return total
You define gettot() to take two arguments: self, and hand. Then you never use hand, and when you call the function you only pass one argument (self.dealer.hand).
Eliminate the self argument (which makes no sense anyway, since it's a function defined outside of a class), and replace the for x in self.hand line with for x in hand. Even better, make the function a method of the Player object.
There are numerous problems
I would add a function to Card that asks if it is an Ace. That will work better then constructing a bunch and seeing if they are equal.
You are using == instead of = for some of your assignments. == is for comparison. = is for assignment.
don't say inout == True just say inout (since inout is a bool already)
you keep poping off the deck. When you run out you shuffle it again, but at this point it has nothing in it.
at the top of gettot you are referencing self.hand, but self doesnt have a hand it should just be hand as it is passed into gettot.
player.blackjack is never defined but I would add a check there for if gettot == 21, and move gettot to a modual function for now
self.player.hand.gettot() should be gettot(self.player.hand)
you are total+=x where total is an int and x is a Card, you cant add those unless you define how to add an int to a Card. I would just add to Card a get_value function for now to get the face value. (you could handle face cards being value of 10 here too) then use total += x.get_value()
you also want to adjust for aces at the end of gettot, otherwise you don't know if you are going to be over 21. ie. what happends if the first card in your hand is an ace?
example:
class Card(object):
def __init__(self,suit,number):
self.number=number
self.suit=suit
def __str__(self):
return '%s %s'%(self.number,self.suit)
def get_value(self):
if self.number == 'A':
return 11
if self.number in 'JQK':
return 10
return int(self.number)
def is_ace(self):
return self.number == 'A'
def gettot(hand):
total = 0
aces = 0
for x in hand:
if x.is_ace():
aces += 1
total += x.get_value()
while aces and total > 21:
aces -= 1
total -= 10
return total
That should get you started, just keep debugging
Related
import random
from time import sleep
def wait():
#sleep(0.5)
print()
p1_discards = []
p2_discards = []
p1_card = []
p2_card = []
class Card():
def __init__(self, value, name, suit):
self.value = value
self.name = name
self.suit = suit
def __lt__(self, other):
return self.value < other.value
def __gt__(self, other):
return self.value > other.value
def __eq__(self, other):
return self.value == other.value
def __str__(self):
return f'{self.name} of {self.suit}'
def create_deck():
deck = []
suits = ("Clubs","Spades","Hearts","Diamonds")
ranks = ("2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace")
for s in suits:
for i,r in enumerate(ranks):
deck.append(Card(i+1,r,s))
return deck
def find_winner(card1, card2):
if card1 > card2:
p1_discards.append(card2)
p1_discards.append(card1)
return p1_name
if card1 < card2:
p2_discards.append(card1)
p2_discards.append(card2)
return p2_name
else:
p1_discards.append(card1)
p2_discards.append(card2)
return "No one wins"
def main():
global p1_name, p2_name
p1_name = input("Enter player one's name: ")
p2_name = input("Enter player two's name: ")
deck = create_deck()
random.shuffle(deck)
while len(deck) > 0:
p1_card.append(deck.pop())
p1_draw = p1_card.pop()
p2_card.append(deck.pop())
p2_draw = p2_card.pop()
winner = find_winner(p1_draw, p2_draw)
print(f"{p1_name} draws a {p1_draw}")
print(f"{p2_name} draws a {p2_draw}")
print(f"{winner} wins")
input("Press enter to play again")
print('test1')
wait()
while len(p1_discards) > 1 and len(p2_discards) > 1:
if len(p1_discards) == 0:
print(f"{p1_name} has no cards left!")
if len(p2_discards) == 0:
print(f"{p2_name} has no cards left!")
print('test2')
p1_card.append(p1_discards.pop())
p1_draw = p1_card.pop()
p2_card.append(p2_discards.pop())
p2_draw = p2_card.pop()
winner = find_winner(p1_draw, p2_draw)
print(f"{p1_name} draws a {p1_draw}")
print(f"{p2_name} draws a {p2_draw}")
print(f"{winner} wins")
input("Press enter to play again")
wait()
if __name__ == '__main__':
main()
In the second while loop, the same card gets shown to the player over and over again. I'm not sure why this is the case and I would like help. The first while loop goes by without problems, but when the code reaches the second while loop, it starts to print the same thing over and over. I have used print commmands to ensure that the issue lies within only the second while loop, not the first.
I tried to make new variables and lists, but nothing worked and it just kept printing the same thing over and over without fixing anything.
how would I solve this problem? The program is supposed to remove all pairs from your hand at the beginning but it is not working. This is what it outputs at the moment:
Hello. I am Robot and I distribute the cards.
Your hand is:
2♠ 5♡ Q♠ Q♡ 4♡ J♢ 2♣ J♠ K♢ 8♢ 10♠ A♣ 5♣ 3♣ 6♣ 4♢ 7♣ 9♢ 2♢ J♡ A♢ 8♠ 10♣ 6♢ 10♡
Don't worry, I cannot see your cards or their order.
Now discard all pairs in your hand. I will do it too.
Press Enter to continue.
************************************************************
Your turn.
Your hand is:
9♢ J♡ 3♣ K♢ 10♠ 2♢ 10♣ 10♡ 7♣
There is not supposed to be two 10s in your hand. This is the code:
# vieux garcon card game.
import random
def wait_for_player():
try:
input("Press Enter to continue. ")
except SyntaxError:
pass
def prepare_pack():
pack = []
colors = ['♠', '♡', '♢', '♣']
value = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
for val in value:
for color in colors:
pack.append(val + color)
pack.remove('J♣')
return pack
def shuffle_pack(p):
random.shuffle(p)
def give_cards(p):
giver = []
other = []
loop = 0
for i in p:
if (loop % 2) == 0:
giver.append(i)
else:
other.append(i)
loop += 1
return (giver, other)
def remove_pairs(l):
colors = ['♠', '♡', '♢', '♣']
result = []
for crt in l:
if crt[1] + crt[0] == '10':
nbr = '10'
else:
nbr = crt[0]
for i in colors:
find = False
if nbr + i in result:
find = True
result.remove(nbr + i)
break
if find == False:
result.append(crt)
random.shuffle(result)
return result
def show_cards(p):
for i in p:
print(i, end = " ")
print()
def enter_valid_position(n):
enter = int(input('Please enter a number from 1 to'+ str(n) +": ")) - 1
while enter not in range(0, n):
enter = int(input('Invalid position. Please enter a number from 1 to ' + str(n) +": ")) - 1
return enter
def play():
p = prepare_pack()
shuffle_pack(p)
tmp = give_cards(p)
giver = tmp[0]
human = tmp[1]
print("Hello. I am Robot and I distribute the cards.")
print("Your hand is:")
show_cards(human)
print("Don't worry, I cannot see your cards or their order.")
print(
"Now discard all pairs in your hand. I will do it too."
)
wait_for_player()
giver = remove_pairs(giver)
human = remove_pairs(human)
#Instance = 1, human's turn, instance = 2, robot's turn
instance = 1
while instance in range(1,2):
if instance == 1:
print('*' * 60)
print('Your turn.')
print('Your hand is: ')
show_cards(human)
print("I have ", len(giver), "cards. If 1 is the position of my first card and ")
print(len(giver), "is the position of my last card, which card do you want?")
entry = enter_valid_position(len(giver))
print("You asked for my card number ", entry+1, ".")
print("There it is. It is a ", giver[entry])
print("With ", giver[entry]," added, your hand is:")
human.append(giver[entry])
giver.remove(giver[entry])
show_cards(human)
human=remove_pairs(human)
if len(human) == 0:
print("I finished all the cards.")
win = True
break
print("After discarding all pairs and shuffling the cards, your hand is:")
show_cards(human)
wait_for_player()
instance = 2
pass
if instance == 2:
print('*' * 60)
print('My turn.')
take_card = random.randint(0, len(human) - 1)
giver.append(human[take_card])
human.remove(human[take_card])
print("I took your card number ", take_card+1,".")
giver=remove_pairs(giver)
if len(giver)==0:
print("I finished all the cards.")
win = False
break
wait_for_player()
instance = 1
pass
if win == True:
print("Congratulations! You, Human, have won.")
else:
print("You lost! Me, Robot, have won.")
# main
play()
What should I do? My program does remove pairs later on in the game, but not at the beginning.
I found my error.
for crt in l:
if crt[1] + crt[0] == '10':
nbr = '10'
I flipped the positions of the 1 and 0. it was checking for 01 and not 10. It was supposed to be:
for crt in l:
if crt[0] + crt[1] == '10':
nbr = '10'
Sorry for the inconvience.
I have the following code and cant seem to realized why I get this error: Traceback (most recent call last):
card_ranks = [c.rank for c in cards[i:i+5]]
AttributeError: 'str' object has no attribute 'rank'
Here's the code:
import random
import logging
from collections import OrderedDict
from const import __version__, suits, ranks, POS_TOP, POS_BOTTOM
logger = logging.getLogger(__name__)
def f_list(lst, sep=','):
return sep.join([str(x) for x in lst])
def f_lists(lst, sep=' / '):
return f_list(map(f_list, lst), sep)
class Card(object):
"""Represents a single french-design card with it's rank and suit.
Cards can be compared and ordered by rank. A card, relative to
a card of the same rank but different suit, is compared as neither
higher, lower nor equal.
:param rank: Either the rank (one of 'A', 'K', 'Q', 'J', 'T', '9', ... '2')
or rank and suit together (e.g. 'AS', '8H', etc.)
:type rank: str
:param suit: The suit, if not given as one string with rank
(one of 'S', 'H', 'C', 'D' for spade, heart, club or diamond)
:type suit: str
:raises: ValueError
"""
def __init__(self, rank, suit=None):
if suit is None:
suit = rank[1]
rank = rank[0]
if rank not in ranks:
raise ValueError('Card(): Invalid rank')
if suit not in suits:
raise ValueError('Card(): Invalid suit')
self.rank = rank
self.suit = suit
#classmethod
def card_list(cls, *args):
"""Create a list of new cards.
Each argument should describe one card with rank and suit together.
:param args: One or more cards.
:type rank: str
:returns: List of new cards, one for each input parameter.
:rtype: list of :class:`pokercards.cards.Card` objects
:raises: ValueError
"""
lst = []
for c in args:
lst.append(cls(c))
return lst
def __str__(self):
return self.rank + self.suit
def __repr__(self):
return 'Card(%s, %s)' % (self.rank, self.suit)
def __hash__(self):
return (ord(self.rank) << 8) + ord(self.suit)
def __eq__(self, obj):
return self.rank == obj.rank and self.suit == obj.suit
def __ne__(self, obj):
return self.rank != obj.rank or self.suit != obj.suit
def __lt__(self, obj):
return ranks.index(self.rank) > ranks.index(obj.rank)
def __gt__(self, obj):
return ranks.index(self.rank) < ranks.index(obj.rank)
def __le__(self, obj):
return ranks.index(self.rank) >= ranks.index(obj.rank)
def __ge__(self, obj):
return ranks.index(self.rank) <= ranks.index(obj.rank)
class Deck(object):
"""Represents a single deck of 52 :class:`card.Card` objects.
The deck could be imagined face down on a table. All internal lists
represent the cards in order from bottom up. So dealing the top
card means poping last item from the list.
"""
def __init__(self):
self.popped = []
self.discarded = []
self.active = []
for s in suits:
for r in ranks:
self.active.append(Card(r, s))
def shuffle(self):
"""Shuffle the deck."""
random.shuffle(self.active)
def pop(self):
"""Deal the top card from the deck.
:returns: :class:`pokercards.cards.Card` instance
"""
card = self.active.pop()
self.popped.append(card)
return card
def discard(self):
card = self.active.pop()
self.discarded.append(card)
def return_cards(self, cards, pos = POS_BOTTOM):
if pos not in (POS_BOTTOM, POS_TOP):
raise Exception('Deck.return_cards(): invalid pos parameter')
for card in cards[:]:
if card in self.discarded:
self.discarded.remove(card)
elif card in self.popped:
self.popped.remove(card)
else:
raise Exception('Deck.return_cards(): card not among removed cards')
if pos == POS_BOTTOM:
self.active[0:0] = [card]
else:
self.active.append(card)
def return_discarded(self, pos = POS_BOTTOM):
self.return_cards(self.discarded, pos)
def return_popped(self, pos = POS_BOTTOM):
self.return_cards(self.popped, pos)
def return_all(self, pos = POS_BOTTOM):
self.return_popped()
self.return_discarded()
def stats(self):
return (len(self.active), len(self.popped), len(self.discarded))
def __str__(self):
return '[%s]' % ' '.join((str(card) for card in self.active))
def __repr__(self):
return 'Deck(%s)' % self.__str__()
class PokerHand(object):
"""Compute the best hand from given cards, implementing traditional
"high" poker hand ranks.
The hand object can be given more than five cards (as in Texas
Hold'em or similar variants) and the evaluation will pick the best
hand.
Evaluated :class:`pokercards.cards.PokerHand` objects are
compared and sorted by the rank of the hand.
.. attribute:: cards
List of :class:`pokercards.cards.Card` objects to make the hand
from. The :meth:`pokercards.cards.PokerHand.evaluate` method
should be called after manual update to re-evaluate the updated
hand.
Following attributes are available after evaluating the hand.
.. attribute:: hand_rank
Readonly rank of the hand (0 = high card to 8 = straight flush)
.. attribute:: hand_cards
Readonly list of cards which complete the rank.
.. attribute:: kickers
Readonly list of extra cards which can break a tie.
:param cards: List of :class:`pokercards.cards.Card` objects.
:param evaluate: Evaluate the hand when creating.
:type evaluate: bool
"""
def __init__(self, cards, evaluate=True):
cards.sort(reverse=True)
self.cards = cards
if evaluate:
self.evaluate()
def evaluate(self):
"""Evaluate the rank of the hand.
Should be called either implicitly at start by leaving
parameter ``evaluate`` True when creating the hand or
explicitly by calling this method later, e.g. after changing
the :attr:`cards` attribute manually.
"""
self._eval_hand_rank()
self._fill_kickers()
def _by_rank(self, cards=None):
if cards is None:
cards = self.cards
ranked = OrderedDict()
for card in cards:
if card.rank in ranked:
ranked[card.rank].append(card)
else:
ranked[card.rank] = [card]
return ranked
def _by_suit(self, cards=None):
if cards is None:
cards = self.cards
suited = OrderedDict()
for card in cards:
if card.suit in suited:
suited[card.suit].append(card)
else:
suited[card.suit] = [card]
return suited
def _find_flushes(self, cards=None):
if cards is None:
cards = self.cards
flushes = []
for cards in self._by_suit(cards).values():
l = len(cards)
if l >= 5:
for i in xrange(0, l - 4):
flushes.append(cards[i:i+5])
return flushes
def _find_straights(self, cards=None):
if cards is None:
cards = self.cards
straights = []
for i in xrange(0, len(cards) - 4):
card_ranks = [c.rank for c in cards[i:i+5]]
j = ranks.index(card_ranks[0])
if card_ranks == ranks[j:j+5]:
straights.append(cards[i:i+5])
return straights
def _fill_kickers(self):
hand_count = len(self.hand_cards)
kicker_count = 5 - hand_count
if kicker_count > 0:
kickers = self.cards[:]
for card in self.hand_cards:
kickers.remove(card)
self.kickers = kickers[:kicker_count]
else:
self.kickers = []
logger.debug("kickers: %s", f_list(self.kickers))
logger.debug("--- -------------- ---")
def _eval_hand_rank(self):
logger.debug("--- Evaluating %s ---", f_list(self.cards))
straights = self._find_straights()
if straights: logger.debug( "straights: %s", f_lists(straights))
flushes = self._find_flushes()
if flushes: logger.debug("flushes: %s", f_lists(flushes))
pairs = []
threes = []
fours = []
for cards in self._by_rank().values():
l = len(cards)
if l >= 4:
fours.append(cards[0:4])
elif l == 3:
threes.append(cards)
elif l == 2:
pairs.append(cards)
if pairs: logger.debug("pairs: %s", f_lists(pairs))
if threes: logger.debug("threes: %s", f_lists(threes))
if fours: logger.debug("fours: %s", f_lists(fours))
# straight flush
for cards in straights:
if cards in flushes:
self.hand_rank = 8
self.hand_cards = cards
logger.debug("* straight flush: %s", f_list(self.hand_cards))
return
# four of a kind
if len(fours) > 0:
self.hand_rank = 7
self.hand_cards = fours[0]
logger.debug("* four of a kind: %s", f_list(self.hand_cards))
return
# full house
if len(threes) > 1:
self.hand_rank = 6
self.hand_cards = threes[0] + threes[1][:2]
logger.debug("* full house: %s", f_list(self.hand_cards))
return
elif len(threes) == 1 and len(pairs) > 0:
self.hand_rank = 6
self.hand_cards = threes[0] + pairs[0]
logger.debug("* full house: %s", f_list(self.hand_cards))
return
# flush
if len(flushes) > 0:
self.hand_rank = 5
self.hand_cards = flushes[0]
logger.debug("* flush: %s", f_list(self.hand_cards))
return
# straight
if len(straights) > 0:
self.hand_rank = 4
self.hand_cards = straights[0]
logger.debug("* straight: %s", f_list(self.hand_cards))
return
# three of a kind
if len(threes) > 0:
self.hand_rank = 3
self.hand_cards = threes[0]
logger.debug("* three of a kind: %s", f_list(self.hand_cards))
return
# two pair
if len(pairs) > 1:
self.hand_rank = 2
self.hand_cards = pairs[0] + pairs[1]
logger.debug("* two pairs: %s", f_list(self.hand_cards))
return
# one pair
if len(pairs) == 1:
self.hand_rank = 1
self.hand_cards = pairs[0];
logger.debug("* two of a kind: %s", f_list(self.hand_cards))
return
# high card
self.hand_rank = 0
self.hand_cards = [self.cards[0]]
logger.debug("* high card: %s", f_list(self.hand_cards))
def __str__(self):
return '[%s]' % f_list(self.cards)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self.__str__())
def __cmp__(self, other):
if self.hand_rank > other.hand_rank:
return 1
elif self.hand_rank < other.hand_rank:
return -1
else:
# same rank
for c1, c2 in zip(self.hand_cards, other.hand_cards):
if c1 > c2:
return 1
elif c1 < c2:
return -1
else:
# same cards, check kickers
for c1, c2 in zip(self.kickers, other.kickers):
if c1 > c2:
return 1
elif c1 < c2:
return -1
# really, a tie
return 0
deck = Deck()
deck.shuffle()
player = []
computer = []
cmoney = 500
money = 500
pot = 0
for i in range(5):
card = deck.pop()
player.append(str(card))
player.sort()
for i in range(5):
card = deck.pop()
computer.append(str(card))
computer.sort()
pot += 10
money -= 5
cmoney -= 5
print "All players have anted $5."
print "Your Hand:", player
print "Your Money: $" + str(money)
print "Pot: $" + str(pot)
discard = []
ask = raw_input("Bet or check? ")
if ask.lower() == "bet":
ask2 = int(raw_input("How much? "))
if ask2 > money:
print "You don't have that much money!"
else:
money -= ask2
cmoney -= ask2
pot += ask2 * 2
print("Pot: $" + str(pot))
ui = raw_input("Do you want to discard some cards? ")
if ui.lower() == "yes":
ui2 = int(raw_input("How many? "))
for i in range(ui2):
ui3 = raw_input("Card " + str(i + 1) + ": ")
discard.append(ui3)
player.pop()
for i in range(ui2):
card = deck.pop()
player.append(str(card))
print "Your Hand:", player
print "Your Money: $" + str(money)
ask3 = raw_input("Bet or check? ")
if ask3.lower() == "bet":
ask4 = int(raw_input("How much? "))
if ask4 > money:
print "You don't have that much money!"
else:
money -= ask4
pot += ask4
pval = PokerHand(player, True)
cval = PokerHand(computer, True)
if pval > cval:
print "YOU WIN!"
money += pot
pot = 0
else:
print "YOU LOSE!"
cmoney += pot
pot = 0
print "Pot: $" + str(pot)
print "Your Hand:", player
print "Computer\'s Hand:", computer
You are constructing the PokerHand with an array of strings, not an array of cards. The code is here:
for i in range(5):
card = deck.pop()
player.append(str(card))
player.sort()
for i in range(5):
card = deck.pop()
computer.append(str(card))
computer.sort()
Instead of str(card), try just using append(card). Hopefully that should work, unless you use the string elsewhere.
I cannot figure it out how to end this loop :(
import random
class Enemy:
life = 300
print ('Player 1 your life is ' + str(life) + ' hp' )
def bonusdmg(self):
bondmg=random.randrange(40,51)
print('congratz u made ' + str(bondmg)+' bonus dmg')
self.life-=bondmg
def attack(self):
ad1=random.randrange(50,81)
print(str(ad1) + 'dmg')
print('ouch')
self.life -=ad1
def attack2(self):
ad2=random.randrange(60,90)
print(str(ad2) + 'dmg')
print('arghhh')
self.life -=ad2
def attack3(self):
ad3=random.randrange(100,111)
print(str(ad3) + 'dmg')
print('tsshaaah')
self.life -=ad3
def heal(self):
hp=random.randrange(40,51)
print ('No more potions')
self.life +=hp
print(str(hp) + ' hp have been restored')
def checkLife(self):
if self.life <=0:
print('Your enemy is dead')
else:
print(str(self.life) + "hp life left")
class Enemy2:
life = 300
print ('Player 2 your life is ' + str(life) + ' hp' )
def bonusdmg(self):
bondmg=random.randrange(40,51)
print('congratz u made ' + str(bondmg)+' bonus dmg')
self.life-=bondmg
def attack(self):
ad1=random.randrange(50,81)
print(str(ad1) + 'dmg')
print('ouch')
self.life -=ad1
def attack2(self):
ad2=random.randrange(60,90)
print(str(ad2) + 'dmg')
print('arghhh')
self.life -=ad2
def attack3(self):
ad3=random.randrange(100,111)
print(str(ad3) + 'dmg')
print('tsshaaah')
self.life -=ad3
def heal(self):
hp=random.randrange(40,51)
print ('No more potions')
self.life +=hp
print(str(hp) + ' hp have been restored')
def checkLife(self):
if self.life <=0:
print('Your enemy is dead')
else:
print(str(self.life) + "hp life left")
enemy2 = Enemy2()
enemy1 = Enemy()
while 1:
turn = 1
if turn ==1:
while 1:
print('Player 1 is your turn !')
bonus=str(random.randrange(1,6))
player_move=input('Player1 choose your attack !')
if player_move =='a':
enemy1.attack()
enemy1.checkLife()
turn +=1
break
if player_move =='s':
enemy1.attack2()
enemy1.checkLife()
turn +=1
break
if player_move == 'd':
enemy1.attack3()
enemy1.checkLife()
turn +=1
break
if enemy1.life <=0:
break
if bonus=='2':
enemy1.bonusdmg()
if turn ==2:
while 1:
print('Player 2 is your turn !')
bonus=str(random.randrange(1,6))
player_move=input('Player2 choose your attack !')
if player_move =='a':
enemy1.attack()
enemy1.checkLife()
turn -=1
break
if player_move =='s':
enemy1.attack2()
enemy1.checkLife()
turn -= 1
break
if player_move == 'd':
enemy1.attack3()
enemy1.checkLife()
turn -=1
break
if enemy1.life <=0:
break
if bonus=='2':
enemy1.bonusdmg()
You can try breaking the loop once a certain condition is satisfied. For example, try it like this:
# in while loop
if condition_is_true:
break
Otherwise, you'll need to specify a condition within the declaration of your while loop. I suggest this technique because it does not close your program. It can execute the code below your loop as well, if you have any.
while condition_is_true:
I cleaned up a lot of this, some notes at bottom.
import random
class Player:
def __init__(self, num):
self.num = num
self.life = 300
print('%s your life is %d hp' % (self, self.life))
self.enemy = None
def __str__(self):
return "Player %d" % self.num
def bonusdmg(self):
bondmg=random.randrange(40,51)
print('congratz u made %d bonus dmg' % bondmg)
self.deal_damage(bondmg)
def attack(self):
ad1=random.randrange(50,81)
print('You attack for %d dmg -- ouch' % ad1)
self.deal_damage(ad1)
def attack2(self):
ad2=random.randrange(60,90)
print('You attack for %d dmg -- arghhh' % ad2)
self.deal_damage(ad2)
def attack3(self):
ad3=random.randrange(100,111)
print('You attack for %d dmg -- tsshaaah' % ad3)
self.deal_damage(ad3)
def heal(self):
hp=random.randrange(40,51)
print ('No more potions')
self.life += hp
print('%d hp have been restored' % hp)
def checkEnemyLife(self):
if self.enemy.life <=0:
return "%s is dead" % self.enemy
else:
return "%s has %d hp left" % (self.enemy, self.enemy.life)
# New
def take_damage(self, amt):
print('%s takes %d dmg' % (self, amt))
self.life -= amt
# New
def deal_damage(self, amt):
self.enemy.take_damage(amt)
print(self.checkEnemyLife())
# New
def handle_action(self, player_move):
if player_move =='a': self.attack()
if player_move =='s': self.attack2()
if player_move == 'd': self.attack3()
bonus=str(random.randrange(1,6))
if bonus==2: # Fixed this
self.bonusdmg()
# New
def turn(self):
print("")
player_move = raw_input("%s it's your turn! Choose your attack! " % self)
self.handle_action(player_move)
# New
def won(self):
return (self.enemy.life <= 0)
player1 = Player(1)
player2 = Player(2)
player1.enemy = player2
player2.enemy = player1
# Enemy class
# life as attribute
# raw_input
# string formatting
turn = 1 # Moved this
run_game = True
while run_game:
if turn == 1:
player1.turn()
if player1.won():
print("Player 1 wins")
run_game = False
break
turn += 1
elif turn == 2:
player2.turn()
if player2.won():
print("Player 2 wins")
run_game = False
break
turn -= 1
Made both Enemy classes a single Player class, player1 and player2 are instances of the same class.
Gave each Player instance a reference to their enemy, so they don't deal damage to themselves anymore.
Created a bunch of methods that help stream line your main game loop
Improved printing using string formatting (%) operator.
Changed input to the safer raw_input
life is now an instance attribute instead of a class attribute
A of other, smaller changes
Although your code has many mistakes,I think the infinite loop you are referring is in the inner loop
turn = 1
if turn ==1:
while 1: #this cause a problem, how are you going to exit this loop?
#rest of the code
You never change turn = 2 therefore the if statement turn == 1 is always True. You need to find a place to make turn = 2 so the second player can move. This however will not solve all your issues.
We are supposed to use the code below to print out the parameters listed in it, currently however we are unable to do so and are using a round about method. This is supposed to print out things instead of what we print out in the Game class in the playturn function
def __str__(self):
x = self.name + ":\t"
x += "Card(s):"
for y in range(len(self.hand)):
x +=self.hand[y].face + self.hand[y].suit + " "
if (self.name != "dealer"):
x += "\t Money: $" + str(self.money)
return(x)
Here is our actual code, if you also see any other issues your input would be greatly appreciated
from random import*
#do we need to address anywhere that all face cards are worth 10?
class Card(object):
def __init__(self,suit,number):
self.number=number
self.suit=suit
def __str__(self):
return '%s'%(self.number)
class DeckofCards(object):
def __init__(self,deck):
self.deck=deck
self.shuffledeck=self.shuffle()
def shuffle(self):
b=[]
count=0
while count<len(self.deck):
a=randrange(0,len(self.deck))
if a not in b:
b.append(self.deck[a])
count+=1
return(b)
def deal(self):
if len(self.shuffledeck)>0:
return(self.shuffledeck.pop(0))
else:
shuffle(self)
return(self.shuffledeck.pop(0))
class Player(object):
def __init__(self,name,hand,inout,money,score,bid):
self.name=name
self.hand=hand
self.inout=inout
self.money=money
self.score=score
self.bid=bid
def __str__(self):
x = self.name + ":\t"
x += "Card(s):"
for y in range(len(self.hand)):
x +=self.hand[y].face + self.hand[y].suit + " "
if (self.name != "dealer"):
x += "\t Money: $" + str(self.money)
return(x)
class Game(object):
def __init__(self,deck, player):
self.player=Player(player,[],True,100,0,0)
self.dealer=Player("Dealer",[],True,100,0,0)
self.deck=DeckofCards(deck)
self.blackjack= False
def blackjacksearch(self):
if Game.gettot(self.player.hand)==21:#changed
return True
else:
return False
def firstround(self):
#self.player.inout=True#do we need this since this is above
#self.player.hand=[]#do wee need this....
#self.dealer.hand=[]#do we need this ....
self.player.hand.append(DeckofCards.deal(self.deck))
for card in self.player.hand:
a=card
print(self.player.name + ' ,you were dealt a '+str(a))
self.dealer.hand.append(DeckofCards.deal(self.deck))
for card in self.dealer.hand:
a=card
print('The Dealer has '+str(a))
playerbid=int(input(self.player.name + ' how much would you like to bet? '))
self.player.money-=playerbid
self.player.bid=playerbid
def playturn(self): #should this be changed to inout instead of hit.....we never use inout
#for player in self.player:
# a=player
#print(str(a))
hit=input('Would you like to hit? ') #should input be in loop?
while self.player.inout==True: #and self.blackjack!=True:#changed
print(self.player.name + ' , your hand has:' + str(self.player.hand)) #do we want to make this gettot? so it prints out the players total instead of a list....if we want it in a list we should print it with out brakets
self.player.hand.append(DeckofCards.deal(self.deck))
for card in self.player.hand:
a=card
print('The card that you just drew is: ' + str(a))
#print(Game.gettot(self.player.hand))
hit=input('Would you like to hit? ')
if hit=='yes':
(self.player.hand.append(DeckofCards.deal(self.deck)))#changed
self.player.inout==True#
else:
(self.player.hand) #changed
self.player.inout==False #changed
if self.player.blackjack==True:
print(self.player.name + " has blackjack ")
if hit=='no':
print (self.player.hand.gettot())
def playdealer(self):
while Game.gettot(self.dealer.hand)<17:#changed
self.dealer.hand.append(DeckofCards.deal(self.deck))
dealerhand=Game.gettot(self.dealer.hand) #changed
print(dealerhand)
if Game.gettot(self.dealer.hand)==21:#changed
self.dealer.blackhjack=True
dealerhand1=Game.gettot(self.dealer.hand)#changed
print(dealerhand1)
def gettot(self,hand):
total=0
for x in self.hand:
if x==Card('H','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('D','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('S','A'):
b=total+x
if b>21:
total+=1
else:
total+=11
if x==Card('C','A'):
b=total+x #changed
if b>21:
total+=1
else:
total+=11
else:
total+=x
return(total)
def playgame(self):
play = "yes"
while (play.lower() == "yes"):
self.firstround()
self.playturn()
if self.player.blackjack == True:
print(self.player.name + " got BLACKJACK! ")
self.player.money += self.player.bid * 1.5
print (self.player.name + " now has " + str(self.player.money))
print("\n")
self.player.inout = False
if self.player.score > 21:
print(self.player.name + " lost with a tot of " + str(self.player.score))
self.player.money -= self.player.bid
print (self.player.name + " now has " + str(self.player.money))
print ("\n\n")
self.player.inout = False
self.playdealer()
if self.dealer.blackjack == True:
print("Dealer got blackjack, dealer wins\n")
self.player.money -= self.player.bid
print("Round\n")
print("\t",self.dealer)
print("\t",self.player)
print("\t Dealer has " + str(self.dealer.score) + ", " + self.player.name + " has " + str(self.player.score))
elif self.player.inout == True:
print("Round\n")
print("\t",self.dealer)
print("\t",self.player)
print("\n\t Dealer has " + str(self.dealer.score) + ", " + self.player.name + " has " + str(self.player.score))
if self.dealer.score > 21:
print("\t Dealer lost with a total of " + str(self.dealer.score))
self.player.money += self.player.bid
print(self.player.name + " now has " + str(self.player.money))
elif self.player.score > self.dealer.score:
print("\t" +self.player.name + " won with a total of " + str(self.player.score))
self.player.money += self.player.bid
print("\t"+self.player.name + " now has " + str(self.player.money))
else:
print("\t Dealer won with a total of " + str(self.dealer.score))
self.player.money -= self.player.bid
print("\t"+self.player.name + " now has " + str(self.player.money))
else:
print("Round")
print("\t",self.dealer)
print("\t",self.player)
if self.player.blackjack == False:
print("\t "+ self.player.name + " lost" )
else:
print("\t "+self.player.name + " Won!")
if self.player.money <= 0:
print(self.player.name + " out of money - out of game ")
play = "no"
else:
play = input("\nAnother round? ")
print("\n\n")
print("\nGame over. ")
print(self.player.name + " ended with " + str(self.player.money) + " dollars.\n")
print("Thanks for playing. Come back soon!")
ls= [Card('H','A'),Card('H','2'),Card('H','3'),Card('H','4'),Card('H','5'),Card('H','6'),Card('H','7'),Card('H','8'),Card('H','9'),Card('H','10'),
Card('H','J'),Card('H','Q'),Card('H','K'),
Card('S','A'),Card('S','2'),Card('S','3'),Card('S','4'),Card('S','5'),
Card('S','6'),Card('S','7'),Card('S','8'),Card('S','9'),Card('S','10'),
Card('S','J'),Card('S','Q'),Card('S','K'),
Card('C','A'),Card('C','2'),Card('C','3'),Card('C','4'),Card('C','5'),
Card('C','6'),Card('C','7'),Card('C','8'),Card('C','9'),Card('C','10'),
Card('C','J'),Card('C','Q'),Card('C','K'),
Card('D','A'),Card('D','2'),Card('D','3'),Card('D','4'),Card('D','5'),
Card('D','6'),Card('D','7'),Card('D','8'),Card('D','9'),Card('D','10'),
Card('D','J'),Card('D','Q'),Card('D','K')]
def main():
x = input("Player's name? ")
blackjack = Game(ls,x)
blackjack.playgame()
main()
The problem is that, in at least some places, you're trying to print a list.
While printing anything, including a list, calls str on it, the list.__str__ method calls repr on its elements. (If you don't know the difference between str and rep, see Difference between __str__ and __repr__ in Python.)
If you want to print the str of every element in a list, you have to do it explicitly, with a map or list comprehension.
For example, instead of this:
print(self.player.name + ' , your hand has:' + str(self.player.hand))
… do this:
print(self.player.name + ' , your hand has:' + [str(card) for card in self.player.hand])
But this is still probably not what you want. You will get ['8', '9'] instead of [<__main__.Card object at 0x1007aaad0>, <__main__.Card object at 0x1007aaaf0>], but you probably wanted something more like `8H 9C'. To do that, you'd want something like:
print(self.player.name + ' , your hand has:' +
' '.join(str(card) for card in self.player.hand))
You already have similar (although more verbose) code inside Player.__str__:
for y in range(len(self.hand)):
x +=self.hand[y].face + self.hand[y].suit + " "
This code could be improved in a few ways.
First, it's going to raise an AttributeError because you're using face instead of number. But really, you shouldn't need to do this at all—the whole reason you created a Card.__str__ method is so you can just use str(Card), right?
Second, you almost never want to loop over range(len(foo)), especially if you do foo[y] inside the loop. Just loop over foo directly.
Putting that together:
for card in self.hand:
x += str(card) + " "
At any rate, you need to do the same thing in both places.
The version that uses the join method and a generator expression is a little simpler than the explicit loop, but does require a bit more Python knowledge to understand. Here's how you'd use it here:
x += " ".join(str(card) for card in self.hand) + " "
Your next problem is that Card.__str__ doesn't include the suit. So, instead of 8H 9C, you're going to get 8 9. That should be an easy fix to do on your own.
Meanwhile, if you find yourself writing the same code more than once, you probably want to abstract it out. You could just write a function that takes a hand list and turns it into a string:
def str_hand(hand):
return " ".join(str(card) for card in self.hand)
But it might be even better to create a Hand class that wraps up a list of cards, and pass that around, instead of using a list directly.
You are not running the functionality you want because you are referencing player.hand. Try changing
str(self.player.hand)
to
str(self.player)