开发者

Python - 2 Questions: Editing a variable in a function and changing the order of if else statements internally/during runtime

开发者 https://www.devze.com 2022-12-28 23:03 出处:网络
First of all, I should explain what I\'m trying to do first. I\'m creating a dungeon crawler-like game, and I\'m trying to program the movement of computer characters/monsters in the map. The map is

First of all, I should explain what I'm trying to do first.

I'm creating a dungeon crawler-like game, and I'm trying to program the movement of computer characters/monsters in the map. The map is basically a Cartesian coordinate grid. The locations of characters are represented by tuples of the x and y values, (x,y). The game works by turns, and in a turn a character can only move up, down, left or right 1 space. I'm creating a very simple movement system where the character will simply make decisions to move on a turn by turn basis. Essentially a 'forgetful' movement system.

A basic flow chart of what I'm intending to do:

  1. Find direction towards destination
  2. Make a priority list of movements to be done using the direction eg.('r','u','d','l') means it would try to move right first, then up, then down, then left.
  3. Try each of the possibilities following the priority order. If the first movement fails (blocked by obstacle etc.), then it would successively try the movements until the first one that is successful, then it would stop.

At step 3, the way I'm trying to do it is like this:

def move(direction,location):
    try:
        -snip- # Tries to move, raises the exception Movementerror if cannot move in the direction
        return 1 # Indicates movement successful
    except Movementerror:
        return 0 # Indicates movement unsuccessful (thus character has not moved yet)

prioritylist = ('r','u','d','l')
if move('r',location): pass
elif move('u',location): pass
elif move('d',location): pass
elif move('l',location): pass
else: pass

In the if/else block, the p开发者_高级运维rogram would try the first movement on the priority on the priority list. At the move function, the character would try to move. If the character is not blocked and does move, it returns 1, leading to the pass where it would stop. If the character is blocked, it returns 0, then it tries the next movement.

However, this results in 2 problems:

1.How do I edit a variable passed into a function inside the function itself, while returning if the edit is successful?

I have been told that you can't edit a variable inside a function as it won't really change the value of the variable, it just makes the variable inside the function refer to something else while the original variable remain unchanged. So, the solution is to return the value and then assign the variable to the returned value. However, I want it to return another value indicating if this edit is successful, so I want to edit this variable inside the function itself. How do I do so?

2.How do I change the order of the if/else statements to follow the order of the priority list? It needs to be able to change during runtime as the priority list can change resulting in a different order of movement to try.


Re 2., I would change your relatively-big if/elif tree to a simple loop:

prioritylist = ('r','u','d','l')
for direction in prioritylist:
  if move(direction, location): break

less repetitious, easier to extend in the future if you want to allow diagonal steps or whatever -- and automatically "follows the priority list" in whatever order it's in, without any need to change your code itself.

Re 1., you can return multiple values from a function:

def move(direction,location):
    try:
        -snip-
        return True, newlocation
    except Movementerror:
        return False, location

and you would then change the above loop to, e.g.:

prioritylist = ('r','u','d','l')
for direction in prioritylist:
  success, newlocation = move(direction, location)
  if success: break

else: newlocation = location

using the else branch of the for, which executes if no break happens in the for, to deal with the case in which no attempt produced a success.


You can use a for-loop, and break out of the loop at the first successful choice:

for option in prioritylist:
    if move(option,location): # succeeded
        break

You should also return True or False, instead of a 1 or 0, as it makes the intention clearer.

Also, I should add that the statement about not editing a parameter is not entirely true... you cannot edit the parameter, itself, but you can edit the contents of that parameter assuming it is a mutable object. Tuples, which you are using, are immutable and so cannot be modified, but lists can be modified:

positions = ['N','S','E','W']

def mutate_list(p):
     p.reverse()

print positions # prints ['N', 'S', 'E', 'W']
mutate_list(positions)
print positions # prints ['w', 'E', 'S', 'N']
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号