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 Console 21 Game
You can play the game against the computer using this trinket – just click the
run button to start.
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
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() == "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(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.