Одна расстраивающая ошибка в условном выражении в Python - PullRequest
0 голосов
/ 12 августа 2011

Как видно из названия, у меня есть одна ошибка в скрипте для игры, которую я создаю. У меня внутри определенной функции есть оператор if, который должен выполняться, только если переменная меньше единицы. Но когда функция запускается, даже если эта переменная равна или больше единицы, оператор if все еще выполняется и не переходит к else. Вот мой исходный код:

from sys import exit
from sys import argv
from random import shuffle
import random


script = argv


#-------------------------------------------------------------------------

start_room = "your starting point"
top_room = "room with a magical orb"
top_hallway = "long hallway"
mask_room = "room with a golden mask"
fog_hallway = "hallway filled with fog"
fountain_hallway = "hallway with the magical fountain of life at the end"
bottom_room = "room with a magical fire burning in the centre"
bottom_hallway = "round tunnel infested with huge rats"
electric_hallway = "hallway with an electric feel, a crackling in the air"
i = 0
numbers = []
death_toll = 0

#-------------------------------------------------------------------------

def dead():
    print "You died."
    exit(0)

# next few lines to def cheat_death() will be for generating random numbers for use in cheat_death()
while i < 6:
    numbers.append(random.randrange(1,9000))

    i = i + 1

# Now, using the six numbers generated above, I'll turn the string list of numbers[], make it a floating number, and then put them into a question.
# Using this question, if the user answers correctly, they will be taken to start(). If not, they will go to dead().

def cheat_death(numbers):
    shuffle(numbers)

    question = "%d + %d - %d + %d - %d + %d" % tuple(numbers)

    print "You have a single chance to cheat death. To live, please answer the question correctly below:"
    print question

    answer = eval(question)
    print answer

    user_answer = raw_input("> ")

    death_toll == death_toll + 1

    if str(user_answer) == str(answer) and death_toll < 1:
        start()
    else:
        dead()

def end_of_hallway_four():
    print "You come to the end of the hallway.\n\tYou find a big gold coin on the top of a pedestal, sitting on a padded seat."
    print "Around the pedestal there is a wide circle of metal."
    print "Would you like to take the expensive gold coin?"

    take_coin = raw_input("> ")

    if take_coin == "yes" or take_coin == "y" or take_coin == "sure" or take_coin == "yeah":
        cheat_death(numbers)
    elif take_coin == "no" or take_coin == "n":
        print "Very wise indeed."
        exit(0)
    else:
        cheat_death(numbers)

def hallway_four():
    print "You are now in a %s" % electric_hallway
    print "Would you like to see what's at the end of the hallway?"

    end_of_hallway = raw_input("> ")

    if end_of_hallway == "yes" or end_of_hallway == "y" or end_of_hallway == "sure":
        end_of_hallway_four()
    elif end_of_hallway == "no" or end_of_hallway == "n" or end_of_hallway == "nah":
        print "You don't know what you're missing!"
        exit(0)
    else:
        cheat_death(numbers)

def hallway_three():
    print "You are now in a %s" % fountain_hallway
    print "Would you care for a drink of the fountain of life?"

    drink = raw_input("> ")

    if drink == "yes" or drink == "y" or drink == "sure" or drink == "yeah":
        print "You feel very much rejuvinated, and full of energy. You'll live forever!"
        exit(0)
    elif drink == "no" or drink == "n":
        print "Feeling suddenly tired, you quit your journey for a quick nap."
        exit(0)
    else:
        cheat_death(numbers)

def hallway_two():
    print "You are now in a %s" % fog_hallway
    print "Would you like to follow the door at the end of the hallway?"

    hallway_two_door = raw_input("> ")

    if hallway_two_door == "yes" or hallway_two_door == "y" or hallway_two_door == "yeah" or hallway_two_door == "sure":
        hallway_three()
    elif hallway_two_door == "no" or hallway_two_door == "n":
        hallway_one()
    else:
        cheat_death(numbers)

