M. Chen
M. Chen

Reputation: 155

Anyway to change my recursive function to return a value and be without global variables?

I learn python just about one month. This is a recursive function I worte for my Pygame to find the correct way in a polygon without retreat. It's just a Pentagon here, (0,1,2,3,4) are vertices' number.

However, this code works with two global variables:

last_poses = {}
route_all = []

This means I have to initialize those two variables every time I call it. And I also try to return the all the available route lines, but it didn't work properly.

This result comes from the global variable, it's correct:

[{0: 0, 1: 4, 2: 3, 3: 2, 4: 1, 5: 0}, {0: 0, 1: 4, 2: 3, 3: 2, 4: 1, 5: 0}]

This result comes from return value:

[{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 0}]

My question is to return the correct value without global variables. Anyone who can help me resolve this, I really appreciate that.

legal_action = ((4,1),(0,2),(1,3),(2,4),(0,3))

def route_cal(start_pos, steps):
    global last_poses,route_all
    last_poses[steps] = start_pos
    steps -= 1
    dest_all = list(legal_action[start_pos])

    if len(last_poses) >= 2:
        for i in dest_all:
            if i == last_poses[steps+2]:
                dest_all.remove(i)
    if steps > 0:
        for pos in dest_all:
            # route_cal(pos,steps)
            return route_cal(pos,steps)
    elif steps == 0:
        last_poses[steps] = dest_all[0]
        route_all.append(last_poses)
        return route_all
    # return route_all

last_poses = {}
route_all = []
# route_cal(0, 5)
# print route_all

routelines = route_cal(0,5)
print routelines

Circuit of my game

Upvotes: 0

Views: 287

Answers (3)

Prune
Prune

Reputation: 77880

In keeping with my earlier comment, here is a simple iterative way to traverse the polygon. It seems to give what you specified, without using a global variable or even recursion. Is this all you need?

def route_cal(start_node, move_list):
    # For each step in the circuit
    here = start_node
    path = [here]
    for step in range(len(move_list)):
        # Find any legal move to an adjacent vertex
        dest = move_list[here]
        for here in dest:
            if here not in path:    # Don't repeat a vertex
                path.append(here)
                break
    path.append(start_node)

    # Now that we've found the full circuit, build a dictionary in each direction
    path_len = len(path)
    forward = {n: path[n] for n in range(path_len)}
    reverse = {n: path[path_len-n-1] for n in range(path_len)}
    return [forward, reverse]


legal_action = ((4,1), (0,2), (1,3), (2,4), (0,3))
print route_cal(0, legal_action)

Upvotes: 0

mugabits
mugabits

Reputation: 1035

You have a few options.One of them is using an optional parameter. It looks like you can use route_all as an optional parameters.

e.g.

def route_cal(start_pos, steps, route_all = {}):

Remember that optional parameters get initialized once (the first time the function is called).

Another way is to get rid of dest_all and last_poses, and only use one variable, route_all, and append to it everyone you reach a point in your polygon, and only return that point.

return [route_all] + [recursive_call_here]

You can also look into not using your legal_actions variables and create the "neighbors" value as needed depending on the step number you are in.

There are other ways to minimize your problem and I recommend moving this question to the Code Review section to gain more insight about your code. For example, I would try to avoid using so many loops and instead use a formula that will calculate the "neighbors" when recursing through each step. Also, prevent reaching the Index out of range exception and/or the KeyError exception by making sure you don't access something it doesn't exists.

Upvotes: 0

John Kossa
John Kossa

Reputation: 459

The easiest answer is to use nonlocal instead of global. It's the same deal, but the variable is in a parent scope instead of the global one.

For your example, however, it looks like the parent scope of that function is the global one, so it won't change anything.

The more correct, but more difficult answer is if you want to get rid of external variable use, you're going to have to either pass the values into your function as parameters or return a tuple containing both of your currently global variables and your original return variable.

This question may help get you started.

Upvotes: 1

Related Questions