简体   繁体   English

Python 基于文本的游戏问题

[英]Python Text based game trouble

I have 3 issues with my code I haven't been able to figure out.我的代码有 3 个问题,我无法弄清楚。

  1. I have trouble with my code when it loops it almost always says invalid command even when its valid and even completes the movement command.我的代码在循环时遇到问题,即使它有效甚至完成移动命令,它几乎总是说无效命令。

  2. I need to have the items dictionary update when the item is picked up.拾取物品时,我需要更新物品字典。 I have tried pop(), popitem(), and del but I still have errors when I try to pick the item up again.我已经尝试过 pop()、popitem() 和 del,但是当我再次尝试拾取该项目时仍然出现错误。

  3. I can't seem to get the split to work correctly for picking up items with two words.我似乎无法让拆分正确地使用两个词来拾取物品。 Such as 'fire spell' or 'health potion'.例如“火咒”或“健康药水”。

rooms = {
        'Bedroom': {'South': 'Old Living Room'},
        'Old Living Room': {'South': 'Old Office', 'East': 'Old Kitchen', 'West': 'Old Garage'},
        'Old Garage': {'East': 'Old Living Room'},
        'Old Kitchen': {'West': 'Old Living Room', 'North': 'Pulsing Room', 'South': 'Freezer Room'},
        'Old Office': {'North': 'Old Living Room'},
        'Pulsing Room': {'West': 'Dining Room', 'South': 'Old Kitchen'},
        'Freezer Room': {'North': 'Old Kitchen'},
        'Evil Lair': {'Teleported here after all items gathered'}
    }
    
story = {
    'Old Living Room': {'text': 'You enter the old living room and the bedroom door disappears behind you. You see a stick that appears to be a wand on a coffee table.'},
    'Old Garage': {'text': 'You enter an old garage. On an old moving box you see a glowing red health potion'},
    'Old Kitchen': {'text': 'You are in an old familiar kitchen. On top of the oven you see a scroll for a fire spell'},
    'Old Office': {'text': 'You are in your fathers old office. On his old desk you see a blue glowing magic shield'},
    'Pulsing Room': {'text': 'You enter an unfamiliar purple pulsing room. In the center of the room you see a portal key'},
    'Freezer Room': {'text': 'You are in a freezer room. The cold appears to be coming from a scroll that has an ice spell written on it.'},
    'Evil Lair': {'text': 'You are teleported to the Evil Lair. You see Lazarus in front of you.'}
}

items = {
    'Old Living Room': {'contents': 'Wand'},
    'Old Garage': {'contents': 'Health Potion'},
    'Old Kitchen': {'contents': 'Fire Spell'},
    'Old Office': {'contents': 'Magic Shield'},
    'Pulsing Room': {'contents': 'Portal Key'},
    'Freezer Room': {'contents': 'Ice Spell'},
    'Evil Lair': {'contents': 'Lazarus, the Demon Mage'}
}

current_room = 'Bedroom'
story_text = 'Bedroom'
item_collection = 'Old Living Room'
inventory = []

def get_next_room(current_room, direction): # Defining the next room command
    next_room = current_room
    for x in rooms:  # Creating the loop
        if x == current_room:
            if direction in rooms[x]:
                next_room = rooms[x][direction] # Assign the next room
    return next_room

def move_instructions():
    # Print the movement commands the user can use.
    print('########################################################################')
    print('#                 Text based Adventure game                            #')
    print('#        Collect 6 items to face the final boss, Lazarus!!             #')
    print('# Use movement commands North, South, East, West to move between rooms #')
    print("#           'Add to inventory: get 'item name'                         #")
    print('########################################################################\n')

move_instructions()

input('Press Enter to begin your adventure!!')

print('####################################################################################################################')
print('You awaken in your childhood room, but something is different about it. It is dark and appears that the room is \n'
      'falling apart. There are cracks in the walls the glow purple. Unsure of how you got here you stand up and look out \n'
      'the only window in the room to see you are floating through what looks like a void. As you look out the window you \n'
      'see a mysterious figure begin to come toward the window. As it gets closer you realize it is not a person but a \n'
      'monster of some sort. It has tentacles for legs, human like upper body and arms. Its head is human like with no \n'
      'hair or eyes. It comes to the window and laughs as it says “You shall never leave this place. This is my domain. \n'
      'MUHAHAHA”. The figure suddenly disappears. Your task is to gather the items to access the portal that is protecting \n'
      'the creature. To do this, you must collect the items to battle the evil demon wizard Lazarus as well as the portal key. \n'
      'You will need a wand, magic shield, a fire spell, a ice spell, a health potion, and the pulsing purple portal key. \n'
      'Once all items are collected the key will begin pulsing and teleport the player to the Evil Lair.')
print('####################################################################################################################\n')

