The 21 Game with Python Turtle Graphics

Here’s something fun.

The 21 Game is a two-player counting game where each player can add 1, 2, or 3, starting at zero, to the total. the total must not exceed 21 and the player who lands on 21 loses.

Python Code Listing for the 21 Game

It is often a great idea to run Python code using an installed version of Python on your computer rather than in a browser. One reason is that some browser-based implementations have subtly different behaviors to a “real” Python installation, and another is that sooner or later if you are serious about Python programming, you will need to work with a full version that allows installation of packages and access to your file system. So here is the full code listing for Python 3.

"""
The 21 Game - Compucademy
"""

import random
import time


while True:

    print(r"""
      _______ _            ___  __    _____                      
     |__   __| |          |__ \/_ |  / ____|                     
        | |  | |__   ___     ) || | | |  __  __ _ _ __ ___   ___ 
        | |  | '_ \ / _ \   / / | | | | |_ |/ _` | '_ ` _ \ / _ \
        | |  | | | |  __/  / /_ | | | |__| | (_| | | | | | |  __/
        |_|  |_| |_|\___| |____||_|  \_____|\__,_|_| |_| |_|\___|

    """)

    current_number = 1

    if random.randint(0, 1) == 0:
        current_player = "human"
    else:
        current_player = "computer"

    while current_number <= 21:

        print("The current number is " + str(current_number) + ".")
        print()

        if current_player == "human":

            print("Add 1, 2, or 3. Do not pass 21. The player who lands on 21 loses.")

            player_choice = ""
            while player_choice not in ["1", "2", "3"]:
                player_choice = input("What will you add? ")

            player_choice = int(player_choice)
            current_number = current_number + player_choice
            print()

            if current_number >= 21:
                print("The current number is " + str(current_number) + ".")
                print()
                print("Sorry, you lose.")
                break
            current_player = "computer"

        else:

            computer_choice = random.randint(1, 3)
            current_number = current_number + computer_choice
            print("Computer turn. The computer choses " +
                  str(computer_choice) + ".")
            print()
            time.sleep(1)

            if current_number >= 21:
                print("The current number is " + str(current_number) + ".")
                print()
                print("Well done, you won!")
                break
            current_player = "human"

    print()
    play_again = input("Do you want to play again? ")
    if play_again.lower().startswith("y"):
        continue
    else:
        print("Goodbye")
        break

This book is a great introduction to creating games using Python:

As an Amazon Associate I earn from qualifying purchases.

Strategy for the 21 Game

The computer opponent in the program above is not using any particular strategy, so with a bit of clever thinking, you may be able to find a strategy that allows you to win all or most of the time, perhaps depending on who starts. One way to explore this is with the help of a visual representation. With Python, one of my favourite tools for creating visual representations is the Turtle Graphics Module.

You can run the code in a browser using the embedded repl.it frame below. I have use repl.it insted of trinket.io to embed the code as repl.it has better support for some of the Turtle Graphics methods I use in the code.

The code allows you to toggle the color of the squares in the representation of the game so you can see how you might win. If you need a hint on the strategy, think what might constitute a “safe square.”

Here is the full code listing. You can use the buttons at the top to copy the code if if you need to.

import turtle

TURTLE_SIZE = 20  # This is the default for a `square` turtle
SQUARE_SIZE = 20
FONT_SIZE = 12
FONT = ('Arial', FONT_SIZE, 'normal')


def toggle(box):
    """Toggles the colour of a Turtle when it is clicked."""
    if box.color()[0] == "Red":
        box.color("Green")
    else:
        box.color("Red")

# Screen setup
screen = turtle.Screen()
screen.setup(600, 200)
screen.title("The 21 Game")
screen.bgcolor("black")
# Disable animation
screen.tracer(0)

# Create 21 clickable squares
for i in range(21):
    box = turtle.Turtle("square")

    def click_callback(x, y, box=box):
        """Passes `box` to `toggle()` function."""
        return toggle(box)

    box.shapesize(SQUARE_SIZE / TURTLE_SIZE)
    box.color("Red")
    box.penup()
    box.goto(-231 + i * (SQUARE_SIZE + 2), 0)
    box.onclick(click_callback)

# Write numbers above the squares
pen = turtle.Turtle(visible=False)
pen.color("white")
pen.penup()
pen.goto(-231, 22)
for i in range(21):
    pen.write(str(i + 1), align="center", font=FONT)
    pen.forward(22)

# Restore animation
screen.tracer(1)
turtle.done()

Hopefully the comments will help to understand how this code works, but there are couple of things to point out.

  • The click callback (the function that is called when a click event is detected on a turtle) needs an additional parameter so it can be attached to a particular turtle. This had me stumped for a while, but then I found this link which explains how to do it. If you don’t know, the Turtle Module is build on Tkinter, so solving Turtle-related problems can involve thinking about what’s going on with Tkinter.

  • To save having to wait for the drawing to take place, I have used screen.tracer(0) then screen.tracer(1) to re-enable animation once the drawing is complete.

The “extra arguments” trick means that creating this code from scratch is more of an intermediate exercise than one for beginners, but as a demo of what’s possible with Python Turtle Graphics as well as a useful way to help you become an expert at the 21 Game, I think it’s pretty neat.

I hope you enjoy playing this game and exploring the Python code it uses.

Sharing is caring!

Leave a Reply

Your email address will not be published. Required fields are marked *