2012-10-18 21 views
7

Zajmuję się prostą tekstową grą Dungeon, używając Python3. Najpierw użytkownik jest proszony o wybranie bohatera z pliku screen.py.TypeError: __init __() przyjmuje co najmniej 2 argumenty (1 dany) błąd

from game import * 


class GameScreen: 
    '''Display the current state of a game in a text-based format. 
    This class is fully implemented and needs no 
    additional work from students.''' 

    def initialize_game(self): 
     '''(GameScreen) -> NoneType 
     Initialize new game with new user-selected hero class 
     and starting room files.''' 

     hero = None 
     while hero is None: 
      c = input("Select hero type:\n(R)ogue (M)age (B)arbarian\n") 
      c = c.lower() 
      if c == 'r': 
       hero = Rogue() 
      elif c == 'm': 
       hero = Mage() 
      elif c == 'b': 
       hero = Barbarian() 

     self.game = Game("rooms/startroom", hero) 

    def play(self): 
     '''(Game) -> NoneType 
     The main game loop.''' 

     exit = False 
     while not exit: 
      print(self) 
      if self.game.game_over(): 
       break 
      c = input("Next: ") 
      if c in ['q', 'x']: 
       print("Thanks for playing!") 
       exit = True 
      elif c == 'w': # UP 
       self.game.move_hero(-1, 0) 
      elif c == 's': # DOWN 
       self.game.move_hero(1, 0) 
      elif c == 'a': # LEFT 
       self.game.move_hero(0, -1) 
      elif c == 'd': # RIGHT 
       self.game.move_hero(0, 1) 
      elif c == 'r': 
       ## RESTART GAME 
       self.initialize_game() 
      else: 
       pass 

    def __str__(self): 
     '''(GameScreen) -> NoneType 
     Return a string representing the current room. 
     Include the game's Hero string represetation and a 
     status message from the last action taken.''' 

     room = self.game.current_room 
     s = "" 

     if self.game.game_over(): 
      #render a GAME OVER screen with text mostly centered 
      #in the space of the room in which the character died. 

      #top row 
      s += "X" * (2 + room.cols) + "\n" 
      #empty rows above GAME OVER 
      for i in list(range(floor((room.rows - 2)/2))): 
       s += "X" + " " * room.cols + "X\n" 
      # GAME OVER rows 
      s += ("X" + " " * floor((room.cols - 4)/2) + 
       "GAME" + " " * ceil((room.cols - 4)/2) + "X\n") 
      s += ("X" + " " * floor((room.cols - 4)/2) + 
       "OVER" + " " * ceil((room.cols - 4)/2) + "X\n") 
      #empty rows below GAME OVER 
      for i in list(range(ceil((room.rows - 2)/2))): 
       s += "X" + " " * room.cols + "X\n" 
      #bottom row 
      s += "X" * (2 + room.cols) + "\n" 
     else: 
      for i in range(room.rows): 
       for j in room.grid[i]: 
        if j is not None: 
         if j.visible: 
          s += j.symbol() 
         else: 
          #This is the symbol for 'not yet explored' : ? 
          s += "?" 
       s += "\n" 
     #hero representation 
     s += str(self.game.hero) 
     #last status message 
     s += room.status 
     return s 

if __name__ == '__main__': 
    gs = GameScreen() 
    gs.initialize_game() 
    gs.play() 

Ilekroć uruchomić ten kod, otrzymuję ten błąd: Błąd typu: startowy() trwa co najmniej 2 argumenty (1 podano), który ma do czynienia z Rogue() lub innych klas bohatera. Oto hero.py.

