简体   繁体   中英

Why does this one chunk of code come up with error but the other one doesn't?

I have two sections of Python code - one works and the other one comes up with an error. What rule makes this the case?

Here is the chunk of code that got the error, along with the error:

Code:

elif door == "2": 
    print "You stare into the endless abyss at Cthulhu's retina."
    print "1. blueberries."
    print "2. Yellow jacket clothespins."
    print "3. Understanding revolvers yelling melodies."

    insanity = raw_input("> ")

    if insanity == "1" or insanity == "2": 
        print "Your body survives powered by a mind of jello. Good job!" 
        print "Now what will you do with the jello?"
        print "1. Eat it."
        print "2. Take it out and load it in a gun."
        print "3 Nothing."

        jello = raw_input("> ")

        if jello == "1" or jello == "2":
            print "Your mind is powered by it remember? Now you are   dead!"
        elif jello == "3":
            print "Smart move. You will survive." 
        else:
            print "Do something!" 

else: 
    print "The insanity rots your eyes into a pool of muck. Good job!"

I got this error message in prompt:

  File "ex31.py", line 29
  print "Now what will you do with the jello?"
                                           ^
IndentationError: unindent does not match any outer indentation level

BUT when my code is like this:

elif door == "2": 
print "You stare into the endless abyss at Cthulhu's retina."
print "1. blueberries."
print "2. Yellow jacket clothespins."
print "3. Understanding revolvers yelling melodies."

insanity = raw_input("> ")

if insanity == "1" or insanity == "2": 
    print "Your body survives powered by a mind of jello. Good job!" 
        print "Now what will you do with the jello?"
        print "1. Eat it."
        print "2. Take it out and load it in a gun."
        print "3 Nothing."

        jello = raw_input("> ")

        if jello == "1" or jello == "2":
            print "Your mind is powered by it remember? Now you are dead!"
        elif jello == "3":
            print "Smart move. You will survive." 
        else:
            print "Do something!" 

else: 
    print "The insanity rots your eyes into a pool of muck. Good job!"

I get no error message.

Basically my question is - why do I not get an error message if I indent the line

print "Now what will you do with the jello?"

...and the rest of the block of code below it.

But I get an error code if I leave it with the same indentation as the line above it?

Does this mean that the print line after an if statement can only be one line in total, with no other print lines allowed to be linked to the output of the if statement above the first print line of that block?

Thanks.

I suspect you're mixing spaces and tabs. It's best to use only spaces so that your visual indentation matches the logical indentation.

Examining your source code, there's a tab character in the second line here:

    if insanity == "1" or insanity == "2": 
\t    print "Your body survives powered by a mind of jello. Good job!" 
        print "Now what will you do with the jello?"

I've marked it with \\t , which makes the mixed up indentation stick out.

You're not indenting after the elif at the top of this code:

elif door == "2": 
print "You stare into the endless abyss at Cthulhu's retina."
print "1. blueberries."
print "2. Yellow jacket clothespins."
print "3. Understanding revolvers yelling melodies."

Have you tried:

elif door == "2": 
    print "You stare into the endless abyss at Cthulhu's retina."
    print "1. blueberries."
    print "2. Yellow jacket clothespins."
    print "3. Understanding revolvers yelling melodies."

and see what happens?

Have you checked that your indentation is consistent? Are you using 4 spaces everywhere (not tabs)? I cut and paste your code from your first example(starting from the insanity raw input) and it ran fine on my machine.

Off on a tangent:

As you are already finding out, trying to do a story of any size with cascading if-else clauses very quickly becomes unwieldy.

Here is a quick state-machine implementation that makes it easy to write a story room-by-room:

# assumes Python 3.x:

def get_int(prompt, lo=None, hi=None):
    """
    Prompt user to enter an integer and return the value.

    If lo is specified, value must be >= lo
    If hi is specified, value must be <= hi
    """
    while True:
        try:
            val = int(input(prompt))
            if (lo is None or lo <= val) and (hi is None or val <= hi):
                return val
        except ValueError:
            pass

