2

I'm programming a text based adventure game in Python, where the player moves on a 5x5 grid and picks up items, but I'm having trouble with changing the co-ordinates of the player. coorx and coory are not incrementing and decrementing within their respective functions.

coorx = 3 #The beginning x coordinate of the player
coory = 3 #The beginning y coordinate of the player

loop = True
#The dimensions of the map are 5x5.
# __ __ __ __ __
#|  |  |  |  |  |
#|__|__|__|__|__|
#|  |  |  |  |  |
#|__|__|__|__|__|
#|  |  |><|  |  |
#|__|__|__|__|__|
#|  |  |  |  |  |
#|__|__|__|__|__|
#|  |  |  |  |  |
#|__|__|__|__|__|
#>< = The player's starting position on the map

def left(coorx):
    if coorx != 1: #This checks if the x co-ordinate is not less than 1 so the player does walk off the map.
        coorx -= 1 #This function moves the player left by decrementing the x co-ordinate.

def right(coorx):
    if coorx != 5: #This checks if the x co-ordinate is not more than 5 so the player does walk off the map.
        coorx += 1 #This function moves the player right by incrementing the x co-ordinate.

def back(coory):
    if coory != 1: #This checks if the y co-ordinate is not less than 1 so the player does walk off the map.
        coory -= 1 #This function moves the player left by decrementing the y co-ordinate.

def forward(coory):
    if coory != 5: #This checks if the y co-ordinate is not more than 5 so the player does walk off the map.
        coory += 1 #This function moves the player right by incrementing the y co-ordinate.


while loop: #This loops as long as the variable "loop" is True, and since "loop" never changes, this is an infinite loop.
    move = input().lower()

    if move == "l":
        left(coorx)
        print("You move left.")
        print(coorx, coory)
    elif move == "r":
        right(coorx)
        print("You move right.")
        print(coorx, coory)
    elif move == "f":
        forward(coory)
        print("You move forward.")
        print(coorx, coory)
    elif move == "b":
        back(coory)
        print("You move backwards.")
        print(coorx, coory)

This is what is output.

>f
>You move forward.
>3 3
>f
>You move forward.
>3 3
>l
>You move left.
>3 3
>l
>You move left.
>3 3
>b
>You move backwards.
>3 3
>b
>You move backwards.
>3 3
>r
>You move right.
>3 3
>r
>You move right.
>3 3

As you can see, the co-ordinates do not change from "3 3" throughout. Any assistance with my problem would be greatly appreciated.

iolim5678
  • 91
  • 8
  • they are, within the functions. You must return the new value to use it outside the function. – Jasper Feb 25 '16 at 20:34

5 Answers5

3

Your coordinates are global, but you haven't declared them global so they are being shadowed by a local variable with the same name. You need to declare them global with your functions to be able to modify them.

Option one (without globals):

def left(x_coord):
    if x_coord != 1: 
        x_coord -= 1
    return x_coord # Do something with this

Option two:

def left():
    global coorx
    if coorx != 1:
        coorx -= 1

You can read more about globals here and here

aneroid
  • 12,983
  • 3
  • 36
  • 66
Michal Frystacky
  • 1,418
  • 21
  • 38
  • 1
    This is wrong an will still fail because the function gets an argument `coorx` so the body of the function can never use `global coorx`. – aneroid Feb 25 '16 at 20:44
  • 1
    Yeah, I missed something stupid during my answer as well :-/ – aneroid Feb 25 '16 at 20:56
1

Just read something that reminded me of this question. One way to change your co-ordinates without needing to return a value or use global is to use a mutable container type:

>>> coor = [3, 3]  # x, y
>>>
>>> def left():
...     if coor[0] != 1:
...         coor[0] -= 1
...
>>>
>>> left()
>>> coor
[2, 3]
>>>

What's happening here is that the variable coor is only referenced, not assigned to. What you're assigning to is in that container, not the variable coor itself. This uses the implicit existence of the global coor within left() when it's not assigned-to in the same function.

(I guess this is what I had in mind in the first version of my previous answer.)

This will also work with dictionaries, and is a bit more readable:

>>> coor = dict(x=3, y=3)
>>>
>>> def left():
...     if coor['x'] != 1:
...         coor['x'] -= 1
...
>>>
>>> left()
>>> coor
{'x': 2, 'y': 3}
>>>
aneroid
  • 12,983
  • 3
  • 36
  • 66
0

Your variables are changing locally. Use global to solve the problem. You can also solve the problem using arguments and returning coordiantes.

Cosinux
  • 321
  • 1
  • 4
  • 16
0

You're passing coorx and coory as values to functions with the argument name as coorx and coory. That makes local references to coorx and coory instead of the global.

Edit: You need to specify global coorx and global coory at the top of each function.

Also, in your function defs for left, right, back and forward, you shouldn't use the same parameter names. Also, in your specific case, you don't need to pass these functions any arguments because left() is move left. It doesn't need an argument as per your functionality.

def left():
    global coorx
    ...  # rest as per your code

def right():
    global coorx
    ...  # rest as per your code

def back():
    global coory
    ...  # rest as per your code

def forward():
    global coory
    ...  # rest as per your code
aneroid
  • 12,983
  • 3
  • 36
  • 66
  • 1
    You can't use the `+=` or `-=` operators on a global variable without a `global` declaration. You'll get an `UnboundLocalError`. This is true even if in-place addition is supported (which it's not for integers). – Blckknght Feb 25 '16 at 20:43
  • @Blckknght My bad, don't know what I was thinking. I was mixing up "referencing-only" vs "referencing-and-assignment" in one function. – aneroid Feb 25 '16 at 20:58
0

There a problem in your "move" functions:

  • there are "coorx" and "coory" in the global scope (you set both to 3)
  • every "move" function has a parameter (coorx or coory) which is local to the function

What your functions are doing is changing the local variable (parameter) which is discarded after the function returns. Global variables don't get changed.

Anyhow, using global variables and changing them this way is a bad programming practice. This task really "asks for" implementation as a class with relevant class properties (self.coorx) and methods that let you "move around":

http://www.diveintopython3.net/iterators.html#defining-classes

CaptSolo
  • 1,771
  • 1
  • 16
  • 17