def gold_room():
    print "You are in a %s" % mask_room
    print "Do you take the valuable mask?"

    take_mask = raw_input("> ")

    if take_mask == "yes" or take_mask == "y" or take_mask == "yeah" or take_mask == "sure":
        cheat_death(numbers)
    elif take_mask == "no" or take_mask == "n" or take_mask == "nah":
        print "Wise indeed."
        hallway_one()
    else:
        cheat_deaath()

def rat_hallway():
    print "You are now in a %s" % bottom_hallway
    print "Do you want to follow the light at the end of the tunnel?"

    follow_light = raw_input("> ")

    if follow_light == "yes" or follow_light == "y" or follow_light == "sure" or follow_light == "yeah":
        print "You find yourself at the end of the tunnel, where there is a single door. You follow this door."
        hallway_four()
    elif follow_light == "no" or follow_light == "n":
        exit(0)
    else:
        cheat_death(numbers)

def hallway_one():
    print "You are now in a %s" % top_hallway
    print "At the end of the %s, you find two doors. One looks gold plated, and the other one looks moist and mossy.\nWhich one do you take?" % top_hallway

    top_hallway_door = raw_input("> ")

    if top_hallway_door == "1":
        gold_room()
    elif top_hallway_door == "2":
        hallway_two()
    else:
        cheat_death(numbers)

def fire_room():
    print "You are now in a %s" % bottom_room
    print "Would you like to go through door #1, or door #2?\nYou came from door #2."

    fire_door = raw_input("> ")

    if fire_door == "1":
        rat_hallway()
    elif fire_door == "2":
        start()
    else:
        cheat_death(numbers)

def orb_room():
    print "You are now in a %s" % top_room
    print "There are two doors you could take. Which one do you choose?"

    orb_door = raw_input("> ")

    if orb_door == "1":
        start()
    elif orb_door == "2":
        hallway_one()
    else:
        cheat_death(numbers)

def start_game_question():    
    print """
    You will be asked a series of questions.
    Your answer will either take you to a different room, or perform an action.
    If you come to a point where you are exited from the game, don't quit!
    There's many more rooms to discover!"""
    print "\nTo answer questions, either enter the door number,\nor answer with a word if asked."
    print "\nYour progress will NOT be saved."
    print "To restart the game, just enter python %s." % script
    print "\n\nAre you read to play?"

    start_game = raw_input("> ")

    if start_game == "yes" or start_game == "y" or start_game == "sure" or start_game == "yeah":
        start()
    elif start_game == "no" or start_game == "n" or start_game == "nah":
        exit(0)
    else:
        "Please try again."
        start_game_question()

def start():
    print "You are now at %s." % start_room
    print "Would you like to go through door #1 or door#2?"

    starting_door = raw_input("> ")

    start_door = starting_door

    if start_door == 1:
        orb_room()
    elif start_door == 2:
        fire_room()
    else:
        cheat_death(numbers)

start_game_question()

А вот соответствующие функции:

i = 0
numbers = []
death_toll = 0

def dead():
    print "You died."
    exit(0)

# next few lines to def cheat_death() will be for generating random numbers for use in cheat_death()
while i < 6:
    numbers.append(random.randrange(1,9000))

    i = i + 1

# Now, using the six numbers generated above, I'll turn the string list of numbers[], make it a floating number, and then put them into a question.
# Using this question, if the user answers correctly, they will be taken to start(). If not, they will go to dead().

def cheat_death(numbers):
    shuffle(numbers)

    question = "%d + %d - %d + %d - %d + %d" % tuple(numbers)

    print "You have a single chance to cheat death. To live, please answer the question correctly below:"
    print question

    answer = eval(question)
    print answer

    user_answer = raw_input("> ")

    death_toll == death_toll + 1

    if str(user_answer) == str(answer) and death_toll < 1:
        start()
    else:
        dead()

Код конкретной проблемы:

    def cheat_death(numbers):
    shuffle(numbers)

    question = "%d + %d - %d + %d - %d + %d" % tuple(numbers)

    print "You have a single chance to cheat death. To live, please answer the question correctly below:"
    print question

    answer = eval(question)
    print answer

    user_answer = raw_input("> ")

    death_toll == death_toll + 1

    if str(user_answer) == str(answer) and death_toll < 1:
        start()
    else:
        dead()

