Question

I am working on a simple game which involves 2 players. Each player has two counters which they can move individually by selecting them. Player 1 has counters 1 and 1, whilst player 2 has counters 3 and 4. In order to prevent a player from moving one of their opponents counters I have written the following recursive function.

It works fine if no one 'cheats'.

If a player cheats, the function gets them to re-enter a correct counter number. This is carried through to the final return statement as expected.

However instead of returning a correct counter number at this point it appears to take another step and change it to the initial wrong value. It is as if the code has remembered all the values of the variable counter that have been tried during the recursion and cycles through them at the end before returning whatever was the first one.

What am I missing?

def get_counter(current_player):
    counter = int(input("Select which counter you want to move."))
    if counter != 1 and counter != 2 and current_player == 1:
        print("This is not your counter")
        print("Your counters are 1 or 2")
        get_counter(current_player)
    elif counter != 3 and counter != 4 and current_player == 2:
        print("This is not your counter")
        print("Your counters are 3 or 4")
        get_counter(current_player)
    return counter
Was it helpful?

Solution

You are calling the function recursively but don't return the recursive result. Add return statements:

def get_counter(current_player):
    counter = int(input("Select which counter you want to move."))
    if counter != 1 and counter != 2 and current_player == 1:
        print("This is not your counter")
        print("Your counters are 1 or 2")
        return get_counter(current_player)
    elif counter != 3 and counter != 4 and current_player == 2:
        print("This is not your counter")
        print("Your counters are 3 or 4")
        return get_counter(current_player)
    return counter

Without explicitly returning the result of the recursive get_counter() call, the calling function continues where it had left off before the call, and executes the return counter statement instead. The local counter variable is not shared between recursive function calls, so it's the first choice the player made that is eventually returned from the outermost call.

However, don't underestimate the ability of your users to continue to try and cheat; you'll eventually run into the maximum recursion depth. You shouldn't really use recursion to handle user input; use a loop instead:

def get_counter(current_player):
    while True:
        counter = int(input("Select which counter you want to move."))
        if current_player == 1 and counter not in (1, 2):
            print("This is not your counter")
            print("Your counters are 1 or 2")
            continue
        if current_player == 2 and counter not in (3, 4):
            print("This is not your counter")
            print("Your counters are 3 or 4")
            continue
        return counter

This returns only if a correct count has been entered; it continues with the loop (reasking the question) if incorrect entries have been made instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top