Is an infinite for loop bad practice? - python

I'm implementing a card game in Python, and for my class to handle players, PlayerHandler, I recently implemented __next__ to simply call next_player. Because gameplay can be thought of in an infinite loop (The players will keep playing until they quit or win/lose), it did not make sense for it to stop iteration. However, it could seem confusing if a for loop caused an infinite loop, so should I raise a StopIteration somewhere?
class PlayerHandler():
"""Holds and handles players and order"""
def __init__(self, players=None, order=1):
if players is None:
self.players = []
else:
self.players = list(players)
self.current_player = None
self.next_player()
self.order = order
def get_player(self, interval):
assert type(interval) == int, "Key must be an integer!"
if not interval and self.players:
return self.current_player
elif self.players:
step = interval * self.order
index = self.players.index(self.current_player) + step
while index >= len(self.players):
index -= len(self.players)
while index <= -(len(self.players)):
index += len(self.players)
return self.players[index]
else:
raise KeyError("No players in the list!")
def next_player(self):
"""Sets the current player to the next player to play"""
if not self.current_player:
if self.players:
self.current_player = self.players[0]
else:
self.current_player = None
else:
self.current_player = self.get_player(1)
def __iter__(self):
return self
def __next__(self):
self.next_player()
return self.current_player

What matters is that your code is readable. If you're worried, add a comment -- that's what they're for!
# Endless loop
for p in players:
# Do game things...
Having said that, maybe you should StopIteration when there are no more players.

Related

How to make a Cage Fighting Simulation with user input instead of random for Python

