Ok, so I'm experiencing a weird error, and unfortunately, I don't know that I can show both examples here.
Take a look at the following code (apologies for the length):
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}
class Card():
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
## Attributes listed in the __init__ statement do not have to
## correlate to called objects (ie: suit,rank)
self.value = values[rank]
## Values represents the integer value of each card as compared
## to it's string (word) based rank
def __str__(self):
return self.rank + " of " + self.suit
## Allows for printing in the form of X of Y, or Two of Hearts as an example
# Deck will be a compilation of all card objects to a single list
# that can then be shuffled, dealt from, etc.
class Deck():
def __init__(self):
## All cards starts off with a blank list
self.all_cards = []
## For each suit in suits
for suit in suits:
### For each rank in ranks
for rank in ranks:
#### Create the Card object equal to the suit and rank of the card
#### ie: Two of spades, three of clubs, etc.
created_card = Card(suit,rank)
#### Then append each card created to the self.all_cards list.
self.all_cards.append(created_card)
def shuffle(self):
## Method call to randomize the self.all_cards list internally
random.shuffle(self.all_cards)
def deal_one(self):
return self.all_cards.pop()
game_deck = Deck()
game_deck.shuffle()
## Checking to make sure the deck is full before continuing
print(len(game_deck.all_cards))
## Attempt without watching tutorial
class Player():
def __init__(self,name):
self.name = name
self.player_hand = []
self.balance = 100
self.bet = 0
def deposit(self,dep_amt):
self.balance += dep_amt
print(f'{dep_amt} added to balance. New balance is: ${self.balance}')
def withdraw(self,wit_amt):
self.balance -= wit_amt
print(f'{wit_amt} subtracted from balance. New balance is: ${self.balance}')
def player_bet(self,bet_amt = 0):
while True:
bet_amt = int(input("How much would you like to bet? \n"))
if bet_amt > self.balance:
print("Sorry, you don't have enough money, try again.")
elif bet_amt < 1:
print('Sorry, you must bet at least $1')
else:
print(f'Thanks, your bet is ${bet_amt}')
self.balance -= bet_amt
print(f'Your remaining balance is ${self.balance}')
break
## May need to be adjusted to clear the hand entirely, unsure
def remove_one(self):
return self.player_hand.pop(0)
# NOTE: The most cards a player can hold without busting is 11
def add_cards(self,new_cards):
### Single card object
self.player_hand.append(new_cards)
def __str__(self):
return f'{self.name} has a balance of ${self.balance}.'
## Attempt without watching tutorial
class Dealer():
def __init__(self,name):
self.name = name
self.player_hand = []
self.balance = 500
def deposit(self,dep_amt):
self.balance += dep_amt
print(f'{dep_amt} added to balance. New balance is: ${self.balance}')
def withdraw(self,wit_amt):
self.balance -= wit_amt
print(f'{wit_amt} subtracted from balance. New balance is: ${self.balance}')
def remove_one(self):
return self.player_hand.pop(0)
def add_cards(self,new_cards):
### Single card object
self.player_hand.append(new_cards)
def __str__(self):
return f'{self.name} has a balance of ${self.balance}.'
## Full Game Code
game_on = True
playing = False
while game_on == True:
game_check = input('Would you like to play Black Jack, Y/N? ').lower()
if game_check == 'y':
round_counter = 0
dealer_name = 'Klaus the Dealer'
dealer = Dealer(dealer_name)
player_name = input("Player One, what is your name? ")
player_one = Player(player_name)
print(f"Nice to meet you {player_name}, you'll be playing against {dealer_name}\n")
print(player_one)
print(dealer)
print("Let's play Black Jack!\n")
playing = True
else:
print('Ok, have a nice day')
game_on = False
break
while playing == True:
round_counter +=1
for x in range(2):
player_one.add_cards(game_deck.deal_one())
dealer.add_cards(game_deck.deal_one())
So when I run this code all at once, at the very last 2 lines, I get an index error when the code hits the player_one.add_cards(game_deck.deal_one()) stating IndexError: pop from empty list
The thing is, if I run this code in separate lines in a Jupiter notebook, and separate out the class calls from the rest of the game code, the player_one.add_cards(game_deck.deal_one()) works just fine.
Can anyone tell me what is causing this error?
You are running out of cards... :)
the line you reference is inside of an infinite loop.
while playing == True:
round_counter +=1
for x in range(2):
player_one.add_cards(game_deck.deal_one())
dealer.add_cards(game_deck.deal_one())
suggestion: while you are troubleshooting, just pop a little print statement in the deal_one() function to see what is being dealt and then delete it later.
Ok, so thanks to Jeff H for pointing out that the call for the card deal was inside an infinite loop, even though I couldn't fix the problem by breaking the loop itself, I did figure out how to start off the initial deal by absorbing it into the game_check statement above, like so:
while game_on == True:
game_check = input('Would you like to play Black Jack, Y/N? ').lower()
if game_check == 'y':
round_counter = 0
dealer_name = 'Klaus the Dealer'
dealer = Dealer(dealer_name)
player_name = input("Player One, what is your name? ")
player_one = Player(player_name)
print(f"Nice to meet you {player_name}, you'll be playing against {dealer_name}\n")
print(player_one)
print(dealer)
print("Let's play Black Jack!\n")
playing = True
for x in range(2):
player_one.add_cards(game_deck.deal_one())
dealer.add_cards(game_deck.deal_one())
This won't account for having to deal cards into the hand later while in another while loop, but it will fix the first issue.
Related
I am trying some text based rpg game as a beginner in python. But i am struggling to get done one thing.
If i use while loop to run program 5 times. So i want repeat killing monster but without saving his attributes.
If you run this code, character kills a monster in couple of moves and appends his experience to himself and monster hp decreases to <= 0 and dies.
Looping whole program does not work, randomly created monster is still the same, i just want to create new monster with new random attributes every time i loop program. It is possible? I am new to this and can't figure it out at this moment. Some tips ?
Here is some code but without while loop: final output is to loop this menu and fight simulator to gain exp and items from random monsters.
import random
import time
# List of items to drop
normal_items = ['Copper ore', 'Apple', 'Animal skin', 'Stone', 'Feather', 'Rotten egg', 'Bag of sand', "Simple dagger", "Blue flower"]
rare_items = ['Energized wand', 'Staff of purity', 'Enhanced gloves', 'Adamant chest plate']
legendary_items = ['Crown of Immortality', 'Robe of fire-dragon']
drop_chance_dice = random.randint(1, 100)
# Simple drop chance function
def dice():
if drop_chance_dice <= 70:
random_choice = (random.choice(normal_items))
print(f"You got: {random_choice} ")
if 70 <= drop_chance_dice <= 98:
random_choice = (random.choice(rare_items))
print(f"You got: {random_choice} ")
if 99 <= drop_chance_dice <= 100:
random_choice = (random.choice(legendary_items))
print(f"Congratulations! You got an legendary item: {random_choice}")
# Instances and mobs
rat_nest= ['Rat', 'Giant Rat', 'Leader of Rats']
northern_forest = ['Snake', 'Wolf', 'Witch']
# My Character Class
class YourCharacter:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Creating my character(preset)
my_character = YourCharacter("Your character \n", 'FroGres', 16, 0, 1, 100)
# Introduction
def introduction_of_player(my_character):
print(f"{my_character.intro}")
print(f"{my_character.name}")
print(f"Attack: {my_character.attack}")
print(f"Experience: {my_character.exp}")
print(f"Level: {my_character.level}")
print(f"HP: {my_character.hp}")
# Monsters class build
class Monster:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Monsters attributes + list of mobs (for testing - to be upgraded)
# rat nest
rat = Monster("You fight vs: \n", "Rat", random.randint(4, 6), random.randint(8, 14), random.randint(1, 3),
random.randint(50, 100))
giant_rat = Monster("You fight vs: \n", "Giant Rat", random.randint(6, 8), random.randint(10, 18), random.randint(2, 4),
random.randint(80, 130))
rat_boss = Monster("You fight vs: \n", "Leader of Rats", random.randint(4, 6), random.randint(8, 14),
random.randint(1, 3),
random.randint(50, 100))
# northern forest
#Witch = Monster("You fight vs: \n", "Witch", random.randint(8, 12), random.randint(12, 20), random.randint(3, 6), random
# .randint(120, 200))
list_of_mobs = [rat, giant_rat, rat_boss]
event_mob = random.choice(list_of_mobs) # Random pick monster , USED in function
# Introduction of Monster
def introduction_of_monster_ratnest(list_of_mobs):
print(f"{list_of_mobs.intro}")
print(f"{list_of_mobs.name}")
print(f"Attack: {list_of_mobs.attack}")
print(f"Experience: {list_of_mobs.exp}")
print(f"Level: {list_of_mobs.level}")
print(f"HP: {list_of_mobs.hp}")
def escape_or_fight():
take_input = input("[a]ttack or [r]un?")
if take_input == 'a':
return attack()
if take_input == 'r':
print("You run as fast as possible.. ")
print("You returning to your hideout..")
else:
print("Something wrong")
# Menu of actions
def menu_dungs():
asking = input("Where do you want to go?: 1.Rat Nest or 2.Northern Forest :")
if asking == "1":
print("You entering rat nest.. good luck!\n")
time.sleep(1)
print("Some ugly creature stays on your way!")
print(f"{event_mob.name} is looking at you!")
if event_mob == rat:
introduction_of_monster_ratnest(rat)
escape_or_fight()
elif event_mob == giant_rat:
introduction_of_monster_ratnest(giant_rat)
escape_or_fight()
elif event_mob == rat_boss:
introduction_of_monster_ratnest(rat_boss)
escape_or_fight()
else:
print("Something went horribly wrong.. Don't even ask..")
elif asking == "2":
print("You entering northern forest.. good luck!\n")
print("Dungeon unavailable at this moment, try another one")
pass
# Not in use
else:
print("Try again and choose correct location\n")
menu_dungs()
def attack():
gain_exp = event_mob.exp + my_character.exp
rounds = 0
while event_mob.hp > 0:
event_mob.hp = event_mob.hp - my_character.attack
rounds += 1
print(f"You hit with: {my_character.attack} damage. Enemy HP is {event_mob.hp}")
print(f"Enemy HP after your attack is {event_mob.hp}", "\n")
if event_mob.hp <= 0:
print(f"{event_mob.name} has died..")
print(f"It tok you: {rounds} moves to kill that creature! \n")
print("Congratulations! Here is your loot")
dice()
print(f"You got: {event_mob.exp} experience from that fight.")
print(f"Your experience is now: {gain_exp}")
menu_dungs()
I tried: to create new unique monster with new randomly created attributes every time i run program. I used while loop but monster is not "respawning"
I expect: Some sort of simulator, after i kill monster, program creates new one and my character gains experience and items every fight.
I wonder: If there is some method to makes this class unique every loop.
Here is HOW-TO to achieve all goals in your question:
each time generate monsters with different parameters
respawn monsters
First you create 3 sepreate functions that would return a new monster - the class of returned value is always the same (Monster) but they return new instances on each call:
def get_rat():
return Monster("You fight vs: \n", "Rat", ...)
def get_giant_rat():
return Monster(...)
def get_rat_boss():
reutrn Monster(...)
You will also need to modify how you select monsters. I would suggest to create list of functions - so instead of selecting a monster you select a function, that generates monster:
# This should replace the list_of_mob
list_of_mob_generators = [get_rat, get_giant_rat, get_rat_boss]
And the last - you should select monster on each loop interation in main menu (so the monster could respawn). The shortest way is to change your global variable:
event_mob = None # we change event_mob initially to None - we will select in later
def menu_dungs():
global event_mob # this is new
asking = input("Where do you want to go?: 1.Rat Nest or 2.Northern Forest :")
if asking == "1":
event_mob_generator = random.choice(list_of_mob_generators) # get one of the functions
event_mob = event_mob_generator() # call the function to get monster
print("You entering rat nest.. good luck!\n")
time.sleep(1)
print("Some ugly creature stays on your way!")
print(f"{event_mob.name} is looking at you!")
# and this condition has changed, since we do not have one instance of each monster anymore
if event_mob.name == 'Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Giant Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Rat Boss':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
else:
print("Something went horribly wrong.. Don't even ask..")
... # and so on
and of course do not forget a while loop for main menu =)
while True:
menu_dungs()
Thanks for help, program works as i wanted but still shows me 8 yellow errors in attack() function. Cannot find reference 'hp' in 'None' etc.
maybe because this event_mob = None ?
Could you run this code and see what is going on ? very likely i did put something in wrong place..
import random
import time
# List of items to drop
normal_items = ['Copper ore', 'Apple', 'Animal skin', 'Stone', 'Feather', 'Rotten egg', 'Bag of sand', "Simple dagger", "Blue flower"]
rare_items = ['Energized wand', 'Staff of purity', 'Enhanced gloves', 'Adamant chest plate']
legendary_items = ['Crown of Immortality', 'Robe of fire-dragon']
drop_chance_dice = random.randint(1, 100)
# Simple drop chance function
def dice():
if drop_chance_dice <= 70:
random_choice = (random.choice(normal_items))
print(f"You got: {random_choice} ")
if 70 <= drop_chance_dice <= 98:
random_choice = (random.choice(rare_items))
print(f"You got: {random_choice} ")
if 99 <= drop_chance_dice <= 100:
random_choice = (random.choice(legendary_items))
print(f"Congratulations! You got an legendary item: {random_choice}")
# Instances and mobs
rat_nest= ['Rat', 'Giant Rat', 'Leader of Rats']
#not in use
northern_forest = ['Snake', 'Wolf', 'Witch']
# My Character Class
class YourCharacter:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Creating my character(preset)
my_character = YourCharacter("Your character \n", 'FroGres', 16, 0, 1, 100)
# Introduction
def introduction_of_player(my_character):
print(f"{my_character.intro}")
print(f"{my_character.name}")
print(f"Attack: {my_character.attack}")
print(f"Experience: {my_character.exp}")
print(f"Level: {my_character.level}")
print(f"HP: {my_character.hp}")
# Monsters class build
class Monster:
def __init__(self, intro, name, attack, exp, level, hp):
self.intro = intro
self.name = name
self.attack = attack
self.exp = exp
self.level = level
self.hp = hp
# Monsters getting functions
# rat nest
def get_rat():
return Monster("You fight vs: \n", "Rat", random.randint(4, 6), random.randint(8, 14), random.randint(1, 3),
random.randint(50, 100))
def get_giant_rat():
return Monster("You fight vs: \n", "Giant Rat", random.randint(6, 8), random.randint(10, 18), random.randint(2, 4),
random.randint(80, 130))
def get_rat_boss():
return Monster("You fight vs: \n", "Rat Boss", random.randint(4, 6), random.randint(8, 14),random.randint(1, 3),
random.randint(50, 100))
# northern forest
# def get_witch():
# return Monster("You fight vs: \n", "Witch", random.randint(8, 12), random.randint(12, 20), random.randint(3, 6), random
# .randint(120, 200))
list_of_mobs_generators = [get_rat, get_giant_rat, get_rat_boss]
def escape_or_fight():
take_input = input("[a]ttack or [r]un?")
if take_input == 'a':
return attack()
if take_input == 'r':
print("You run as fast as possible.. ")
print("You returning to your hideout..")
else:
print("Something wrong")
# Menu of actions
event_mob = None
def menu_dungs():
global event_mob
asking = input("Where do you want to go?: 1.Rat Nest or 2.Northern Forest :")
if asking == "1":
event_mob_generator = random.choice(list_of_mobs_generators)
event_mob = event_mob_generator()
def introduction_of_monster_ratnest(event_mob):
print(f"{event_mob.intro}")
print(f"{event_mob.name}")
print(f"Attack: {event_mob.attack}")
print(f"Experience: {event_mob.exp}")
print(f"Level: {event_mob.level}")
print(f"HP: {event_mob.hp}")
print("You entering rat nest.. good luck!\n")
time.sleep(1)
print("Some ugly creature stays on your way!")
print(f"{event_mob.name} is looking at you!")
if event_mob.name == 'Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Giant Rat':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
elif event_mob.name == 'Rat Boss':
introduction_of_monster_ratnest(event_mob)
escape_or_fight()
else:
print("Something went horribly wrong.. Don't even ask..")
elif asking == "2":
print("You entering northern forest.. good luck!\n")
print("Dungeon unavailable at this moment, try another one")
pass
# Not in use
else:
print("Try again and choose correct location\n")
def attack():
gain_exp = event_mob.exp + my_character.exp
rounds = 0
while event_mob.hp > 0:
event_mob.hp = event_mob.hp - my_character.attack
rounds += 1
print(f"You hit with: {my_character.attack} damage. Enemy HP is {event_mob.hp}")
print(f"Enemy HP after your attack is {event_mob.hp}", "\n")
if event_mob.hp <= 0:
print(f"{event_mob.name} has died..")
print(f"It tok you: {rounds} moves to kill that creature! \n")
print("Congratulations! Here is your loot")
dice()
print(f"You got: {event_mob.exp} experience from that fight.")
print(f"Your experience is now: {gain_exp}")
while True:
menu_dungs()
so I'm trying to make a scoring system using my current code for blackjack. The game is versus the computer and a player and the rules are a bit different , but that has all been setup. I need to purpose the code for scoring both player and computer's cards. I also should make it so an ace is set to be the value of 1, if to avoid busting. I was thinking of doing so as cards are drawn, but I'm not entirely sure. I tried cross class variables and I didn't find much success. Maybe I could fuse the player and deck classes?
Anyways, here is what I have, I'll provide any more information you need and there should be fairly thorough comments.
# This is a game of blackjack versus a computer.
# ------------------------------------------------------------------------------------------------------
# importing necessary files
import random
# A couple global variables for any necessary repeats and scoring.
RepeatCardChoice = 0
YourScore = 0
ComputerScore = 0
HitCount = 0 # The amount of times the player hits. Used for showing cards.
# Our deck itself.
class Card: # This is for developing the cards in the first place.
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
def show(self):
print(str(self.rank) + str(self.suit))
class Deck: # This is for deck behaviors and creating a deck.
def __init__(self):
self.cards = []
self.Cards()
def Cards(self):
for suit in ["S", "C", "D", "H"]: # S = Spades, C = Clubs, D = Diamonds, and H = Hearts
for rank in range(1, 14):
value = rank
if rank == 1:
rank = 'A' # Makes all 1 values = to ace.
elif rank == 11:
rank = 'J' # Makes all 11 values = to jack or j.
elif rank == 12:
rank = 'Q' # Makes all 12 values = to queen or Q.
elif rank == 13:
rank = 'K' # Makes all 13 values = to king or K.
if rank == (11) or (12) or (13):
value = 10
elif rank == 1:
value == 11
self.value = value
self.cards.append(Card(suit, rank))
def show(self): # Shows each card individually.
for card in self.cards:
card.show() # Really just reusing another function to display results.
def shuffle(self):
random.shuffle(self.cards)
def drawCard(self):
return self.cards.pop()
class Player: # This class is for player behaviors such as drawing and showing your hand.
def __init__(self, name):
self.name = name # Allows the player to choose their name.
self.hand = [] # Assigns their cards to a list, to be saved.
self.Deck = Deck()
def draw(self, deck, CardCount): # How the player draws one card at a time. It wasn't necessary to allow more.
count = 0
while count != CardCount:
count += 1
self.hand.append(deck.drawCard())
return self
def showHand(self, showCount): # Shows each card in the player's hand.
count = 0 # A counter is used to limit how much is drawn.
for card in self.hand: # This is so "card" doesn't stay an unresolved reference.
if count == showCount:
return
count += 1
card.show()
# Below is where we apply the classes and play the game. The computer will operate without input, unlike the player.
# Here is the deck.
deck = Deck()
deck.shuffle() # Shuffling the deck in preparation.
PlayerName = str(input('What is your name?')) # Just so the player can choose their name.
# Setting up the players.
Computer = Player("The Computer")
You = Player(PlayerName)
# Giving both players their hand to start off with.
Computer.draw(deck, 2)
You.draw(deck, 2)
# Here is where one card in each hand is shown.
print('You are showing:')
You.showHand(1)
print('The computer is showing:')
Computer.showHand(1)
# Here is where you decide to hit or stand.
while RepeatCardChoice == 0:
CardChoice = str(input('Hit (H) or Stand (S)?'))
if CardChoice == 'H':
You.draw(deck, 1)
HitCount += 1
You.showHand(1+HitCount)
RepeatCardChoice = 0 # This is so the player can keep deciding whether they still want to hit?
elif CardChoice == 'S':
RepeatCardChoice = 21 # Get it, because the winning score in blackjack is 21?
HitCount = 0
else:
RepeatCardChoice = 0
# Here is where we check your score.
if YourScore > 21:
exit('You busted and the computer wins!')
elif YourScore == 21:
exit('Blackjack, you win!')
# Here is where the computer hits or stands.
while ComputerScore <= 17:
Computer.draw(deck, 1)
HitCount +=1
Computer.showHand(1+HitCount)
if ComputerScore>21:
exit('The computer busted and you win!')
elif ComputerScore == 21:
exit('Blackjack, the computer wins!')
# Here is where we compare the scores to decide the winner.
if ComputerScore > YourScore:
exit('The computer wins!')
elif YourScore > ComputerScore:
exit('You win!')
elif ComputerScore == YourScore:
exit('You tied')
The output shouldn't provide any errors if the scoring system is successful, and I setup some variables that I might use to assign the score, however this can be changed as needed. Here is the output anyways.
What is your name?Sample
You are showing:
KC
The computer is showing:
JS
Hit (H) or Stand (S)?H
KC
8S
Hit (H) or Stand (S)?S
JS
...
Traceback (most recent call last):
File "Censored", line 119, in <module>
Computer.draw(deck, 1)
File "Censored", line 66, in draw
self.hand.append(deck.drawCard())
File "Censored", line 54, in drawCard
return self.cards.pop()
IndexError: pop from empty list
Essentially, what is happening is that the computer hits infinitely due to a lack of scoring, until there is nothing left to draw, this is after you stand. I skipped a lot of lines in the output, as they're just a bunch of cards getting drawn.
declared playing in my hit_or_stay function as a global variable but keep getting an error when i run my program saying "name error: playing is not defined" How do i fix this?
I used global playing in hit_or_stand() to control the gameflow depending on the player's input. When I run the code I get error "NameError: name playing is not defined." I tried to move "global playing" outside of hit_or_stay() but nothing seems to work.
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}
class Deck:
'''
CREATES DECK, SHUFFLES DECK, DEALS CARDS.
'''
#CREATES DECK BY ADDING EACH SUIT TO EACH RANK AND STORING IN LIST SELF.DECK
def __init__(self):
self.deck = []
for s in suits:
for r in ranks:
self.deck.append(r + ' of ' + s)
#SHUFFLE DECK CREATED IN __init__()
def shuffle(self):
random.shuffle(self.deck)
#DEALS CARD FROM SELF.DECK AT GAME START AND IF PLAYER CHOOSES TO HIT
def deal(self):
single_card = self.deck.pop()
return single_card
#PRINTS CARDS IN SELF.DECK (FOR TROUBLESHOOTING)
def __str__(self):
for card in self.deck:
return str(self.deck)
#print('\n')
##create an instance of Deck class and print the deck
#test_deck = Deck()
#print(test_deck)
#print('\n')
##shuffle and print the deck
#test_deck.shuffle()
#print(test_deck)
#print('\n')
class Card:
'''
CREATES CLASS FOR INDIVIDUAL CARDS, PRINTS INIDIVIDUAL CARDS "SUIT OF RANK"
'''
#CREATES CHARACTERISITCS OF class Card; self.suit and self.rank
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
class Hand:
'''
HOLDS CARD OBJECT FROM self.deck USING Deck.deal() method
CALCULATES THE VALUE OF THE CARDS IN HAND
ADJUST FOR ACES WHEN APPROPRIATE
'''
#CREATE CHARATERISTICS FOR CARDS IN HAND; self.card = cards in hand, self.value = value of cards in hand, self.aces = counts aces in hand
def __init__(self):
self.cards = []
self.value = 0
self.aces = 0
#ADDS CARDS TO HANDS ONCE DEALT
def add_card(self,card):
#ADDS CARD TO HAND
self.cards.append(card)
#HOLDS THE VALUE OF THE HAND
key = ''
key = card.split()
self.value += values[key[0]]
#ACCOUNT FOR ACE
if key[0] == 'Ace':
self.aces += 1
#KEEPS TRACK OF ACES; ADJUSTS VALUE FOR ACE WHEN APPROPARIATE
def adjust_for_ace(self,card):
if self.value > 21 and self.aces:
self.value -= 10
self.aces -= 1
class Chips:
def __init__(self):
self.total = 100
self.bet = 0
#ADD CHIPS TO TOTAL IF WIN
def win_bet(self):
self.total += self.bet
#TAKE AWAY CHIPS FORM TOTAL IF LOSE
def lose_bet(self):
self.total -= self.bet
#TAKE BET FROM USER
def take_bet(Chips):
while True:
try:
Chips.bet = int(input("How many chips do you want to bet?: "))
except:
print("There was an error! Enter an integer!\n")
continue
else:
if Chips.bet > Chips.total:
print("You don't have enough chips!\n")
else:
print("Your bet is {} chips\n".format(Chips.bet))
break
#IF PLAYER CHOOSES TO HIT
def hit(deck,hand):
#USE IN hit_or_stay function; ADDS CARD DEALT FROM DECK TO THE HAND and ADJUSTS FOR ACES
Hand.add_card(deck.deal())
Hand.adjust_for_ace()
#DETERMINE WHETHER PLAYER WANTS TO HIT OR STAY
def hit_or_stay(deck,hand):
global playing #controls upcoming loop
while True:
h_or_s = raw_input("Would you like to hit or stay? Enter 'hit' or 'stay': ")
if h_or_s[0].lower() == "h":
hit(deck,hand)
elif h_or_s[0].lower() == "s":
playing = False
else:
print("\nThere was an error. Try again.\n")
continue
break
def show_some(player,dealer):
print("Dealer's Hand:")
print(dealer.cards[0])
print("< card hidden >\n")
print("\nPlayer's hand value: {}".format(player.value))
print("Player's Hand:", *player.cards, sep='\n')
def show_all(player,dealer):
print("\nDealer's hand value: {}".format(dealer.value))
print("\nDealer's Hand:", *dealer.cards, sep='\n')
print("\nPlayer's hand value: {}\n".format(player.value))
print("Player's Hand:", *player.cards, sep='\n')
#GAME ENDING FUNCTIONS
def player_busts(player,dealer,Chips):
#PRINT PLAYER BUSTS; TAKE AWAY CHIPS BET FROM TOTAL CHIPS
print("Dealer's hand value: {}\n Player's hand value: {}\n".format(dealer_hand.value,player_hand.value))
print("Player busts! Dealer Wins\n")
Chips.lose_bet()
print("You lost {} chips!\n You have {} chips remaining.".format(Chips.bet,Chips.total))
def player_wins(player,dealer,Chips):
print("Dealer's hand value: {}\n Player's hand value: {}\n".format(dealer_hand.value,player_hand.value))
print("Player wins!\n")
Chips.win_bet()
print("You won {} chips!\n You have {} chips remaining.".format(Chips.bet,Chips.total))
def dealer_busts(player,dealer,Chips):
print("Dealer's hand value: {}\n Player's hand value: {}\n".format(dealer_hand.value,player_hand.value))
print("Dealer busts! Player wins!\n")
Chips.lose_bet()
print("You won {} chips!\n You have {} chips remaining.".format(Chips.bet,Chips.total))
def dealer_wins(player,dealer,Chips):
print("Dealer's hand value: {}\n Player's hand value: {}\n".format(dealer_hand.value,player_hand.value))
print("Dealer wins!\n")
Chips.lose_bet()
print("You lost {} chips!\n You have {} chips remaining.".format(Chips.bet,Chips.total))
def push(player,dealer,Chips):
print("Player and Dealer tie, its a push!\n")
#GAMEPLAY
while True:
print("Welcome to Black Jack. Get as close to 21 as you can without going over 21.\n")
print("Dealer hits until he reaches 17. Aces count as 1 or 11\n")
#create an instance of Deck class and print the deck
game_deck = Deck()
#shuffle and print the deck
game_deck.shuffle()
#CREATE PLAYER HAND AND DEAL TWO CARDS
player_hand = Hand()
player_hand.add_card(game_deck.deal())
player_hand.add_card(game_deck.deal())
#CREATE DEALER HAND AND DEAL TWO CARDS
dealer_hand = Hand()
dealer_hand.add_card(game_deck.deal())
dealer_hand.add_card(game_deck.deal())
#TAKE BET FROM PLAYER
#player_chips = take_bet(Chips())
#SHOW ONE OF DEALER'S CARDS AND ALL OF PLAYER'S CARDS
show_some(player_hand,dealer_hand)
while playing: #THIS IS WHERE THE NAME ERROR OCCURS!!
if player_hand.value < 21:
#PLAYER CHOOSES HIT OR STAY
hit_or_stay(game_deck(),player_hand)
#SHOW PLAYERS CARDS AND KEEP ONE DEALER CARD HIDDEN
show_some(player_hand,dealer_hand)
NameError: name 'playing' is not defined
global in Python doesn't create a variable, it is defining the existing variable as global. So you are trying to state that a some variable is global (but it is still not exists) and then call it. So you get an error.
Please, never use global in Python! In 99.999% cases you can easily replace your code without any global variables! For example, add playing = True after this part of your code:
#GAMEPLAY
while True:
print("Welcome to Black Jack. Get as close to 21 as you can without going over 21.\n")
print("Dealer hits until he reaches 17. Aces count as 1 or 11\n")
#create an instance of Deck class and print the deck
game_deck = Deck()
#shuffle and print the deck
game_deck.shuffle()
The problem is that playing is defined in hit_or_stay, which isn't called until after the while loop begins.
Define playing as True to start, or include an explicit break condition
while True:
print("Welcome to Black Jack. Get as close to 21 as you can without going over 21.\n")
print("Dealer hits until he reaches 17. Aces count as 1 or 11\n")
# ~snip~
# define here
playing = True
while playing:
# rest of your code
Furthermore, it looks like hit_or_stay also has a while loop in it. I'd suggest taking a look at how you've structured your code so far and maybe refactoring it. Instead of just break in hit_or_stay, maybe you could return playing:
def hit_or_stay(deck,hand):
# no need for global playing anymore, as you return the proper bool
h_or_s = raw_input("Would you like to hit or stay? Enter 'hit' or 'stay': ")
if h_or_s[0].lower() == "h":
hit(deck,hand)
return True
elif h_or_s[0].lower() == "s":
return False
else:
raise ValueError("\nThere was an error. Try again.\n")
playing = True
while playing:
try:
playing = hit_or_stay(deck, hand)
# Catch the error for unexpected input and retry
except ValueError as e:
print(e)
continue
For my class i have to make a working Go fish game. i got this far in class but I'm stuck i cant figure out how send player back to Hand so i can make a check statement to see if he has any four of a kind. Any suggestions?
class Card(object):
""" A playing card. """
RANKS = ["A", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "J", "Q", "K"]
SUITS = ["c", "d", "h", "s"]
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __str__(self):
rep = self.rank + self.suit
return rep
class Hand(object):
""" A hand of playing cards. """
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)
def check(self,player):
print(player1)
for self.cards in rep:
print("i")
#####################
class Deck(Hand):
""" A deck of playing cards. """
def populate(self):
for suit in Card.SUITS:
for rank in Card.RANKS:
self.add(Card(rank, suit))
def shuffle(self):
import random
random.shuffle(self.cards)
def deal(self, hands, per_hand = 1):
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 ("Out of cards!")
def main():
deck1 = Deck()
deck1.populate()
deck1.shuffle()
player1 = Hand()
player2 = Hand()
hands = [player1, player2]
deck1.deal(hands, per_hand = 5)
print(player1)
player1.check(player1)
main()
What you said doesn't really make sense . Hand is a class; player1 is an instance of that class. Translating into personal terms, this is parallel to asking how to send Brandon back to human so you can count his teeth. You don't: you simply use the tooth-counting procedure that works on all humans.
Looking specifically at your code, I think this deals with the line
player1.check(player1)
All it should need is
player1.check()
player1 is a Hand; this call goes to Hand's check method. Here, the object that invoked the method automatically shows up as the first argument, self. Get rid of the second one and just use
def check(self):
Does that clarify the point of confusion?
Check this code out, which is a working version of Go Fish executable and playable from the console. See how they use:
def makeTurn(self):
print '%s\'s hand: %s' % (self.name,self.displayHand())
chooseCard = raw_input('What card do you ask for? ').strip()
if chooseCard == 'quit':
sys.exit(0)
if chooseCard not in self.hand:
print 'You don\'t have that card. Try again! (or enter quit to exit)'
chooseCard = self.makeTurn()
return chooseCard
Here is the complete Python Go Fish game.
import random
import sys
from collections import defaultdict
class HumanPlayer(object):
def __init__(self,deck):
self.hand = defaultdict(int)
self.book = []
self.deck = deck #making a copy of deck, all changes within
#this class should affect the global deck
self.score = 0
self.name = raw_input('Name yourself: ')
def Draw(self): #assuming that deck is a global
cardDrawn = self.deck.pop() #removes the last card from deck
self.hand[cardDrawn] += 1 #adds card to hand
print '%s drew %s.' % (self.name,cardDrawn)
self.checkForBooks()
def checkForBooks(self):
# Removes all items of which are 4.
for key,val in self.hand.items(): #can't use iteritems() because we are modifying hand in loop
if val == 4: #completed a book
self.book.append(key)
print '%s completed the book of %s\'s.' % (self.name,key)
self.score += 1
del self.hand[key]
self.emptyCheck()
def emptyCheck(self):
if len(self.deck)!=0 and len(self.hand)==0: #checks if deck/hand is empty
self.Draw()
def displayHand(self): #Displays current hand, cards separated by spaces
return ' '.join(key for key,val in self.hand.iteritems()
for i in range(val)) #meh, make it prettier
def makeTurn(self):
print '%s\'s hand: %s' % (self.name,self.displayHand())
chooseCard = raw_input('What card do you ask for? ').strip()
if chooseCard == 'quit':
sys.exit(0)
if chooseCard not in self.hand:
print 'You don\'t have that card. Try again! (or enter quit to exit)'
chooseCard = self.makeTurn()
return chooseCard
def fishFor(self,card):
if card in self.hand: # if card in hand, returns count and removes the card from hand
val = self.hand.pop(card)
self.emptyCheck()
return val
else:
return False
def gotCard(self,card,amount):
self.hand[card] += amount
self.checkForBooks()
class Computer(HumanPlayer):
def __init__(self,deck):
self.name = 'Computer'
self.hand = defaultdict(int)
self.book = []
self.deck = deck
self.opponentHas = set()
self.score = 0
def Draw(self): #assuming that deck is a global
cardDrawn = self.deck.pop() #removes the last card from deck
self.hand[cardDrawn] += 1 #adds card to hand
print '%s drew a card.' % (self.name)
self.checkForBooks()
##AI: guesses cards that knows you have, then tries cards he has at random.
##Improvements: remember if the card was rejected before, guess probabilities
def makeTurn(self):
# print self.displayHand(),self.opponentHas
candidates = list(self.opponentHas & set(self.hand.keys())) #checks for cards in hand that computer knows you have
if not candidates:
candidates = self.hand.keys() #if no intersection between those two, random guess
move = random.choice(candidates)
print '%s fishes for %s.' % (self.name,move)
return move
def fishFor(self,card): #Same as for humans players, but adds the card fished for to opponentHas list.
self.opponentHas.add(card)
if card in self.hand: # if card in hand, returns count and removes the card from hand
val = self.hand.pop(card)
self.emptyCheck()
return val
else:
return False
def gotCard(self,card,amount):
self.hand[card] += amount
self.opponentHas.discard(card)
self.checkForBooks()
class PlayGoFish(object):
def __init__(self):
self.deck = ('2 3 4 5 6 7 8 9 10 J Q K A '*4).split(' ')
self.deck.remove('')
self.player = [HumanPlayer(self.deck),Computer(self.deck)] #makes counting turns easier
def endOfPlayCheck(self):#checks if hands/decks are empty using the any method
return self.deck or self.player[0].hand or self.player[1].hand
def play(self):
random.shuffle(self.deck)
for i in xrange(9): # Deal the first cards
self.player[0].Draw()
self.player[1].Draw()
turn = 0
while self.endOfPlayCheck():
print '\nTurn %d (%s:%d %s:%d) %d cards remaining.' % (turn,self.player[0].name,
self.player[0].score,self.player[1].name,self.player[1].score,len(self.deck))
whoseTurn = turn%2
otherPlayer = (turn+1)%2
while True: #loop until player finishes turn
cardFished = self.player[whoseTurn].makeTurn()
result = self.player[otherPlayer].fishFor(cardFished)
if not result: #Draws and ends turn
self.player[whoseTurn].Draw()
break
print '%s got %d more %s.' % (self.player[whoseTurn].name,result, cardFished)
self.player[whoseTurn].gotCard(cardFished,result)
if not self.endOfPlayCheck(): break
turn+=1
print '\nScores: \n%s: %d\n%s: %d\n' % (self.player[0].name,self.player[0].score,
self.player[1].name,self.player[1].score)
if self.player[0].score>self.player[1].score:
print self.player[0].name,'won!'
elif self.player[0].score==self.player[1].score:
print 'Draw!'
else:
print self.player[1].name,'won!'
if __name__=="__main__":
game = PlayGoFish()
game.play()
The project: Write a program in python in which the virtual dealer Jake plays against the virtual players: Mike and Will. Mike and Will are free to bet on different outcomes with different payout ratios. This will allow the comparison of various strategies. You should keep track of each player's bank roll (including the dealer)
The game is played with a 7 faced die with numbers [0 - 6] numbers[1, 2, 3] are blue and numbers [4, 5, 6] are green.
Correct Parity Pays: 2/1
Correct Colour Pays: 2/1
Exact Number Pays: 5/1
Here is the first draft with the modifications #Harvey Summer suggested. Comments on how I can improve the code's structure and performance are appreciated.
from random import choice
from random import randint
class die_face():
# This class is used to define the properties linked to each outcome on the dice.
def __init__(self, num, colour, parity):
self.num = num
self.colour = colour
self.parity = parity
# Determine the properties linked to each outcome on the dice.
zero = die_face(0, 'none', 'none')
one = die_face(1, 'blue', 'odd')
two = die_face(2, 'blue', 'even')
three = die_face(3, 'blue', 'odd')
four = die_face(4, 'green', 'even')
five = die_face(5, 'green', 'odd')
six = die_face(6, 'green', 'even')
options = [zero, one, two, three, four, five, six,]
class bet():
# Define the bets
def __init__(self, bet_type, odds):
self.bet_type = bet_type
self.odds = odds
num_bet = bet('num', 5)
colour_bet = bet('colour', 2)
parity_bet = bet('parity', 2)
class broker():
# Define the properties of the broker.
def __init__(self, name, balance):
self.name = name
self.balance = balance
def __str__(self):
result = "Name: {} \n" \
"Balance: {}" .format(self.name, self.balance)
return result
def modify_balance(self, amount):
self.balance += amount
main_broker = broker('Main',1e3)
def random_strategy():
# Bet a random amount on a random game with a random guess.
guess = 'empty'
game_mode= choice([num_bet, colour_bet, parity_bet])
if game_mode == num_bet:
guess = randint(0,6)
elif game_mode == colour_bet:
guess = choice(['blue','green'])
elif game_mode == parity_bet:
guess = choice(['even','odd'])
value = randint(1,10)
return game_mode , value, guess
class player():
# This class defines each player
def __init__(self, name, strategy, bank_roll):
self.name = name
self.strategy = strategy
self.bank_roll = bank_roll
def modify_balance(self, amount):
self.bank_roll += amount
def __str__(self):
result = "Name: {} \n" \
"Bank Roll: {}" .format(self.name, self.bank_roll)
return result
def play(self):
return self.strategy()
# Add the players
Will = player("Will",random_strategy,100)
def dealer(type, bet_value, guess):
#Roll the dice
correct = choice(options)
#Return amount based on Win or Lose
if type == num_bet.bet_type:
if correct.num == guess:
return num_bet.odds * bet_value - bet_value
else:
return -bet_value
if type == colour_bet.bet_type:
if correct.colour == guess:
return colour_bet.odds * bet_value - bet_value
else:
return -bet_value
if type == parity_bet.bet_type:
if correct.parity == guess:
return parity_bet.odds * bet_value - bet_value
else:
return -bet_value
def main_play(player):
# Collect the bets from the players
bets = player.play()
# Roll and return bets
amount = dealer(bets[0].bet_type, bets[1], bets[2])
# Distribute the money
main_broker.modify_balance(amount*-1)
player.modify_balance(amount)
print(player)
print(main_broker)
I would create a bettingtable as a broker where money is put at risk and the outcome to the dealer and players are exchanged based on the play outcome, and allow players and dealer to place bet and collect winnings. Encapsulate betting logic to the players and abstracted it from a game rules class. Each player should have a risk tolerance or game play style (lame, aggressive, cheater, etc.)
If you build this right, it shouldn't matter what the game is: dice, cards, etc. should basically play the same.