DarthOpto
DarthOpto

Reputation: 1662

Python - Blackjack game not getting anymore than 1 player

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

Answers (2)

paisanco
paisanco

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

Igor Hwang
Igor Hwang

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

Related Questions