Here is my code so far using random to pick moves:
import time
import random
PHealth = 10
CHealth = 10
PShots = [
"Great Body Shot To Your Opponent!",
"Nice Take Down!",
"Nice Punch!",
"Strong Kick!",
"You Have Him Pinned Against The Cage!",
"Excellent Counter-Shot!"
]
CShots = [
"You Took a Shot to the Body!",
"You Got Taken Down!",
"Strong Kick Hit You!",
"You Took A Big Punch!",
"You Are Pinned Against The Cage",
"Counter-Shot Got Ya!"
]
for i in range(20):
i = random.randint(0, 100)
if i >= 51:
print(random.choice(PShots))
CHealth = CHealth -1
if CHealth >= 1:
print("Player Health", PHealth)
print("Computer Health", CHealth)
time.sleep(5)
if i <= 50:
print(random.choice(CShots))
PHealth = PHealth -1
if PHealth >= 1:
print("Player Health", PHealth)
print("Computer Health", CHealth)
time.sleep(5)
if CHealth < 1:
print("What A Shot!")
time.sleep(1)
print("Down He Goes!")
time.sleep(1)
print("The Referee Has Stopped The Fight!!")
time.sleep(1)
print("Player Wins!!!")
break
if PHealth < 1:
print("What A Shot!")
time.sleep(1)
print("Down You Go!")
time.sleep(1)
print("The Referee Has Stopped The Fight!!")
time.sleep(1)
print("Computer Wins!!!")
break
Basically I'd like to understand how a player can input one move. So if a player inputs body shot it beats take down. If a player inputs kick it beats punch. If a player inputs take down it beats pinned against the cage, etc. Thinking 6-7 variations and counters.
Here is an idea of how you could implement something akin to what you seem to be looking for using a mix of classes and functions.
The following code should work with Python 3.9+ and has no additional dependencies.
First we define a Move class, instances of which need to have a name, a text_used (for when the player successfully uses the move), and a text_affected (for when move is used against the player). Each instance also stores a set of other Move objects, which it trumps, as well as a set of those it is trumped by. We have a helper method should_beat to easily define such a relationship between two moves.
class Move:
def __init__(self, name: str, text_used: str, text_affected: str, damage: int = 1) -> None:
self.name: str = name
self.text_used: str = text_used
self.text_affected: str = text_affected
self.damage: int = damage
self.trumps: set['Move'] = set()
self.trumped_by: set['Move'] = set()
def __str__(self) -> str:
return self.name
def should_beat(self, other_move: 'Move') -> None:
self.trumps.add(other_move)
other_move.trumped_by.add(self)
Next we define a Player class. Its instances have a name and an optional starting_health set to a previously defined constant by default.
A Player also has a use_move method that takes a Move object, another Player object (the opponent), and a second Move object (the move used by the opponent). That method checks which move beats which and calculates the health subtraction accordingly.
Finally, the Player object has win and lose methods that can be called to print out the win/loss statements when necessary.
class Player:
def __init__(self, name: str, starting_health: int = DEFAULT_STARTING_HEALTH) -> None:
self.name: str = name
self.health: int = starting_health
def __str__(self) -> str:
return self.name
def use_move(self, move: Move, vs_player: 'Player', vs_move: Move) -> None:
if vs_move in move.trumped_by:
self.health -= vs_move.damage
print(vs_move.text_affected)
elif move in vs_move.trumped_by:
vs_player.health -= move.damage
print(move.text_used)
else:
print(TEXT_NO_EFFECT)
def win(self, vs: 'Player') -> None:
print("What A Shot!")
sleep(1)
print(f"{vs} Goes Down!")
sleep(1)
print("The Referee Has Stopped The Fight!!")
sleep(1)
print(f"{self} Wins!!!")
def lose(self, vs: 'Player') -> None:
print("What A Shot!")
sleep(1)
print(f"Down You Go, {self}!")
sleep(1)
print("The Referee Has Stopped The Fight!!")
sleep(1)
print(f"{vs} Wins!!!")
Next, we want a function to define our moves and one that conveniently prints a list of moves to the terminal. Obviously you will want to expand the define_moves function to incorporate all your desired moves and their relationships. It should return a list of all your Move objects.
def define_moves() -> list[Move]:
kick = Move("kick", "Strong Kick!", "Strong Kick Hit You!")
punch = Move("punch", "Nice Punch!", "You Took A Big Punch!")
...
kick.should_beat(punch)
...
return [
kick,
punch,
]
def print_moves(moves_list: list[Move]) -> None:
print("Available moves:")
for i, move in enumerate(moves_list):
print(i, "-", move.name)
Now for the fun part, we need our main fighting loop. In each iteration, we prompt the player for a number that corresponds to an index in our list of moves defined earlier. (The player may also type h to see the moves again.) We do some checks to make sure we received a valid number to get our Move object.
Then we randomly chose a move for the computer opponent out of our moves list, and call our use_move method. It does the health calculations for us. So after that we just check, if someone is done to call the appropriate win or lose method and break out of the loop. Otherwise we print the current health stats and continue.
def fight_computer(player: Player, moves_list: list[Move]) -> None:
computer = Player(name="Computer")
while True:
string = input('Choose your move! (or type "h" to see available moves again)\n').strip().lower()
if string == 'h':
print_moves(moves_list)
continue
try:
i = int(string)
except ValueError:
print("You need to pick a number!")
continue
try:
move = moves_list[i]
except IndexError:
print("No move available with number", i)
continue
computer_move = choice(moves_list)
print(computer, "chose", computer_move)
player.use_move(move, vs_player=computer, vs_move=computer_move)
if player.health < 1:
player.lose(vs=computer)
break
if computer.health < 1:
player.win(vs=computer)
break
print(player, "health:", player.health)
print(computer, "health:", computer.health)
sleep(1)
Lastly, we need a main function to put it all together, prompt the player for his name, etc.
def main() -> None:
player_name = input("Enter your name: ").strip()
player = Player(player_name)
moves_list = define_moves()
print_moves(moves_list)
fight_computer(player, moves_list)
if __name__ == '__main__':
main()
Don't forget to add your imports and constant definitions to the start of the module:
from random import choice
from time import sleep
DEFAULT_STARTING_HEALTH = 10
TEXT_NO_EFFECT = "Your move had no effect!"
All together, this should give you a crude version of the game you described. Try it out. Hope this helps.

