Python Strategy Game – Take the Last Stone

Here’s a fun game. Play it first with a friend if you can. Start with a number between 10 and 20. Take it in turns to subtract either one or two from the number. The player to take the last stone wins. Make sure you both get to go first.

Next explore how this works using an actual pile of stones/pebbles, or if you don’t have any, anything handy where there are multiple identical items. I ended up using drawing pins!

Is there a winning strategy? Does it depend on who starts? If there is a winning strategy, what is it? Are there some situations where you can’t win if your opponent uses a particular strategy?

Spend some time thinking about this and doing experiments. Maybe write your results on some paper and see if there is a pattern.

It is definitely worth spending some time thinking and experimenting with this game. I have written the answer below and you can reveal it by clicking “show solution”. If you give up too early though you will deny yourself the opportunity to strengthen your thinking skills and also to feel the satisfaction that comes when you figure out these kinds of things for yourself.

Python Program for Last Stone Strategy Game

Below you will find a code listing for a Python program that simulates playing this game against an opponent.

When learning to program with Python or any other programming language, you should definitely actually type in code examples for yourself in most situations. Doing so will provide a much more effective learning experience than simply copy/pasting code and running it. There are several reasons for this, which I won’t go into now, but take my word for it and type in the provided code.

The code may or may not be a little above your level of ability to understand fully. If so, you should just type it in anyway. You will find that by doing so, some understanding will seep in “by osmosis”, and then when you have run the code a few times and come back to look at it, you will likely find it makes sense a lot more sense than it did to begin with.

The program is written using functions, and these are a programming construct that you definitely need to master if you intend to take programming at all seriously, so this is a good place to get on board. The functions are named in a fairly self-explanatory way as are the variables in the program (this is a very important habit to get into from the start – don’t use names like num and val in your programs for example, as they don’t provide enough information to anyone who reads you code, including you when you come back to it after a while…)

Here is the Python code listing for the Last Stone Game:

"""
Take the Last Stone game.
A simple console game where the player takes turns with the computer to remove 1 or two stones from a pile of stones.
The player to take the last stone wins.
Robin Andrews - https://compucademy.net
"""

import random
import os

START_NUM = 11
LEVEL = 1  # Only 1 and 2 available
if LEVEL not in [1, 2]:
    raise ValueError("That level isn't available. 1 or 2 only.")


def print_title():
    print(r"""
.____                     __      _________ __                        
|    |   _____    _______/  |_   /   _____//  |_  ____   ____   ____  
|    |   \__  \  /  ___/\   __\  \_____  \\   __\/  _ \ /    \_/ __ \ 
|    |___ / __ \_\___ \  |  |    /        \|  | (  <_> )   |  \  ___/ 
|_______ (____  /____  > |__|   /_______  /|__|  \____/|___|  /\___  >
        \/    \/     \/                 \/                  \/     \/ 
    """)


def choose_player():
    if random.randint(0, 1) == 0:
        return "human"
    else:
        return "computer"


def player_turn():
    global current_number
    player_choice = input("Take away 1 or 2 stones? ")
    while player_choice not in ["1", "2"]:
        player_choice = input("Invalid input. Take away 1 or 2 stones? ")
    player_choice = int(player_choice)
    current_number = current_number - player_choice
    print()
    if current_number <= 0:
        print("You win!")


def computer_turn():
    global current_number
    if LEVEL == 1:
        computer_choice = random.randint(1, 2)
    elif LEVEL == 2:
        # Computer cannot win from this position if opponent plays correctly.
        if current_number % 3 == 0:
            computer_choice = 1  # Arbitrary as can't force win. Could be 2 as well.
        elif current_number % 3 == 1:
            # Move 1 stone and make the opponent lose
            computer_choice = 1
        elif current_number % 3 == 2:
            # Move 2 stones and make the opponent lose
            computer_choice = 2
    current_number = current_number - computer_choice
    print(f"Computer turn. The computer chooses {computer_choice}.")
    print()
    if current_number <= 0:
        print("The computer wins!")


def play_again():
    print()
    return input("Would you like to play again (yes or no)? ").lower().startswith("y")


def main():
    global current_number
    lets_play_again = True

    while lets_play_again:
        current_number = START_NUM
        current_player = choose_player()
        print_title()

        while current_number > 0:
            print(f"The current number is {current_number}.")
            print()
            if current_player == "human":
                player_turn()
                current_player = "computer"
            else:
                computer_turn()
                current_player = "human"
        if not play_again():
            lets_play_again = False

    print()
    print("Goodbye!")


if __name__ == "__main__":
    main()

Here’s a few point about the code:

  • The title is printed using ASCII art – you can click the link to learn more.
  • There are 2 levels. Level 1 uses a random choice to determine the opponent move, whereas level 2 uses the strategy.
  • The START_NUM constant can be used to change the initial number of stones.
  • There is a nested while loop to allow repeat play.
  • Don’t worry about global. It just makes current_number available throughout the program. Context is everything: Global Variables Will Break the Internet.

I hope you found that interesting and useful. If you would like to learn Python programming from me, why not get in touch and we can discuss you learning needs.

Happy Computing!

Sharing is caring!

Leave a Reply

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