Reputation: 1662
I am working through a python programming book and one of the chapters has a blackjack game. I am running through this exercise to find errors in the program and handle it. One of the errors is that I am asking for a number of players in a range between 1 and 7. So in theory, I should be able to have up to 7 players in this game. When I run the program however I unable to add more than 1 player. If I say I want any other number than 1, it just repeats the question.
Here is the games
module where I ask the yes/no and number question:
# Games
# Demonstrates module creation
class Player(object):
""" A Player for the game """
def __init__(self, name, score=0):
self.name = name
self.score = score
def __str__(self):
rep = self.name + ":\t" + str(self.score)
return rep
def ask_yes_no(question):
""" Ask a yes or no question """
response = None
while response not in ("y", "n"):
response = input(question).lower()
return response
def ask_number(question, low, high):
""" Ask for a number within a range """
response = None
while response not in (low, high):
response = int(input(question))
return response
if __name__ == "__main__":
print("You ran this module directly (and did not 'import' it).")
input("\n\nPress the ENTER key to exit.")
And here is the module I am calling the one above from:
# Blackjack
# From 1 to 7 players compete against a dealer
import python_programming_absolute_beginner.chapter_9.cards as cards
import python_programming_absolute_beginner.chapter_9.games as games
class BlackjackCard(cards.Card):
""" A Blackjack Card """
ACE_VALUE = 1
@property
def value(self):
value = BlackjackCard.RANKS.index(self.rank) + 1
if self.is_face_up:
if value > 10:
value = 10
else:
value = None
return value
class BlackjackDeck(cards.Deck):
""" A Blackjack Deck """
def populate(self):
for suit in BlackjackCard.SUITS:
for rank in BlackjackCard.RANKS:
self.cards.append(BlackjackCard(rank, suit))
class BlackjackHand(cards.Hand):
""" A Blackjack Hand """
def __init__(self, name):
super(BlackjackHand, self).__init__()
self.name = name
def __str__(self):
rep = self.name + ":\t" + super(BlackjackHand, self).__str__()
if self.total:
rep += "(" + str(self.total) + ")"
return rep
@property
def total(self):
# if a card in the hand has a value of None, then total is None
for card in self.cards:
if not card.value:
return None
# add up card values, treat each Ace as 1
t = 0
for card in self.cards:
t += card.value
# determine if hand contains an Ace
contains_ace = False
for card in self.cards:
if card.value == BlackjackCard.ACE_VALUE:
contains_ace = True
# if hand contains Ace and total is low enough treat Ace as an 11
if contains_ace and t <= 11:
# add only 10 since we've already added 1 for the Ace
t += 10
return t
def is_busted(self):
return self.total > 21
class BlackjackPlayer(BlackjackHand):
""" A Blackjack Player """
def is_hitting(self):
response = \
games.ask_yes_no("\n" + self.name + ", do you want a hit? (Y/N): ")
return response == "y"
def bust(self):
print(self.name, "busts.")
self.lose()
def lose(self):
print(self.name, "loses.")
def win(self):
print(self.name, "wins.")
def push(self):
print(self.name, "pushes.")
class BlackjackDealer(BlackjackHand):
""" A Blackjack Dealer """
def is_hitting(self):
return self.total < 17
def bust(self):
print(self.name, "busts.")
def flip_first_card(self):
first_card = self.cards[0]
first_card.flip()
class BlackjackGame(object):
""" A Blackjack Game """
def __init__(self, names):
self.players = []
for name in names:
player = BlackjackPlayer(name)
self.players.append(player)
self.dealer = BlackjackDealer("Dealer")
self.deck = BlackjackDeck()
self.deck.populate()
self.deck.shuffle()
# Check the card count, and if it is less than 10 repopulate and
# reshuffle
@property
def still_playing(self):
sp = []
for player in self.players:
if not player.is_busted():
sp.append(player)
return sp
def __additional_cards(self, player):
while not player.is_busted() and player.is_hitting():
self.deck.deal([player])
print(player)
if player.is_busted():
player.bust()
def play(self):
# deal initial 2 cards to everyone
self.deck.deal(self.players + [self.dealer], per_hand=2)
self.dealer.flip_first_card() # hide dealer's first card
for player in self.players:
print(player)
print(self.dealer)
# deal additional cards to players
for player in self.players:
self.__additional_cards(player=player)
self.dealer.flip_first_card() # reveal the dealer's first card
if not self.still_playing:
# since all players have busted, just show the dealer's hand
print(self.dealer)
else:
# deal additional cards to dealer
print(self.dealer)
self.__additional_cards(self.dealer)
if self.dealer.is_busted():
# everyone still playing wins
for player in self.still_playing:
player.win()
else:
# compare each player still playing to the dealer
for player in self.still_playing:
if player.total > self.dealer.total:
player.win()
elif player.total < self.dealer.total:
player.lose()
else:
player.push()
# remove everyone's cards
for player in self.players:
player.clear()
self.dealer.clear()
def main():
print("\t\tWelcome to Blackjack!")
names = []
number = games.ask_number("How many players? (1 - 7): ", low=1, high=8)
for i in range(number):
name = input("Enter player name: ")
names.append(name)
print()
game = BlackjackGame(names)
again = None
while again != "n":
game.play()
again = games.ask_yes_no("\nDo you want to play again?: ")
main()
input("\n\nPress the ENTER key to exit.")
I am not really sure why this is only allowing 1 player instead of up to 7?
Upvotes: 0
Views: 431
Reputation: 4164
There is a logical error in the loop in your main due to improper indentation.
You have
def main():
print("\t\tWelcome to Blackjack!")
names = []
number = games.ask_number("How many players? (1 - 7): ", low=1, high=8)
for i in range(number):
name = input("Enter player name: ")
names.append(name)
print()
#still in the loop, game starts now with first player
game = BlackjackGame(names)
again = None
while again != "n":
game.play()
again = games.ask_yes_no("\nDo you want to play again?: ")
This will start the game immediately after the first player is entered.
You want the body of the for loop to just deal with adding players and only start the game after all the players have been added.
The code should be:
def main():
print("\t\tWelcome to Blackjack!")
names = []
number = games.ask_number("How many players? (1 - 7): ", low=1, high=8)
for i in range(number):
name = input("Enter player name: ")
names.append(name)
print()
#only start the game after all players are added
game = BlackjackGame(names)
again = None
while again != "n":
game.play()
again = games.ask_yes_no("\nDo you want to play again?: ")
Upvotes: 3
Reputation: 72
As I see it, there's a problem in this line of code:
while response not in (low, high) #It checks if variable response equals only 1 or 8.
Try changing it to:
while response not in range(low, high) #This checks if variable response equals any number between 1 and 8
Upvotes: 1