首页 > 解决方案 > 如何在一个房子里有多个敌人。Python 文本角色扮演游戏

问题描述

我正在制作一个游戏,玩家在房子里四处走动并与怪物战斗。我试图弄清楚如何在一个房子里有多个怪物。我不确定如何在列表中创建怪物的实例,或者是否可能。

from random import randint
import subprocess
import platform
import time
import npc, player

class Map:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.monsterHouse = []
        self.start = (0, 0)
        self.player = (0, 0)

    def movePlayer(self, d):
        x = self.player[0]
        y = self.player[1]
        pos = None

        if d == "":
          pos = (x, y)
        elif d[0] == 'r':
            pos = (x + 1, y)
        elif d[0] == 'l':
            pos = (x - 1, y)
        elif d[0] == 'u':
            pos = (x, y - 1)
        elif d[0] == 'd':
            pos = (x, y + 1)
        else:
          pos = (x, y)
        

        if pos[0] > -1 and pos[0] < self.width and pos[1] > -1 and pos[1] < self.height:
          if pos not in self.monsterHouse:
            self.player = pos
          elif pos in self.monsterHouse:
            self.player = pos
            clear()
            enterHouse(self)
            # MonsterHouse.modifyPlayer(self.player)
          elif pos in self.start:
            SafeHouse.modifyPlayer(self.player)

def drawGrid(self, width=2):
    for y in range(self.height):
        for x in range(self.width):
            if (x, y) in self.monsterHouse:
                symbol = 'H'
            elif (x, y) == self.player:
                symbol = '$'
            elif (x, y) == self.start:
                symbol = '&'
            else:
                symbol = '.'
            print("%%-%ds" % width % symbol, end="")
        print()


def getHouse(g: Map) -> list:
        out = []
        for i in range(0, 3):
          x = randint(1, g.width-1)
          y = randint(1, g.height-1)
          if x == 0 and y == 0:
            x = 3
            y = 3
          out.append((x,y))
        return out

def enterHouse(self):
    action = input("Monsters House! What do you do? ([a]ttack, [r]un)")
    if action == 'a':
      MonsterHouse.attackPhase(self)
    elif action == 'r':
        self.movePlayer(self, 'l')

def clear():
    subprocess.Popen("cls" if platform.system() == "Windows" else "clear", shell=True)
    time.sleep(.01)

def main():
    g = Map(5, 5)
    g.monsterHouse = getHouse(g)

    while True:
        drawGrid(g)
        d = input("Which way? (r, l, u, d)")
        g.movePlayer(d)
        clear()

class SafeHouse(Map):
  def modifyPlayer(self):
    self.hp = randint(100, 125)

class MonsterHouse(Map):
  def __init__(self, x, y, enemy):
    self.enemy = enemy
    super().__init__(x, y)

  def attackPhase(self):
    houseMonsters = []
    numMonsters = randint(0,10)
    for x in range(numMonsters):
      typeMonster = randint(1, 4)
      #1 = Zombie, 2 = Vampire, 3 = Ghoul, 4 = Werewolf
      if typeMonster == 1:
        houseMonsters += npc.Zombie
      elif typeMonster == 2:
        houseMonsters += npc.Vampire
      elif typeMonster == 3:
        houseMonsters += npc.Ghoul
      elif typeMonster == 4:
        houseMonsters += npc.Werewolf
    
    # print(houseMonsters)

  def modifyPlayer(self, thePlayer):
    if self.enemy.isAlive():
      thePlayer.hp = thePlayer.hp - self.enemy.damage
      print("You have been attacked by the monsters! You have {} HP remaining.".format(thePlayer.hp))
  

if __name__ == '__main__':
    main()

这是 npc 类,其中包含所有可能进入房子的东西。

 import random
    class NPC():
      def __init__(self, name, hp, attack):
        self.name = name
        self.hp = hp
        self.attack = attack
    
    class Person(NPC):
      def __init__(self):
        super().__init__(100, -1)
    
    # 2x damage from sourstraws
    class Zombie(NPC):
        def __init__(self):
            super().__init__("Zombie", random.randint(50, 100), random.randint(0, 10))
    
    # Cant be hurt by ChocolateBars
    class Vampire(NPC):
        def __init__(self):
            super().__init__("Vampire", random.randint(100, 200), random.randint(10, 20))
    
    # 5x damage form NerdBombs
    class Ghoul(NPC):
        def __init__(self):
            super().__init__("Ghoul", random.randint(40, 80), random.randint(15, 30))
    
    # Cant be hurt by chocolateBars and sourstraws
    class Werewolf(NPC):
        def __init__(self):
            super().__init__("Werewolf", 200, random.randint(0, 40))

所以我设置了它,以便玩家移动到地图上的房子,他们可以攻击或逃跑。如果他们攻击它,那么它会在房子里创造一个随机数量的怪物供玩家攻击。

我收到的错误是 TypeError: 'type' object is not iterable

标签: python

解决方案


有几个小错误。

第一个是要创建对象的新实例,即使没有参数,也需要包含括号。

    houseMonsters += npc.Zombie()

第二个问题是houseMonsters列表。说是无效的语法list += object,代码需要使用list.append(),例如:

 houseMonsters.append( npc.Vampire() )

将这些更改包装在一起给出MonsterHouse.attackPhase()

def attackPhase(self):
    houseMonsters = []
    numMonsters = randint(0,10)
    for x in range(numMonsters):
        typeMonster = randint(1, 4)
        #1 = Zombie, 2 = Vampire, 3 = Ghoul, 4 = Werewolf
        if typeMonster == 1:
            newMonster = npc.Zombie()
        elif typeMonster == 2:
            newMonster = npc.Vampire()
        elif typeMonster == 3:
            newMonster = npc.Ghoul()
        elif typeMonster == 4:
            newMonster = npc.Werewolf()
        # add to the list
        houseMonsters.append( newMonster )

    print( "DEBUG" + str (houseMonsters))

当然,您永远不会看到 DEBUG 打印,因为代码每次循环都会清除屏幕。也许在您开发时,将清除更改为仅打印一行破折号或类似内容。

& . . . . 
$ H . . H 
. . . . . 
. . . . . 
. . . H . 
Which way? (r, l, u, d)r
----------------------------------
Monsters House! What do you do? ([a]ttack, [r]un)a
DEBUG[<npc.Werewolf object at 0x7f080722acd0>, <npc.Werewolf object at 0x7f0807734810>]

推荐阅读