Attribute error from an object that isn't called upon [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am working on a Mastermind game in python, and one of my classes is called the Game class. This runs a 'setup' of the game as such (like finding the player count, player names etc.). However, one of my methods which checks the name inputted against a player list previously defined/stored in a separate class is bringing up an AttributeError when I try to append the name to a new list created in my Game class. This is what my Game class currently looks like:
class WorldOfMastermind:
"""WOM class - Runs whole game, takes results from other classes and stores them (namely players and their scores)"""
def __init__(self):
self.__playerList = []
self.__playerDetails = dict()
def run(self):
"""Run method - holds the menu screen - allows for the user to add player, show scores, play game or quit"""
cpuNames = ComputerPlayer.addDetails(self)
self.__playerList.extend((cpuNames))
start = input('What would you like to do?\n (r) register a new user\n (s) show the score board\n (p) play a game\n (q) quit\n')
if start == 'r':
tempName = HumanPlayer.addDetails(self)
for i in self.__playerList:
if i == tempName:
print('')
print('Sorry, that name already exists')
print('')
self.run()
self.__playerList.append(tempName)
self.__playerDetails[tempName] = [0, 0, float(0)]
print('Welcome,', tempName + '!')
print('')
self.run()
elif start == 's':
self.printScoreBoard()
elif start == 'p':
print('Let\'s play the game of Mastermind!')
Game.startPrep(self, self.__playerList)
elif start == 'q':
print('Thank you for playing the World of Mastermind!')
exit()
else:
print('\nSorry, that is an invalid input')
print('')
self.run()
def printScoreBoard(self):
""" Print the scoreboard by iterating through the dictionary """
print('=====================================')
print('Name Score Games Average ')
print('=====================================')
for i in self.__playerDetails:
print('{:<15} '.format(i), '{:>5}'.format(self.__playerDetails[i][0]), '{:>5}'.format(self.__playerDetails[i][1]), '{:>7}'.format(self.__playerDetails[i][2]))
print('=====================================\n')
self.run()
class Game:
"""Begin the initialization of the game and return results to WOM class"""
def __init__(self, playerCount):
self.__playerCount = playerCount
self.__playingList = []
def startPrep(self, playerList):
"""Prepares the game"""
Game.getPlayerCount(self)
Game.getPlayerNames(self, playerList)
def getPlayerCount(self):
"""Gathers the number of players"""
while True:
try:
self.__playerCount = int(input('How many players (2-4)?'))
except ValueError:
print('Only numbers allowed')
else:
if self.__playerCount < 2 or self.__playerCount > 4:
print('Player count must be between 2-4 inclusive')
else:
break
def getPlayerNames(self, playerList):
"""Gathers names of players and puts them into a list"""
while True:
if self.__playerCount == 2:
while True:
player1 = input('What is the name of player #1?')
if player1 in playerList:
print('successful')
self.__playingList.append(player1)
break
else:
print('Invalid username')
while True:
player2 = input('What is the name of player #2?')
if player2 in playerList:
if player2 not in self.__playingList:
print('successful')
self.__playingList.append(player2)
break
else:
print(player2, 'is already in the game.')
else:
print('Invalid username')
break
Where I feel the error is coming from is in the calling of the getPlayerNames method. As it takes a parameter (the player list from another class), this is purely to check that the name inputted is actually in the game, and if so it prints 'successful' (which it does) but when trying to append the inputted name into the new 'playingList' it brings up the error. I'm not sure why this is as the append line doesn't have any need to reference attributes from another class. Any advice would be appreciated thanks!
Your code works for me, formatted as below.. If I run the following, it asks for the player count and makes sure the names you give are in the eligible player list.
class Game:
"""Begin the initialization of the game and return results to WOM class"""
def __init__(self, playerCount=0):
self.__playerCount = playerCount
self.__playingList = []
def startPrep(self, eligible):
"""Prepares the game"""
self.getPlayerCount()
self.getPlayerNames(eligible)
def getPlayerCount(self):
"""Gathers the number of players"""
while True:
try:
self.__playerCount = int(input('How many players (2-4)?'))
except ValueError:
print('Only numbers allowed')
else:
if self.__playerCount < 2 or self.__playerCount > 4:
print('Player count must be between 2-4 inclusive')
else:
break
def getPlayerNames(self, playerList):
"""Gathers names of players and puts them into a list"""
for i in range(self.__playerCount):
while True:
s = 'What is the name of player #%d? '%(i+1)
player = input(s)
if player in playerList:
print('successful')
self.__playingList.append(player)
break
else:
print('Invalid username')
g = Game()
g.startPrep(['bob','bill'])

Why changing a function argument reflects to the main value that is I passed to that function?