class State:
    def __init__(self, name, description, choices=None, results=None):
        self.name        = name
        self.description = description
        self.choices     = choices or tuple()
        self.results     = results or tuple()

    def run(self):
        # print room description
        print(self.description)

        if self.choices:
            # display options
            for i,choice in enumerate(self.choices):
                print("{}. {}".format(i+1, choice))
            # get user's response
            i = get_int("> ", 1, len(self.choices)) - 1
            # return the corresponding result
            return self.results[i]    # next state name

class StateMachine:
    def __init__(self):
        self.states = {}

    def add(self, *args):
        state = State(*args)
        self.states[state.name] = state

    def run(self, entry_state_name):
        name = entry_state_name
        while name:
            name = self.states[name].run()

and your story rewritten to use it

story = StateMachine()

story.add(
    "doors",
    "You are standing in a stuffy room with 3 doors.",
    ("door 1", "door 2",  "door 3"  ),
    ("wolves", "cthulhu", "treasury")
)

story.add(
    "cthulhu",
    "You stare into the endless abyss at Cthulhu's retina.",
    ("blueberries", "yellow jacket clothespins", "understanding revolvers yelling melodies"),
    ("jello",       "jello",                     "muck")
)

story.add(
    "muck",
    "The insanity rots your eyes into a pool of muck. Good job!"
)

story.add(
    "jello",
    "Your body survives, powered by a mind of jello. Good job!\nNow, what will you do with the jello?",
    ("eat it",   "load it into your gun", "nothing"),
    ("no_brain", "no_brain",              "survive")
)

story.add(
    "no_brain",
    "With no brain, your body shuts down; you stop breathing and are soon dead."
)

story.add(
    "survive",
    "Smart move, droolio!"
)

if __name__ == "__main__":
    story.run("doors")

For debugging, I added a method to StateMachine which uses pydot to print a nicely formatted state graph,

# belongs to class StateMachine
    def _state_graph(self, png_name):
        # requires pydot and Graphviz
        from pydot import Dot, Edge, Node
        from collections import defaultdict

        # create graph
        graph = Dot()
        graph.set_node_defaults(
            fixedsize = "shape",
            width     = 0.8,
            height    = 0.8,
            shape     = "circle",
            style     = "solid"
        )

        # create nodes for known States
        for name in sorted(self.states):
            graph.add_node(Node(name))

        # add unique edges;
        ins  = defaultdict(int)
        outs = defaultdict(int)
        for name,state in self.states.items():
            # get unique transitions
            for res_name in set(state.results):
                # add each unique edge
                graph.add_edge(Edge(name, res_name))
                # keep count of in and out edges
                ins[res_name] += 1
                outs[name]    += 1

        # adjust formatting on nodes having no in or out edges
        for name in self.states:
            node = graph.get_node(name)[0]
            i = ins[name]
            o = outs.get(name, 0)
            if not (i or o):
                # stranded node, no connections
                node.set_shape("octagon")
                node.set_color("crimson")
            elif not i:
                # starting node
                node.set_shape("invtriangle")
                node.set_color("forestgreen")
            elif not o:
                # ending node
                node.set_shape("square")
                node.set_color("goldenrod4")

        # adjust formatting of undefined States
        graph.get_node("node")[0].set_style("dashed")
        for name in self.states:
            graph.get_node(name)[0].set_style("solid")

        graph.write_png(png_name)

and calling it like story._state_graph("test.png") results in

在此处输入图片说明

I hope you find it interesting and useful.

Things to think about next:

  • room inventory: things you can pick up

  • player inventory: things you can use or drop

  • optional choices: you can only unlock the red door if you have the red key in inventory

  • modifiable rooms: if you enter the secluded grove and set it on fire, it should be a charred grove when you return later

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM