Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python I';我收到一个TypeError,因为非类型对象不可下标。如何使其可订阅?_Python - Fatal编程技术网

Python I';我收到一个TypeError,因为非类型对象不可下标。如何使其可订阅?

Python I';我收到一个TypeError,因为非类型对象不可下标。如何使其可订阅?,python,Python,我正试图为一个基于文本的RPG编写代码,方法是跟随Phillip Johnson写的一本名为Make Your Own Python text Adventure的书。我无法识别代码中的错误所在。我已经看了好几遍了,似乎还没弄明白。我试过摆弄不同的东西,但到目前为止,它只会产生不同的错误。我会发布我的代码和回溯 Traceback (most recent call last): File "C:\Users\Timothy Hall\Desktop\Yradel_Game\Yradel_G

我正试图为一个基于文本的RPG编写代码,方法是跟随Phillip Johnson写的一本名为Make Your Own Python text Adventure的书。我无法识别代码中的错误所在。我已经看了好几遍了,似乎还没弄明白。我试过摆弄不同的东西,但到目前为止,它只会产生不同的错误。我会发布我的代码和回溯

Traceback (most recent call last):
  File "C:\Users\Timothy Hall\Desktop\Yradel_Game\Yradel_Game5.py", line 99, in <module>
    main()
  File "C:\Users\Timothy Hall\Desktop\Yradel_Game\Yradel_Game5.py", line 31, in main
    player = Player()
  File "C:\Users\Timothy Hall\Desktop\Yradel_Game\player.py", line 11, in __init__
    self.x = world.start_tile_location[0]
TypeError: 'NoneType' object is not subscriptable

您似乎忘记在此功能中设置
start\u tile\u location

start\u tile\u location=None
#创建解析dsl的函数
def parse_world_dsl():
如果无效,则\u dsl \u有效(世界\u dsl):
raise SYNTASERROR(“DSL无效!”)
dsl_lines=world_dsl.splitlines()
dsl_线=[x表示dsl_线中的x,如果x]
#迭代dsl中的每一行
#使用变量y代替i,因为我们使用的是X-y网格。
对于y,枚举中的dsl_行(dsl_行):
#创建一个对象来存储平铺
行=[]
#使用“拆分”方法将行拆分为缩写
dsl_单元格=dsl_行。拆分(“|”)
#拆分方法包括行的开始和结束
#所以我们需要移除那些不存在的细胞
dsl_单元=[c表示dsl_单元中的c,如果是c]
#迭代dsl行中的每个单元格
#使用变量x代替j,因为我们使用的是x-Y网格
对于x,枚举中的dsl_单元(dsl_单元):
#在字典里查缩写词
tile\u type=tile\u type\u dict[dsl\u单元]
#如果字典返回了有效类型,请创建一个新类型
#平铺对象,根据需要传递X-Y坐标
#通过tile\uuuu init\uuuuu()创建,并将其添加到row对象。如果
#字典里找不到,我们只加了一个。
行。追加(如果平铺类型为(x,y),则为平铺类型,否则为无)
如果“S”==dsl\U单元:
开始位置=(x,y)
#将整行添加到世界地图
世界地图。附加(行)

该错误意味着
world.start\u tile\u location
为None,这只是搜索它的一个例子。您将其初始化为
world.start\u tile\u location=None
,并且您不会更改它。此错误很容易查找,有关详细信息,请参阅此可爱的参考。就您在这里发布的内容而言,您确实没有做太多工作来跟踪代码中的问题。只是想让您知道,正如我在正文中所说的,在发布此问题之前,我查看了我的代码好几次。我对编码还是个新手,这东西有点复杂。我正在尽我最大的努力学习,有时学习会很困难。你发布的那篇文章建议你仔细检查你的代码,并向自己解释它应该做什么,如果你做不到,那就是错误。(橡胶鸭法)。然而,这就是我所做的,仍然找不到错误,这就是为什么我问这个问题。
# this program is a text based rpg