I have tried to create a BLACKJACK game using python (actually I'm learning python). Currently I have not setup bet command (that is written in my Account class). I only takes name from my Account class.
I have a main file : blackjack.py
and two classes in files : deckofcards.py, account.py
I am only accessing name from account class, so I wont be putting that long mess here.
blackjack.py :
from account import Account
player = Account('kalaLokia')
cards = DeckOfCards()
play = False
playershand = []
dealershand = []
action = ''
blackjack = False
def showCards(items, name):
'''
Shows {name}'s cards and hand value
'''
print(f"{name}'s hand: ")
print(f"\t{' - '.join(items)}")
print(f"Hand value: {cards.handValue(items)}")
def bust(hand):
'''
Whether a someone has busted or not
'''
if(cards.handValue(hand) > 21):
return True
return False
def dealersMove():
'''
Dealers move: executes when player calls "stand"
Dealer perform hit until he gets bust, wins or his hand value becomes >= 17
When hand value is >17 and players has greater value, dealer loses ;-)
'''
global blackjack
if(cards.handValue(dealershand) == 21):
print('Dealer got a BLACKJACK')
print('Dealer WINS')
return
elif(blackjack):
print(f'{player.name} got a BLACKJACK')
print(f'{player.name} WINS')
blackjack=False
return
while(not bust(dealershand)):
if(cards.handValue(dealershand) > cards.handValue(playershand)):
print('Dealer WINS')
showCards(dealershand, 'Dealer')
break
elif(cards.handValue(dealershand) == cards.handValue(playershand)):
print("It's a TIE!!\n Dealer WINS")
break
elif(cards.handValue(dealershand) > 17):
print(f'Dealer loses\n{player.name} has WON.')
print(f'{cards.handValue(playershand)} > {cards.handValue(dealershand)}')
break
dealershand.append(cards.hit())
else:
print(f'Dealer busts! \n{player.name} has WON the game.')
def start():
'''
The actiona that can be performed
'''
global blackjack
if(cards.handValue(playershand) == 21):
blackjack = True
dealersMove()
return
while(not bust(playershand)):
action = input(
f"{player.name}'s turn: Do you want to hit or stand ? ").lower()
if(action == 'hit'):
playershand.append(cards.hit())
showCards(playershand, player.name)
elif(action == 'stand'):
dealersMove()
break
else:
print('Please enter a valid action !')
else:
print(f'{player.name} has been BUSTED')
if __name__ == "__main__":
print(f'Hello {player.name}, Welcome to BlackJack Game')
# Tell game rules here, may be
response = input('Do you want to start the game (Y/n)? ').lower()
if(response != 'y'):
play = False
print('You have been exited the game')
else:
play = True
# Ask for bet amount later
while(play):
cards = DeckOfCards()
cards.shuffle()
print('Cards on the table is now shuffled')
playershand = list(cards.initiate())
dealershand = list(cards.initiate())
print(
f"{player.name}'s hand:\n {playershand[0]} - {playershand[1]}\nHand value: {cards.handValue(playershand)}\n")
print(f"Dealer's hand:\n {dealershand[0]} - ?\n")
start()
if(input('Do you want to play again (Y/n)?').lower() != 'y'):
print('The End')
play = False
deckofcards.py :
import random
class DeckOfCards():
'''
All talks here is about cards
'''
cards = {'A':11,'K':10,'Q':10,'J':10,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'10':10}
def __init__(self):
'''
Initialize deck of cards
'''
self.deck = list(self.cards.keys())*4
def shuffle(self):
'''
Simply shuffles the deck of cards
'''
return random.shuffle(self.deck)
def handValue(self, hand):
'''
Calculates and returns the hand value, expecting a string value to be feeded.
'''
result = 0
for element in hand:
result = result + self.cards[element]
while('A' in hand and result > 21):
if(hand[0]=='A'):
result = result - 10
# Somehow this hand.pop is poping out from main value itself. Why ???
hand.pop(0)
if(hand == []):
break
return result
def hit(self):
'''
Pop out and returns the last card in the deck
'''
return self.deck.pop()
def initiate(self):
'''
Pop out 2 cards from the deck and return as a tuple
'''
return (self.deck.pop(), self.deck.pop() )
Issue:
When I have an ACE in my hand and my hand value is greater than 21, the while condition executes in the handValue function (which is in DeckofCards class) as it is. Problem is, after that while condition executes, playershand (declared in main file) I just passed to this handValue function gets empty. That is the hand.pop(0) actually seems popping out value from main object playershand itself (It seems me so).
When I press a hit after that, I get a single new card, all other cards are got popped out. I don't understand why it is so.
On hit(user enter hit) : actually I am passing playershand (cards on the player hand, it's a list) to function showCards (which is also in the main file) where it takes it as argument items and pass it to handValue function in the class DeckOfCards.
So why is it happening? even though I am passing playershand as an argument to other functions, how pop() function affecting playershand which has only access to hand object in the handValue class ?
I have my complete code in github repo to test out, the files in folder blackjack

Global variable playing keeps getting name error

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

Why doesn't my program go to game()?

My game gets caught in a loop and doesn't continue after the last self.custom_input in def __init__(self):. Why does it restart from the beginning instead of calling game()?
class game(object):
def __init__(self):
self.Continue = None
self.game = None
self.score = score()
while self.Continue == None:
self.Continue = raw_input("Question")
print "Good Luck...."
while self.game not in ("no", "quit", "leave", "n"):
self.rounds = self.custom_input("How many rounds would you like? ", self.games)
game()
def game(self):
while self.score.rounds != self.rounds:
self.score.rounds += 1
self.user_choice = custom_input("question",self.plays)
self.computer_choice = computer_choice()
result = evaluate()
if result == "win":
print "statement" %(self.user_choice.capitalize(), self.computer_choice)
self.score.wins += 1
elif result == "loss":
print "statement" %(self.computer_choice.capitalize(), self.user_choice)
self.score.losses += 1
else:
print "statement" %(self.user_choice.capitalize())
self.draws += 1
self.score.rounds += 1
finals()
You've named the game.game function with the same name as the game class, as well as the self.game attribute, and the interpreter is assuming that you're trying to create a new instance of the game class. To fix this, try renaming the game function to play_game, and then do this:
self.play_game()

Categories