class Rogue(Tile): 
    '''A class representing the hero venturing into the dungeon. 
    Heroes have the following attributes: a name, a list of items, 
    hit points, strength, gold, and a viewing radius. Heroes 
    inherit the visible boolean from Tile.''' 

    def __init__(self, rogue, bonuses=(0, 0, 0)): 
     '''(Rogue, str, list) -> NoneType 
     Create a new hero with name Rogue, 
     an empty list of items and bonuses to 
     hp, strength, gold and radius as specified 
     in bonuses''' 

     self.rogue = rogue 
     self.items = [] 
     self.hp = 10 + bonuses[0] 
     self.strength = 2 + bonuses[1] 
     self.radius = 2 + bonuses[2] 
     Tile.__init__(self, True) 

    def symbol(self): 
     '''(Rogue) -> str 
     Return the map representation symbol of Hero: O.''' 

     #return "\u263b" 
     return "O" 

    def __str__(self): 
     '''(Item) -> str 
     Return the Hero's name.''' 

     return "{}\nHP:{:2d} STR:{:2d} RAD:{:2d}\n".format(
        self.rogue, self.hp, self.strength, self.radius) 

    def take(self, item): 
     '''ADD SIGNATURE HERE 
     Add item to hero's items 
     and update their stats as a result.''' 

     # IMPLEMENT TAKE METHOD HERE 
     pass 

    def fight(self, baddie): 
     '''ADD SIGNATURE HERE -> str 
     Fight baddie and return the outcome of the 
     battle in string format.''' 

     # Baddie strikes first 
     # Until one opponent is dead 
      # attacker deals damage equal to their strength 
      # attacker and defender alternate 
     if self.hp < 0: 
      return "Killed by" 
     return "Defeated" 

Co robię źle?

Odpowiedz

9

Problem

W GameScreen.initialize_game() można ustawić hero=Rogue(), ale konstruktor Rogue trwa rogue jako argument. (Powiedział inny sposób, wymaga z rogue przekazać.) Prawdopodobnie masz ten sam problem, gdy ustawisz hero=Mage i hero=Barbarian.

Rozwiązanie

szczęście poprawka jest prosta; możesz po prostu zmienić hero=Rogue() na hero=Rogue("MyRogueName"). Może mógłbyś poprosić użytkownika o nazwę w initialize_game, a następnie użyć tej nazwy.

Uwagi o „przynajmniej 2 argumenty (1 podany)”

Kiedy widzisz błędy takie jak ten, oznacza to, że nazywa się funkcję lub metodę bez przechodzenia wystarczających argumentów do niego. (__init__ to tylko specjalna metoda, która jest wywoływana, gdy obiekt jest inicjowany.) Tak więc podczas debugowania takich rzeczy w przyszłości, spójrz na to, gdzie nazywasz funkcję/metodę, i gdzie ją zdefiniujesz, i upewnij się, że oba mają taka sama liczba parametrów.

Jedna rzecz, która jest dość skomplikowana w przypadku tego rodzaju błędów, to self, która zostaje przekazana.

>>> class MyClass: 
...  def __init__(self): 
...    self.foo = 'foo' 
... 
>>> myObj = MyClass() 

W tym przykładzie, można by pomyśleć, „Dziwne, że zainicjowany myObj, więc MyClass.__init__ nazwano; dlaczego nie muszę przechodzić w coś dla self?” Odpowiedź brzmi, że self jest skutecznie przekazywany za każdym razem, gdy używana jest notacja "object.method()". Mam nadzieję, że pomoże to wyjaśnić błąd i wyjaśni, jak go debugować w przyszłości.

+0

otrzymuję ten błąd teraz! TypeError: __init __() przyjmuje dokładnie 2 argumenty pozycyjne (3 dane), gdy przechodzę hero = Rogue ('hello') – sachitad

+0

Tak, otrzymuję ten sam błąd również w Magu i Barbarzyńcy. Teraz, gdy tylko przekazuję argument podczas wywoływania Rogue'a ("Hello"), pojawia się ten błąd "TypeError: __init __() przyjmuje dokładnie 2 argumenty pozycyjne (3 dane)" – sachitad

+0

oh Przepraszam, że popełniłem błąd.Teraz działa dobrze. Dziękuję bardzo za dobre wyjaśnienie. Wyraźnie zrozumiałem koncepcję obiektową i wykorzystanie pierwszego parametru "self". – sachitad

1
Class Rogue: 
    ... 
    def __init__(self, rogue, bonuses=(0, 0, 0)): 
     ... 

__init__ swojej klasie Rogue potrzebuje parametru rogue, ale jesteś uruchamianiu go jako hero = Rogue() w initialize_game.

Trzeba zdać jakiś odpowiedni parametr do niego jak hero = Rogue('somename')

+0

Otrzymujesz ten błąd teraz! TypeError: __init __() pobiera dokładnie 2 argumenty pozycyjne (3 dane), gdy przechodzę hero = Rogue ('hello') – sachitad

Powiązane problemy