Вопрос

I need to write these four ifs in Python. Notice what it does, is changing between four possible states in a loop: 1,0 -> 0,1 -> -1,0 -> 0,-1 and back to first.

if [dx, dy] == [1,0]:
    dx, dy = 0, 1
if [dx, dy] == 0, 1:
    dx, dy = -1, 0
if [dx, dy] == [-1, 0]
    dx, dy = 0, -1
if [dx, dy] == [0, -1]:
    dx, dy = 1, 0

Can anyone suggest me a better/nicer way to write this?

Это было полезно?

Решение

dx, dy = -dy, dx

When in doubt, apply maths. ;)

Другие советы

Magnus' suggestion is undeniably the right answer to your question as posed, but generally speaking, you want to use a dictionary for problems like this:

statemap = {(1, 0): (0, 1), (0, 1): (-1, 0), (-1, 0): (0, -1), (0, -1): (1, 0)}

dx, dy = statemap[dx, dy]

Even in this case I could argue using a dictionary is better, since it's clear that there are exactly four states and that they repeat, but it's hard to resist the sheer beauty of all teh maths.

By the way, the code in your question has a bug in it, and, assuming that the values you test for are the only possible values, is equivalent to:

dx, dy = 1, 0

The bug is that you need elif for the second and subsequent conditions, otherwise you're continuing to test dx and dy after changing them. If they're 1 and 0, then all your conditions will be true and they end up the same at the end! If they start out as 0 and 1 then the second and all subsequent conditions will be true, and you again end up with 1, 0. And so on...

Just extending Magnus answer. If you imagine [dx, dy] as a vector, what you're actually doing is a rotation of 90 degrees (or PI/2).

To calculate this, you can use the following transformation:

two dimensional rotation

Which in your case translate to:

x = x * cos(90) - y * sin(90)
y = x * sin(90) + y * cos(90)

Since sin(90) = 1 and cos(90) = 0 we simplify it to:

x, y = -y, x

And there you have it!

The values you're working with appear to be a unit vector that continuously rotates - in other words, a phasor. Complex numbers are coordinates, so:

# at initialization
phase = 1
# at the point of modification
phase *= 1j
dx, dy = phase.real, phase.imag

Assuming my interpretation of the meaning of the dx,dy values is correct, this gives you extra flexibility in case it turns out later that you want to rotate by some other amount in each step.

While I would go with Magnus' answer, here's yet another approach for rotating over a set of values:

def rotate(*states):
    while 1:
        for state in states:
            yield state

for dx, dy in rotate((1, 0), (0, 1), (-1, 0), (0, -1)):
    pass

Note that there should be a break somewhere in the for dx, dy loop or else it will never end.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top