I made blackjack with Python.

Introduction

The Advent calendar was free, so I'll write it again. This time, as the title suggests, I made blackjack.

Click here for the previous article → I made a fortune with Python.

environment

Ubuntu18.04LTS Python3.6.9 vim

code

play_bj.py


from random import shuffle


class Deck:
    """
Class representing the deck
    """
    def __init__(self):
        """
Initialize the deck and shuffle it.
        """
        suits = ['spade', 'club', 'diamond', 'heart']
        values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K']
        self.deck = []
        for i in suits:
            for j in values:
                self.deck.append((i, j))
        shuffle(self.deck)

    def draw(self):
        """
Draw one card from the deck and return the drawn card.
        """
        return self.deck.pop(0)


class Person:
    """
Class representing the player
    """
    def __init__(self):
        """
Initialize your hand.
        """
        self.hands = []
        self.point = 0

    def add(self, card):
        """
Add a card to your hand.
        """
        self.hands.append(card)

    def point_sum(self):
        """
Find the total score of playing cards.
        """
        self.point = 0
        for i in self.hands:
            if i[1] in ['J', 'Q', 'K']:
                self.point += 10
            else:
                self.point += i[1]

        return self.point


def BJ():
    """
Main processing
    """
    print('Welcome to Blackjack!')

    d = Deck()
    p = Person()
    c = Person()

    drawing(d, p, 'you')
    drawing(d, p, 'you')

    drawing(d, c, 'CPU')
    card = d.draw()
    c.add(card)

    player_point = p.point_sum()
    cpu_point = c.point_sum()

    if player_point == cpu_point == 21:
        print('It's a draw.')
        return
    elif player_point == 21:
        print('You win!')
        return
    elif cpu_point == 21:
        print('You lose.')
        return
    #Here, A does not become 11, so the above conditional branch is not really necessary.

    while True:
        choice = input('"Hit"Or"Stand"Please enter.: ')

        while True:
            if choice.lower() == 'hit' or choice.lower() == 'stand':
                break
            else:
                choice = input('"Hit"Or"Stand"Please enter.: ')

        if choice.lower() == 'hit':
            drawing(d, p, 'you')
            player_point = p.point_sum()
            if player_point >= 22:
                print('You lose.')
                return
        elif choice.lower() == 'stand':
            break
        else:
            print('error')
            return

    print('Another card of CPU is{}of{}is.'.format(c.hands[1][0], c.hands[1][1]))

    while True:
        cpu_point = c.point_sum()
        if cpu_point < 17:
            drawing(d, c, 'CPU')
            cpu_point = c.point_sum()
            if cpu_point >= 22:
                print('You win!')
                return
        else:
            break

    if player_point == cpu_point:
        print('It's a draw.')
        return
    elif player_point > cpu_point:
        print('You win!')
        return
    elif player_point < cpu_point:
        print('You lose.')
        return


def drawing(class1, class2, name):
    """
Add 1 card from the deck to your hand.
After that, the information of the added card is displayed.
    """
    card = class1.draw()
    class2.add(card)
    print('{}The card drawn by{}of{}is.'.format(name, card[0], card[1]))


if __name__ == '__main__':
    BJ()

in conclusion

It was a good study of functions and classes. Next, let's make A compatible with 11 as well. I will add it as soon as a better one is made.

Postscript

I organized the code by using class inheritance and so on. Also, 11 can be supported for A. (12/09) Added error handling and argparse. (12/16) Added logging. (01/04)

import argparse
import logging
from logging import getLogger, StreamHandler, FileHandler, Formatter
import sys
from random import shuffle


logger = getLogger(__file__)
logger.setLevel(logging.DEBUG)

stream_handler = StreamHandler()
file_handler = FileHandler('debug.log')

stream_handler.setLevel(logging.DEBUG)
file_handler.setLevel(logging.DEBUG)

stream_format = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_format = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

stream_handler.setFormatter(stream_format)
file_handler.setFormatter(file_format)

logger.addHandler(stream_handler)
logger.addHandler(file_handler)


class Card:
    SUITS = 'spade', 'club', 'diamond', 'heart'
    RANKS = 'A', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K'

    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank
        self.number = self.RANKS.index(rank) + 1


class Deck:
    def __init__(self):
        self.deck = [Card(suit, rank)
                     for suit in Card.SUITS
                     for rank in Card.RANKS]
        shuffle(self.deck)

    def draw(self):
        return self.deck.pop()


class Participant:
    def __init__(self, name):
        self.name = name
        self.hands = []
        self.point = []

    def drawing(self, card, display=True):
        self.hands.append(card)
        self.point.append(min(card.number, 10))
        if display:
            print('{}The card drawn by{}of{}is.'
                  .format(self.name, card.suit, card.rank))


class Player(Participant):
    def choose_a_first(self):
        in_a = any(card.rank == 'A' for card in self.hands)
        while in_a and sum(self.point) <= 11:
            try:
                choice_point = input('Do you want A to be 1 or 11?: ')
            except (KeyboardInterrupt, EOFError):
                print()
                print('Blackjack has ended.')
                sys.exit()
            else:
                if choice_point == '11':
                    self.point.append(10)
                    break
                if choice_point == '1':
                    break
        print('{}The total score of{}is.'.format(self.name, sum(self.point)))

    def choose_a(self):
        while self.hands[-1].rank == 'A' and sum(self.point) <= 11:
            try:
                choice_point = input('Do you want A to be 1 or 11?: ')
            except (KeyboardInterrupt, EOFError):
                print()
                print('You have finished blackjack.')
                sys.exit()
            else:
                if choice_point == '11':
                    self.point.append(10)
                    break
                if choice_point == '1':
                    break
        print('{}The total score of{}is.'.format(self.name, sum(self.point)))

    def is_continue(self):
        while True:
            try:
                choice = input('Enter Hit or Stand.: ').lower()
            except (KeyboardInterrupt, EOFError):
                print()
                print('Blackjack has ended.')
                sys.exit()
            else:
                print()
                if choice == 'hit':
                    return True
                if choice == 'stand':
                    return False


class Dealer(Participant):
    def choose_a_first(self):
        in_a = any(card.rank == 'A' for card in self.hands)
        if in_a and sum(self.point) <= 11:
            self.point.append(10)

    def choose_a(self):
        if self.hands[-1].rank == 'A' and sum(self.point) <= 11:
            self.point.append(10)
        print('{}The total score of{}is.'.format(self.name, sum(self.point)))

    def show_card(self):
        print('{}Another card of{}of{}is.'
              .format(self.name, self.hands[1].suit, self.hands[1].rank))
        print('{}The total score of{}is.'.format(self.name, sum(self.point)))
        print()

    def is_continue(self):
        if sum(self.point) < 17:
            return True
        else:
            return False


class BlackJack:
    def __init__(self):
        try:
            name = input('Please enter your name.: ')
        except (KeyboardInterrupt, EOFError):
            print()
            print('Blackjack has ended.')
            sys.exit()
        else:
            self.deck = Deck()
            self.player = Player(name)
            self.dealer = Dealer('dealer')

    def play(self):
        print()
        self.player.drawing(self.deck.draw())
        self.player.drawing(self.deck.draw())
        self.player.choose_a_first()
        print()
        self.dealer.drawing(self.deck.draw())
        self.dealer.drawing(self.deck.draw(), False)
        self.dealer.choose_a_first()
        print()

        j_21 = self.judje_21(sum(self.player.point), sum(self.dealer.point))
        if j_21:
            logger.info('Natural 21')
            return

        while self.player.is_continue():
            self.player.drawing(self.deck.draw())
            self.player.choose_a()
            print()
            if sum(self.player.point) >= 22:
                print('{}Is defeated.'.format(self.player.name))
                logger.info('Player bust')
                return

        self.dealer.show_card()

        while self.dealer.is_continue():
            self.dealer.drawing(self.deck.draw())
            self.dealer.choose_a()
            print()

        self.judje(sum(self.player.point), sum(self.dealer.point))

    def judje_21(self, player_point, dealer_point):
        if player_point == dealer_point == 21:
            print('{}Is also Natural 21.'.format(self.dealer.name))
            print('It's a draw.')
            return True
        elif player_point == 21:
            print('{}Is the winner.'.format(self.player.name))
            return True
        elif dealer_point == 21:
            print('{}Is Natural 21.'.format(self.dealer.name))
            print('{}Is defeated.'.format(self.player.name))
            return True

    def judje(self, player_point, dealer_point):
        if player_point == dealer_point:
            print('It's a draw.')
        elif player_point > dealer_point or dealer_point >= 22:
            print('{}Is the winner.'.format(self.player.name))
        elif player_point < dealer_point:
            print('{}Is defeated.'.format(self.player.name))


def get_parser():
    parser = argparse.ArgumentParser(description='You can play blackjack on the terminal.')

    parser.add_argument('-q', '--qiita', action='store_true', help='Qiita link with source code')
    parser.add_argument('-r', '--rules', action='store_true', help='Explain the rules of blackjack')

    args = parser.parse_args()
    return args


def main():
    args = get_parser()
    if args.qiita:
        print('https://qiita.com/yoshige/items/d06382f2a8b76ce6cd79')
        return

    if args.rules:
        print('Click here for blackjack rules')
        print('https://ja.wikipedia.org/wiki/black Jack')
        return

    logger.info('start')
    print('Welcome to Blackjack!')
    bj = BlackJack()
    bj.play()
    logger.info('end')

if __name__ == '__main__':
    main()

Recommended Posts

I made blackjack with python!
I made blackjack with Python.
I made a simple blackjack with Python
I made wordcloud with Python.
I made a fortune with Python.
I made a daemon with Python
I made a character counter with Python
I made a Hex map with Python
I made a roguelike game with Python
I made a configuration file with Python
I made a neuron simulator with Python
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I made a GUI application with Python + PyQt5
I made a Twitter fujoshi blocker with Python ①
[Python] I made a Youtube Downloader with Tkinter.
I made a bin picking game with Python
I made a Mattermost bot with Python (+ Flask)
I tried fp-growth with python
I tried scraping with Python
I made a python text
I tried gRPC with Python
I made COVID19_simulator with JupyterLab
I tried scraping with python
I made Word2Vec with Pytorch
Othello made with python (GUI-like)
I made a Twitter BOT with GAE (python) (with a reference)
I made a Christmas tree lighting game with Python
I made a net news notification app with Python
I made a LINE BOT with Python and Heroku
SNS Python basics made with Flask
I made a Line-bot using Python!
I can't install python3 with pyenv-vertualenv
I tried web scraping with python.
Numer0n with items made in Python
I sent an SMS with Python
I liked the tweet with python. ..
I played with PyQt5 and Python3
I want to debug with Python
I tried running prolog with python 3.8.2.
I tried SMTP communication with Python
I made a simple typing game with tkinter in Python
I made a package to filter time series with python
I made LINE-bot with Python + Flask + ngrok + LINE Messaging API
I made a simple book application with python + Flask ~ Introduction ~
[I made it with Python] XML data batch output tool
I made a puzzle game (like) with Tkinter in Python
Life game with Python [I made it] (on the terminal & Tkinter)
I made a simple circuit with Python (AND, OR, NOR, etc.)
I made a library to easily read config files with Python
I made a package that can compare morphological analyzers with Python
Statistics with python
I made Othello to teach Python3 to children (4)
I made a payroll program in Python!
Simple Slack API client made with Python
HTTP split download guy made with Python
Python with Go
I tried scraping Yahoo News with Python
I drew a heatmap with seaborn [Python]
I made Othello to teach Python3 to children (2)
I started python