#import the OrderedDict
from collections import OrderedDict

# import the player module
from player import Player

# import the world module
import world

def main():
    # display Yradellian name examples
    print("Some examples of female Yradellian names include Nelsi, Drew, Casey, Ilya, etc.")
    print("Some examples of male Yradellian names include Toreth, Daren, Attel, Mayes, etc.")

    # get the character name from the user
    yesName = False
    while yesName == False:
        charName = input("What can I call you? ")
        nameInput = input("Your name is, " + charName + "? Type Yes or No: ")
        if nameInput == "Yes":
            yesName = True
        else:
            print("Sorry...")

    # call the parse world function
    world.parse_world_dsl()

    # create a player object
    player = Player()

    # display the welcome message
    print()
    player.say_hello(charName)

    # display current inventory
    print()
    print("Here's your starting game Inventory:")
    player.print_inventory()

    while True:
        # display the intro text for each tile
        print()
        room = world.tile_at(player.x, player.y)
        print(room.intro_text())

        # modify the player depending on the tile type
        room.modify_player(player)

        # get the action input from the user
        print()

        choose_action(room, player)
# create a funtion for available actions
def get_available_actions(room, player):
    actions = OrderedDict()
    print("Choose what to do...")

    if player.inventory:
        action_adder(actions, "i", player.print_inventory, "Print inventory")
    if isinstance(room, world.TraderTile):
        action_adder(actions, "t", player.trade, "Trade")
    if isinstance(room, world.EnemyTile) and room.enemy.is_alive():
        action_adder(actions, "a", player.attack, "Attack")
    else:
        if world.tile_at(room.x, room.y - 1):
            action_adder(actions, "n", player.move_north, "Go North!")
        if world.tile_at(room.x + 1, room.y):
            action_adder(actions, "e", player.move_east, "Go East!")
        if world.tile_at(room.x, room.y + 1):
            action_adder(actions, "s", player.move_south, "Go South!")
        if world.tile_at(room.x - 1, room.y):
            action_adder(actions, "w", player.move_west, "Go West!")
    if player.hp < 100:
        action_adder(actions, "h", player.heal, "Heal")

    return actions

# create the action adder function
def action_adder(action_dict, hotkey, action, name):
    action_dict[hotkey.lower()] = action
    action_dict[hotkey.upper()] = action
    print("{}: {}".format(hotkey, name))

# create a function to utilize the action dictionary
def choose_action(room, player):
    action = None
    while not action:
        available_actions = get_available_actions(room, player)
        action_input = input("Action: (Type a letter) ")
        action = available_actions.get(action_input)
        if action:
            action()
        else:
            print("That is invalid input.")

# call the main function
main()
# import the enemies module
import enemies
# import the npc module
import npc
# import the random module
import random

# create a parent class for the map tiles
class MapTile:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def intro_text(self):
        raise NotImplementedError("Create a subclass instead!")
    def modify_player(self, player):
        pass

# create the tile subclasses
class StartTile(MapTile):
    def intro_text(self):
        return """You find yourself in a forest, sunlight trickling through the leaves overhead. Your feet crunch over the underbrush. You can see four paths through the trees.\n"""

class BoringTile(MapTile):
    def intro_text(self):
        return """The trees all look the same here...\n"""

class CityTile(MapTile):
    def intro_text(self):
        return """You made it out of the forest into a small town known as Burenburg. The people greet you warmly and you are filled with a sense of accomplishment.\n"""