Поэтому я добавил в функцию выпуска глобальный дескриптор и отредактировал пару других строк, чтобы получить эту функцию ниже:

def cheat_death (числа): перетасовать (число)

    question = "%d + %d - %d + %d - %d + %d" % tuple(numbers)

    print "You have a single chance to cheat death. To live, please answer the question correctly below:"
    print question

    answer = eval(question)
    print answer

    user_answer = raw_input("> ")

    global death_toll

    death_toll = death_toll +1

    if str(user_answer) == str(answer) and death_toll == 1:
        start()
    else:
        dead()

А вот и вывод терминала о возникшей проблеме:

nathan @ jolicloud: ~ / Documents / python $ python gamenew.py

    You will be asked a series of questions.
    Your answer will either take you to a different room, or perform an action.
    If you come to a point where you are exited from the game, don't quit!
    There's many more rooms to discover!

To answer questions, either enter the door number,
or answer with a word if asked.

Your progress will NOT be saved.
To restart the game, just enter python ['gamenew.py'].


Are you read to play?
> yes
You are now at your starting point.
Would you like to go through door #1 or door#2?
> 3
You have a single chance to cheat death. To live, please answer the question correctly below:
4863 + 5960 - 4251 + 3934 - 2638 + 5900
13768
> 13768
You are now at your starting point.
Would you like to go through door #1 or door#2?
> 3
You have a single chance to cheat death. To live, please answer the question correctly below:
3934 + 4251 - 5900 + 4863 - 2638 + 5960
10470
> 10470
You died.
nathan@jolicloud:~/Documents/python$ 

Как вы видите, правильный способ его запуска - спросить у него ответ на вопрос, а затем, получив правильный ответ, вернуть пользователя к началу, что он и делает. Но затем, если вас попросят ответить на вопрос снова, чего вам не следует в первую очередь, он скажет, что правильный ответ неверен

Итак, вы можете видеть, что я хочу начать с death_toll, являющегося 0, что означает, что у пользователя есть один шанс "умереть". Затем, если вызывается функция cheat_death(), она должна увеличить переменную death_toll на 1, что означает, что у них больше нет шансов «умереть». Я делаю это правильно? Потому что, в конце, я хочу, чтобы пользователь занял else, если death_toll равно или больше 1.

Ответы [ 4 ]

4 голосов
/ 12 августа 2011

Этот оператор не увеличивается death_toll:

death_toll == death_toll + 1

Это сравнение, которое возвращает False.Вы хотите:

death_toll = death_toll +1

Редактировать :

Если я понимаю ваши различные комментарии и т. Д., Вы хотите, чтобы программа предлагала на протяжении всего времени выполненияОдин шанс "обмануть смерть".Если игроку удастся воспользоваться этим шансом, он возвращается к началу, но после этого, если он снова пытается «обмануть смерть», у него нет шансов.

Итак, у вас несколько проблем.Как уже указывалось, вам нужно использовать оператор присваивания при увеличении числа погибших, и вам нужно использовать объявление global, чтобы получить доступ к глобальному счетчику жертв внутри функции.Похоже, что третья проблема в том, что порядок операторов в cheat_death просто неправильный.Если вы не хотите, чтобы у игрока был шанс после увеличения числа погибших, вам необходимо проверить его в начале функции.

Я думаю, что я переписал бы всю функцию следующим образом:

def cheat_death(numbers):
    global death_toll

    if death_toll < 1:

        # This counts as a used chance.  Increment the counter.
        death_toll = death_toll + 1

        shuffle(numbers)

        question = "%d + %d - %d + %d - %d + %d" % tuple(numbers)

        print "You have a single chance to cheat death. To live, please answer the question correctly below:"
        print question

        answer = eval(question)
        print answer

        user_answer = raw_input("> ")

        if str(user_answer) == str(answer):
            start()
        else:
            dead()
    else:
        dead()

