Super simple terminal blackjack for codecademy
Tags: codecademy, python, learnin, beginners
Published: 2023-02-16 01:30:27

Hello there,

since Codecademy recommends creating a post about so called portfolio projects, I just went ahead and created this account. So, mostly I will probably just write this for myself.

The task was to create a simple game you can play with the terminal input.

I simply checked their example ideas and picked blackjack since all my own ideas went way bigger then it should be for this.

So I restricted the game to have an easier time coding:

- Fixed bet of 2 coins (starting with 10)
- The dealer just finishes every round just like in multiplayer games
- When less then 8 cards are left, the game ends

This is how it looks:


The user can choose to draw another card, stay, or double (in the first round)


**Classes**
Pretty straightforward I just created one class for the deck. Even that seemed silly in the end but having the draw function on the deck class seems right enough to make it an own class.

> `class Deck:
>     def __init__(self, number_of_decks):
>         self.deck_count = 0
>         self.number_of_decks = number_of_decks
>         self.cards = one_color * 4 * number_of_decks
>         random.shuffle(self.cards)
>     def draw(self):
>         card = self.cards.pop()
>         if card in card_value_plus:
>             self.deck_count += 1
>         elif card in card_value_minus:
>             self.deck_count += -1
>         return card`

I considered making a class for the player/dealer but a simple list that gets reset after every round is all thats really needed, since the coins are also just a global instance since we only have one player.



**Calculating the hand value**
Since the ace is pretty unique I dealt with it in a way that I sort the list descending before actually counting. Therefore I can see if the value will be 1 or 10:

> `def value_of_hand(cards):    
>     cards.sort(reverse=True)
>     total = 0
>     for value in cards:
>         if value == 1 and total < 11:
>             total += 11
>         elif value > 10:
>             total += 10
>         else:
>             total += value
>     return total`

The bad thing with this is that it still not account for a second ace. Then it would not reset the first one to just one point but would result in a bust.


**Card counting**
I considered to maybe use this to train counting cards. Therefore I added value list and so and a deck count and true count function in the deck:

> `card_value_plus = [2,3,4,5,6] 
> card_value_minus = [0,10,11,12,13]
> def get_true_count(self):
>         return round(self.deck_count / (len(self.cards) / 52))`

The true count is relevant since I let the player choose how many decks he wants to play through.

During the draw the value gets added to the deck count like this:

> `if card in card_value_plus:
>             self.deck_count += 1
>         elif card in card_value_minus:
>             self.deck_count += -1`

Using the in keyword here is a bad idea since simple operations like <7 would be way faster. I just read about different evalutions so I considered making lists to have the option to maybe let the user choose an evalution type.


**Refactoring**
I already did refactor how I draw a random card. First, I had a sorted deck and popped a random element but then I discovered the shuffle function in the random module and thought this is a way better way. Now I just keep popping the last element and shuffle the deck in the beginning.

Other things I should probably refactor (but probably wont) are:

1. Naming list for cards have a placeholder for the first element so I can start with 1 as ace and then just go up. Somehow get rid of the placeholder (confusing in the long term but I liked not to up the index before getting the name).

Maybe use a dict.

2. Remove lists for card counting. 

Rather use direct comparions

3. Rework the print statements while finishing the dealer to avoid duplicated code.

Use an output function giving the cards to print.

4. If the user wants to double in the first round I only use the multiplier while ending the round but then need to check for extra losses. 

Should withdraw 2 coins when double gets placed.

5. Block double in second round and if coins are too low


Then of course there are still basic black jack rules missing like insurance or adjustable bets before the round and splitting twins.

If anyone wants to comment or actually refactor stuff feel free to check out the [repo](https://github.com/charichu/blackjack)

EDIT: If you know ,please let me know why I need quotes for my code and the markdown for code seems to be breaking all the time.