class EnemyTile(MapTile):
    # have enemies randomly appear
    def __init__(self, x, y):
        r = random.random()
        if r < 0.50:
            self.enemy = enemies.Wolf()
            self.alive_text = "A lone Wolf approaches you baring its fangs."
            self.dead_text = "The Wolf keels over, dead before you."
        else:
            self.enemy = enemies.Goblin()
            self.alive_text = "A Goblin tries to steal your gold, you must defend yourself against his blade."
            self.dead_text = "The Goblin sticks its tongue out at you as it falls over dead."
        super().__init__(x, y)
    # display their alive/dead message
    def intro_text(self):
        text = self.alive_text if self.enemy.is_alive() else self.dead_text
        return text
    # have enemies attack the player
    def modify_player(self, player):
        if self.enemy.is_alive():
            player.hp = player.hp - self.enemy.damage
            print("Enemy does {} damage. You have {} HP remaining.".format(self.enemy.damage, player.hp))

class TraderTile(MapTile):
    def __init__(self, x, y):
        self.trader = npc.Trader()
        super().__init__(x, y)
    # create a method to trade between a buyer and seller
    def trade(self, buyer, seller):
        for i, item in enumerate(seller.inventory, 1):
            print("{}. {} - {} Gold".format(i, item.name, item.value))
        while True:
            user_input = input("Choose an item or press Q to exit: ")
            if user_input in ["Q", "q"]:
                return
            else:
                try:
                    choice = int(user_input)
                    to_swap = seller.inventory[choice - 1]
                    self.swap(seller, buyer, to_swap)
                except ValueError:
                    print("Invalid choice!")
    # create a method to swap items and gold between the buyer and seller
    def swap(self, seller, buyer, item):
        if item.value > buyer.gold:
            print("That's too expensive")
            return
        seller.inventory.remove(item)
        buyer.inventory.append(item)
        seller.gold = seller.gold + item.value
        buyer.gold = buyer.gold - item.value
        print("Trade complete!")
    # create a method to accept user input about who is the buyer and seller
    def check_if_trade(self, player):
        while True:
            print("Would you like to (B)uy, (S)ell or (Q)uit?")
            user_input = input()
            if user_input in ["Q", "q"]:
                return
            elif user_input in ["B", "b"]:
                print("Here's what's available to buy: ")
                self.trade(buyer = player, seller = self.trader)
            elif user_input in ["S", "s"]:
                print("Here's what's available to sell: ")
                self.trade(buyer = self.trader, seller = player)
            else:
                print("Invalid choice!")
    # create intro text for this room
    def intro_text(self):
        return """A man in a brown robe awaits you, willing to trade."""

class GoldTile(MapTile):
    def __init__(self, x, y):
        self.gold = random.randint(1, 50)
        self.gold_claimed = False
        super().__init__(x, y)

    def modify_player(self, player):
        if not self.gold_claimed:
            self.gold_claimed = True
            player.gold = player.gold + self.gold
            print("+{} Gold added.".format(self.gold))

    def intro_text(self):
        if self.gold_claimed:
            return """Another clearing in the forest with nothing in it but cute animals and underbrush."""
        else:
            return """Someone must've dropped some gold! You pick it up."""

# create the basic world map
world_dsl = """
| |E|C|E| |
|B|B| |B| |
|T| |G|E|B|
|G| |E| |G|
|E|B|S|T|B|
| | |E| |G|
| | |G|B|E|
"""

# create a function to validate the dsl
def is_dsl_valid(dsl):
    if dsl.count("|S|") != 1:
        return False
    if dsl.count("|C|") == 0:
        return False
    lines = dsl.splitlines()
    lines = [l for l in lines if l]
    pipe_counts = [line.count("|") for line in lines]
    for count in pipe_counts:
        if count != pipe_counts[0]:
            return False

    return True

# define a dictionary that maps dsl abreviations to tile types
tile_type_dict = {"C": CityTile,
                  "E": EnemyTile,
                  "S": StartTile,
                  "B": BoringTile,
                  "G": GoldTile,
                  "T": TraderTile,
                  " ": None}

world_map = []

start_tile_location = None

