-1

This is for a school assesment. I have done all the criteria needed and want to add more code relating to functions. Basically it is a 'game' where the program asks if you want to help defend a nearby village. if you say yes it will give you a list of troops you can pick to take. then it runs this code (keep in mind my current code works perfectly)

while enemy_score>=0:
    if picked_troop == 1 or picked_troop == 2 or picked_troop == 3:
        shoot = input()
        if shoot == 'w':
            enemy_score -= random.randint(1, 10)
            print(enemy_score)
            if enemy_score<0:
                break

enemy_score has already been set to 50 and the 'if picked troop' line is to make sure that the shooting code needs to be run as shoot is greater than 0 at the start of the code (because shoot = 50). I tried changing the code to..

def kill(enemy_score=None):
    shoot = input()
    if shoot == 'w':
        enemy_score -= random.randint(1, 10)
        print(enemy_score)

so i replaced everything from shoot = input() with kill,,,,, however when i do this the program takes the random number of 0 when the w key is pressed, and then returns to 50 again. so in the console it looks like this

w
46
w
47
w
46
w
48

how can i make this a continuous so it looks like

w
47
w
41
w
31
etc
DYZ
  • 51,549
  • 10
  • 60
  • 87
  • `enemy_score` is the function parameter. When you call the function, it acts like a local variable. Changing a local variable does not modify any namesake global variables. You either have to declare `global enemy_score` or return the new value from the function. – DYZ Nov 19 '18 at 02:53

1 Answers1

0

The problem is scope. The enemy_score in your function kill() is not the same enemy_score as exists outside of the function. Say you have this arrangement:

enemy_score = 50
...
def kill(enemy_score):
    enemy_score -= 10
    print(enemy_score)

print(enemy_score)
kill(enemy_score)
print(enemy_score)

You'll see that that the output of this snippet is

50
40
50

in other words, the enemy_score from the outer scope clearly doesn't change, whereas the enemy_score inside the function clearly does.


The thing is, when you define kill(enemy_score=...), what you're doing is saying "I want a function called kill, and I want it to be called with one argument, which is assigned to a variable called enemy_score." Python knows that you already have an enemy_score variable, but you declared that outside this function, and clearly if you're defining it differently inside the function, then so long as you're inside the function, python will use the version from inside the function. The outer enemy_score and inner enemy_score are different variables, and as a result changing the inner enemy_score does not change the outer enemy_score.

When python calls a function with a variable (e.g. kill(enemy_score)), it doesn't pass in the variable itself (called pass-by-reference - some other programming languages do this, and if this was the case then changing the inner enemy_score would change the outer enemy_score). Rather, it passes-by value - it copies the value of enemy_score and sends that to the function.


Now, there are two ways to address this problem. The first is, instead of passing in enemy_score as a variable, to inherit it from the global scope:

enemy_score = 50
...
def kill():
    global enemy_score   # <----
    enemy_score -= 10
    print(enemy_score)

print(enemy_score)
kill()
print(enemy_score)

This prints 50 40 40.

The fact that you have to say global enemy_score is a weird quirk of python - but you need to do it when you want to bring a variable from the global namespace inside a function.

The second solution would be to have kill() return the value of the inner enemy_score, after it's been changed, and then assign that to the outer enemy_score:

enemy_score = 50
...
def kill(enemy_score):
    enemy_score -= 10
    print(enemy_score)
    return enemy_score    # <----

print(enemy_score)
enemy_score = kill(enemy_score)
print(enemy_score)

This also prints 50 40 40, as expected.

Both of these solutions are pretty common, though which is "better" to use depends on the situation. In this case I would recommend using the second version.

Green Cloak Guy
  • 22,147
  • 4
  • 26
  • 47
  • as to which is better, refer to https://stackoverflow.com/questions/19158339/why-are-global-variables-evil – njzk2 Nov 19 '18 at 04:28