print('You see your old childhood bedroom and a mysterious door.')  # Print current room
while True:
    print('Inventory: ', inventory)
    movement = input('What would you like to do?')  # Ask for user movement input
    movement = movement.capitalize()  # Makes first letter capital
    if movement == 'Exit':  # Exit command to end game
        print('Game ended')
        exit(0)  # Exit to end game
    if movement == 'North' or movement == 'South' or movement == 'East' or movement == 'West':  # Assign movement commands
        next_room = get_next_room(current_room, movement)  # Calls function
        if next_room == current_room:  # Used if user enters movement that
            print('There is a wall there. Try a different movement command.')
        else:
            current_room = next_room  # Move user to next room
            story_text = current_room
            print(*story[story_text].values())
    if movement.lower().split()[0] == 'get':
        item = movement.lower().split()[1]
        item_collection = current_room
        if item in [x.lower() for x in items[item_collection].values()]:
            inventory.append(item)
            print('You have obtained the', item)
        else:
            print('Invalid item')
    else:
        print('Invalid Command')  # Print if invalid movement command

Addressing your first issue:解决您的第一个问题:

if movement == 'Exit':
    ...
if movement == 'North' or movement == 'South' or movement == 'East' or movement == 'West':
    ...
if movement.lower().split()[0] == 'get':
    ...
else:
    print('Invalid Command')

Let's say your command is Exit .假设您的命令是Exit The first if clause evaluates to True , and the contents of that stanza is executed.第一个if子句的计算结果为True ,然后执行该节的内容。 Your code proceeds to the next if , evaluates as false, and then moves on to the comparison if with get .您的代码继续进行下一个if ,评估为 false,然后继续进行比较 if 与get This evaluates as false, so it moves to the else branch and executes that.这评估为假,所以它移动到else分支并执行它。 Thus, you get an 'Invalid Command' response, even though you also execute the 'Exit' command.因此,即使您执行了“退出”命令,您也会收到“无效命令”响应。

It's not clear what errors you're getting with your second issue, but you're not using a dictionary - you're using a list.目前尚不清楚您在第二个问题中遇到了什么错误,但您没有使用字典 - 您正在使用列表。 It's not clear that you're removing the item from the room when it is picked up.目前尚不清楚您是否在捡起物品时将其从房间中取出。 Without seeing that code or what you're doing to replace it (drop it) it's hard to know where you're going wrong.如果没有看到该代码或您正在做什么来替换它(删除它),很难知道您哪里出错了。

Similarly, with your third problem, you say 'it doesn't work right' without saying what is wrong.同样,对于您的第三个问题,您说“它不能正常工作”而不说什么是错的。 If you have a string fire wand and .split()[1] it should give you wand .如果你有一个字符串fire wand.split()[1]它应该给你wand That said, what you probably want to do is split your sentence out into tokens, handling them in a sub-function and returning an object or value that you can use more clearly to manipulate the game state.也就是说,您可能想要做的是将您的句子拆分为标记,在子函数中处理它们并返回一个对象或值,您可以更清楚地使用它来操纵游戏状态。 For instance, a function that takes the string "get wand" and returns an object Get("wand") that has relevant methods attached to it (say, update_inventory() ).例如,一个函数接受字符串“get wand”并返回一个对象Get("wand") ,该对象附加了相关的方法(例如update_inventory() )。

Essentially, your approach ought to be something like this:本质上,您的方法应该是这样的:

class Command:
   ...

class Move(Command):  # Subclasses Command
   ...

class Get(Command):
   ...

def parse_command(inp: str) -> Command:
   tokens = inp.split()
   if len(tokens) == 1 and tokens[0] in ["west", "south", "north", "east"]:
       return Move(tokens[0])
   elif len(tokens) == 2 and tokens[0] is "get":
       return Get(tokens[1])
   ... # etc.

# in the game loop
inp = input("What would you like to do?")
cmd = parse_command(inp)
cmd.take_action()  # take_action() is defined individually on each class.

There are some definite inconsistencies.有一些明确的不一致之处。

  1. I would start by making the main loop use elif.我首先让主循环使用 elif。 I assume only one command can be processed per input or per loop.我假设每个输入或每个循环只能处理一个命令。 There is no need to keep on matching.没有必要继续匹配。 Using elif will only continue if it has not matched yet.仅当 elif 尚未匹配时才会继续使用。 You are also inconsistent on how you clean your input.您在清理输入的方式上也不一致。 Either capitalize always, or lower case always.要么总是大写,要么总是小写。 Don't do both.不要两者都做。
  2. You should consider using OO here.您应该考虑在这里使用 OO。 Each room should be an object with its own "state" (a set of properties associated with that room).每个房间都应该是一个具有自己“状态”(与该房间相关联的一组属性)的对象。 When an object is collected, it should be removed from the inventory of that room and moved to the inventory of the character.收集物品后,应将其从该房间的物品栏中移出并移至角色的物品栏中。 If an object is discarded, the reverse should happen.如果一个对象被丢弃,则应该发生相反的情况。
  3. use split with specified max splits...使用具有指定最大拆分的拆分...
item = movement.lower().split(' ', 1)[1]

The 1 in the split means split only once. split 中的 1 表示只拆分一次。 item[0] should be the command "get". item[0] 应该是命令“get”。 item[1] is everything after. item[1] 是之后的一切。

actually, using re.split is even better, I think...实际上,我认为使用 re.split 会更好...

re.split('\s+', movement.lower(), 1)

the \s is white space. \s 是空格。 With the +, it matches on variable length white space.使用 +,它匹配可变长度的空白。 Sometimes user's will type an extra space, for example (this may be causing some of your issues).例如,有时用户会键入一个额外的空格(这可能会导致您的一些问题)。 The 1, again, limits how many splits can happen. 1 再次限制了可以发生的拆分次数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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