# create the function to parse the dsl
def parse_world_dsl():
    if not is_dsl_valid(world_dsl):
        raise SyntaxError("DSL is invalid!")

    dsl_lines = world_dsl.splitlines()
    dsl_lines = [x for x in dsl_lines if x]

    # iterate over each line in the dsl
    # instead of i, the variable y is used because we're working with an X-Y grid.
    for y, dsl_row in enumerate(dsl_lines):
        # create an object to store the tiles
        row = []
        # split the line into abbreviations using the "split" method
        dsl_cells = dsl_row.split("|")
        # the split method includes the beginning and end of the line
        # so we need to remove those nonexistent cells
        dsl_cells = [ c for c in dsl_cells if c]
        # iterate over each cell in the dsl line
        # instead of j, the variable x is used becuase we're working with an X-Y grid
        for x, dsl_cell in enumerate(dsl_cells):
            # look up the abbreviation in the dictionary
            tile_type = tile_type_dict[dsl_cell]
            # if the dictionary returned a valid type, create a new
            # tile object, pass it the X-Y coordinates as required
            # by the tile__init__(), and add it to the row object. If
            # None was found in the dictionary, we just add None.
            row.append(tile_type(x, y) if tile_type else None)

        # add the whole row to the world_map
        world_map.append(row)

# create a function that locates the tile at a specific coordinate
def tile_at(x, y):
    if x < 0 or y < 0:
        return None
    try:
        return world_map[y][x]
    except IndexError:
        return None
# import the items module
import items
# import the world module
import world

# create a class for Player
class Player:
    # define the inventory
    def __init__(self):
        self.inventory = [items.Dagger(), items.BreadRoll(), items.Potion()]
        self.x = world.start_tile_location[0]
        self.y = world.start_tile_location[1]
        self.hp = 100
        self.gold = 100
    # print the inventory and the best weapon
    def print_inventory(self):
        print("Inventory:")
        for item in self.inventory:
            print("* " + str(item))
        print("Gold: {}".format(self.gold))
        best_weapon = self.most_powerful_weapon()
        print("Your best weapon is your {}".format(best_weapon))
    # create a function to heal the player
    def heal(self):
        consumables = [item for item in self.inventory if isinstance(item, items.Consumable)]
        if not consumables:
            print("You don't have any items to heal you!")
            return
        for i, item in enumerate(consumables, 1):
            print("Choose an item to use to heal: ")
            print("{}. {}".format(i, item))
        valid = False
        while not valid:
            choice = input("")
            try:
                to_eat = consumables[int(choice) - 1]
                self.hp = min(100, self.hp + to_eat.healing_value)
                self.inventory.remove(to_eat)
                print("Current HP: {}".format(self.hp))
                valid = True
            except (ValueError, IndexError):
                print("Invalid choice, try again.")
    # welcome the user to the game
    def say_hello(self, name):
        print("Hello, " + name, ", welcome to the world of Yradel.")
    # create a function to determine the best weapon
    def most_powerful_weapon(self):
        max_damage = 0
        best_weapon = None
        for item in self.inventory:
            try:
                if item.damage > max_damage:
                    best_weapon = item
                    max_damage = item.damage
            except AttributeError:
                pass
        return best_weapon
    # create functions to let the player move
    def move(self, dx, dy):
        self.x += dx
        self.y += dy
    def move_north(self):
        self.move(dx = 0, dy = -1)
    def move_east(self):
        self.move(dx = 1, dy = 0)
    def move_south(self):
        self.move(dx = 0, dy = 1)
    def move_west(self):
        self.move(dx = -1, dy = 0)
    # create a function to attack the enemy
    def attack(self):
        best_weapon = self.most_powerful_weapon()
        room = world.tile_at(self.x, self.y)
        enemy = room.enemy
        print("You use {} against the {}!".format(best_weapon.name, enemy.name))
        enemy.hp -= best_weapon.damage
        if not enemy.is_alive():
            print("You killed {}!".format(enemy.name))
        else:
            print("{} HP is {}.".format(enemy.name, enemy.hp))
    # create a method to allow trade
    def trade(self):
        room = world.tile_at(self.x, self.y)
        room.check_if_trade(self)