(Что ж, я, вероятно, переписал бы его, чтобы вернуть что-то вместо прямого вызова start(), но я не собираюсь пытаться изменить всю программу целиком.)

2 голосов
/ 12 августа 2011

В python сначала есть что-то, что не очевидно.

Если в функции вы используете оператор присваивания или дополненного присваивания (+=, -= и т. П.) С переменной, топредполагается, что эта переменная является локальной переменной функции.

Это печальное последствие того, что вам не нужно объявлять локальные переменные.

Если вы хотите изменитьпеременная, которая "за пределами", вы должны использовать объявление global:

toll = 0

def function_1():
    toll = toll + 1   # ERROR, it's a local variable, not the one shown above

def function_2():
    global toll
    toll = toll + 1   # Ok, now works as you want

Также в вашем коде есть логическая проблема.Переменная death_toll инициализируется в 0, но затем она немедленно увеличивается (при условии, что вы исправили сравнение == в присваивании =), поэтому при первом обращении к if это уже 1.

Тогда вы разрешаете запускать, только если оно меньше 1 ... это явно невозможно, потому что вы просто увеличили его на строчку выше ...

0 голосов
/ 12 августа 2011

Я не думаю, что это поможет решить вашу общую проблему: вам нужно научиться тщательно анализировать, читать и отлаживать свой собственный код.

Однако вот очевидный источник вашей ошибки(Я вынул операторы print, чтобы сделать поток кода более наглядным):

global death_toll
death_toll = death_toll +1

if str(user_answer) == str(answer) and death_toll == 1:
    start()
else:
    dead()

Я не понимаю, что вы здесь делаете.Вы хотите сделать так, чтобы у пользователя была ровно одна жизнь?Таким образом, они возвращаются к началу, если они потеряют свою жизнь, но только один раз?То, как у вас это получается, они увеличивают число погибших (теряют жизнь?), Даже если они правильно задают вопрос.

Трудно отладить чужую программу, если вы действительно не знаете, кем они былисобираетсяПоскольку вы выбросили всю свою программу, я постараюсь взять ее построчно и дать несколько советов по улучшению.Я надеюсь, что вы принимаете их так же беззаботно, как они предназначены.

Я собираюсь использовать счетчик жизней (поскольку вы можете обманывать смерть столько раз), так что я думаю, что я бы назвал глобальную переменную lives_left и уменьшил ее для удобства чтения.Обратите внимание, что вам, вероятно, не нужно преобразовывать ваши ответы в строки;int может быть более устойчивым в конце, на случай, если вы получите забавный ввод пользователя:

lives_left = 3 # Three chances to cheat death before even math can't save you!

, а затем и позже, в вашей функции:

global lives_left

if int(user_answer) == int(answer) and  lives_left:
    lives_left -= 1
    start()
else:
    dead()

В отношении не связанныхобратите внимание, я также заметил, что в вашем коде есть несколько таких выражений:

if take_mask == "yes" or take_mask == "y" or take_mask == "yeah" or take_mask == "sure":
    cheat_death(numbers)
elif take_mask == "no" or take_mask == "n" or take_mask == "nah":
    print "Wise indeed."
    hallway_one()
else:
    cheat_deaath()

Вы можете сделать это гораздо более читабельным и упорядоченным с помощью оператора in.Определите свои строки положительных и отрицательных ответов где-то заранее:

answers{'positive':['yes', 'yeah', 'sure', 'y'], 'negative':['no', 'nah', 'n']}

, а затем ссылайтесь на эти возможности в любой более поздний момент:

if take_mask in answers['positive']:
    cheat_death(numbers)
elif take_mask in answers['negative']:
    print "Wise indeed."
    hallway_one()
else:
    cheat_death()

Также обратите внимание, что ваша функция cheat_death() вышеНЕОБХОДИМО принять параметр!

Я дам вам знать, если увижу что-нибудь еще!

0 голосов
/ 12 августа 2011
death_toll == death_toll + 1

Эта строка сравнивает death_toll с (death_toll + 1), затем отбрасывает результат сравнения.

Очевидно, вы имели в виду «=», а не «==».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...