The_Mach34
The_Mach34

Reputation: 13

Is there a more efficient way to write a really long "if elif" chain in python?

I quite a beginner to real programming languages and I am using Python to write a long if elif chain to check x and y variables as coordinates and depending on the coordinates it would do something different. (This is for a text-based adventure game)

This is what I have now and I was wondering how I could do it in a much nicer way.

if x == 1 and y == 1:
    dothis()
elif x == 1 and y == 2:
    dothat()
elif x == 1 and y == 3:
    doANewThing()
elif x == 1 and y == 3:
    doSomethingDif()

Except this appears over 900 times. I hate it. Please Help.

Upvotes: 0

Views: 240

Answers (2)

John Kugelman
John Kugelman

Reputation: 361739

I'll take a guess that each of the cases represents a different room in the game, and you want to call a different function for each room.

A good pattern for this is to separate your data from the code. Treat the coordinates and the function for each room as data, extract them into some sort of room list. All you need for the code is to check the player's coordinates, find the corresponding room function, and call it.

Data

A dictionary is perfect for looking up things. Let's treat the x,y coordinates as keys and the functions as values.

rooms = {
    (1, 1): dothis,
    (1, 2): dothat,
    (1, 3): doANewThing,
    (1, 4): doSomethingDif,
    # etc.
}

Notice how the function names don't have parentheses after them. It's dothis and dothat, not dothis() and dothat(). We're only listing the names of the functions here; we're not actually calling them.

Code

try:
    # Look up the function for the current room...
    room_function = rooms[(x, y)]

    # ...And call it.
    room_function()

# Error! Didn't find an entry for (x, y).
except KeyError:
    handle_error()

What's great about this is you can easily add new rooms to the dictionary without having to write any new if-else blocks. In fact, there are no if-else blocks!

Upvotes: 1

Cireo
Cireo

Reputation: 4427

Based on your short description, you probably have a different problem than you think you do =).

For example, if I was writing a program to handle the first move of a chess game, I wouldn't write out all 4096 options in the function move(x, y, new_x, new_y).

Try taking a look at dictionaries or a matrix (list of list) and move towards a 'lookup -> object action' model. For example:


class Thing(object):
    DESCRIPTION = 'undescribable beauty'
    def describe(self):
        return self.DESCRIPTION

class Wall(Thing):
    DESCRIPTION = 'a plain old wall'

class Townsfolk(Thing):
    DESCRIPTION = 'an angry ten-year-old'

class Nothing(Thing):
    DESCRIPTION = 'only the darkness of your soul'

map = {}  # coordinate -> thing
# TODO: load this from ascii art
map[(0, 0)] = Wall()
map[(0, 1)] = Townsfolk()
map[(0, 2)] = Wall()

def look_at(pos):
    item = map.get(pos, Nothing())
    print("You see %s" % item.describe())
>>> look_at((0,0))
You see a plain old wall
>>> look_at((0,3))
You see only the darkness of your soul

Upvotes: 1

Related Questions