2016-09-09 1 views
4

Lasst uns sagen, ich habe zwei Objekte der MapTile Klasse:Wie kann man etwas als Objekt anstatt als Liste bezeichnen?

class MapTile(object):      #The main class for stationary things that inhabit the grid ... grass, trees, rocks and stuff. 
     def __init__(self, name, internal_column, internal_row, visible): 
      self.name = name 
      self.internal_column = internal_column 
      self.internal_row = internal_row 
      self.visible = visible 

, die einen 2-dimensionalen Array bewohnen, ihre jeweiligen internal_column und internal_row Attribute deren Koordinaten im Array darstellt.

Ich möchte eine Funktion schreiben, die den Abstand zwischen zwei solcher Objekte zurückgibt. Hier ist, was ich bisher:

def return_distance(self, pointA, pointB): 
     distance = math.sqrt((pointA.internal_column - pointB.internal_column)**2 + (pointA.internal_row - pointB.internal_row)**2) 
     return distance 

Wo pointA und pointB würden die beiden Objekte sein.

Wenn ich es ausprobieren, bekomme ich diesen Fehler:

Traceback (most recent call last): 
    File "/Users/kosay.jabre/Desktop/Monster.py", line 380, in <module> 
    Map.update() 
    File "/Users/kosay.jabre/Desktop/Monster.py", line 297, in update 
    if Map.return_distance(Map.Grid[column][row], character) <= character.visionrange: 
    File "/Users/kosay.jabre/Desktop/Monster.py", line 245, in return_distance 
    distance = math.sqrt((pointA.internal_column - pointB.internal_column)**2 + (pointA.internal_row - pointB.internal_row)**2) 
AttributeError: 'list' object has no attribute 'internal_column' 

Ich rufe die Abstandsfunktion wie folgt aus:

for character in Map.everyone: 
    for column in range(MAPSIZE): 
     for row in range(MAPSIZE): 
      if Map.return_distance(Map.Grid[column][row], character) <= character.visionrange: 
       Map.Grid[column][row].visible = True 

Was soll ich tun? Wie kann ich auf die Attribute des Objekts in "Map.Grid [Spalte] [Zeile]" anstelle von "Map.Grid [Spalte] [Zeile]" selbst als Liste zugreifen? Hier ist, wie Map.Grid erstellt:

MAPSIZE = 25 

class Map(object):    #The main class; where the action happens 
    global MAPSIZE 
    Grid = [] 
    friendlies = [] 
    enemies = [] 
    everyone = [friendlies + enemies] 
    visible = [] 

    for row in range(MAPSIZE):  # Creating grid 
     Grid.append([]) 
     for column in range(MAPSIZE): 
      Grid[row].append([]) 

    for row in range(MAPSIZE):  #Filling grid with grass 
     for column in range(MAPSIZE): 
      TempTile = MapTile("Grass", column, row, False) 
      Grid[column][row].append(TempTile) 

und ich füge hinzu Dinge direkt so Map.everyone:

for column in range(MAPSIZE): 
      for row in range(MAPSIZE): 
       for i in range(len(Map.Grid[column][row])): 
        if Map.Grid[column][row][i].__class__.__name__ == "Character": 
         Map.everyone.append(Map.Grid[column][row][i]) 

Hier ist die vollständige, vollständige Code, wie ich es bin mit:

import random 
import math 
import pygame 

pygame.init()         
Clock = pygame.time.Clock()     
Screen = pygame.display.set_mode([650, 650]) 
DONE = False         
MAPSIZE = 25 #how many tiles 
TURN = 0 


TILEWIDTH = 20 #pixel size of tile        
TILEHEIGHT = 20 
TILEMARGIN = 4 

BLACK = (0, 0, 0)        
WHITE = (255, 255, 255) 
GREEN = (0, 255, 0) 
RED = (255, 0, 0) 
BLUE = (0, 0, 255) 
BROWN = (123, 123, 0) 
MOVECOLOR = (150, 250, 150) 

KeyLookup = { 
    pygame.K_LEFT: "W", 
    pygame.K_RIGHT: "E", 
    pygame.K_DOWN: "S", 
    pygame.K_UP: "N" 
} 

class MapTile(object):      #The main class for stationary things that inhabit the grid ... grass, trees, rocks and stuff. 
    def __init__(self, name, internal_column, internal_row, visible): 
     self.name = name 
     self.internal_column = internal_column 
     self.internal_row = internal_row 
     self.visible = visible 

class Character(object):     #can move around and do cool stuff 
    def __init__(self, name, HP, internal_column, internal_row, damage, allegiance): 
     self.name = name 
     self.HP = HP 
     self.internal_column = internal_column 
     self.internal_row = internal_row 
     self.damage = damage 
     self.allegiance = allegiance 

    visionrange = 10 
    moves_left = 15 
    direction = "N" 

    def move(self, direction):  #how characters move around 
     if self.collision_check(direction): 
      print("Collision") 
      return 
     if self.moves_left == 0: 
      print("No more moves left") 
      return 

     elif direction == "N":      
       self.internal_row -= 1 
       self.direction = "N" 
     elif direction == "W": 
       self.internal_column -= 1 
       self.direction = "W" 
     elif direction == "E": 
       self.internal_column += 1 
       self.direction = "E" 
     elif direction == "S": 
       self.internal_row += 1 
       self.direction = "S" 

     self.moves_left = self.moves_left - 1 


    def collision_check(self, direction):  
     if direction == "N": 
      if self.internal_row == 0: 
       return True 
      if len(Map.Grid[self.internal_column][(self.internal_row)-1]) > 1: 
       return True 
     elif direction == "W": 
      if self.internal_column == 0: 
       return True 
      if len(Map.Grid[self.internal_column-1][(self.internal_row)]) > 1: 
       return True 
     elif direction == "E": 
      if self.internal_column == MAPSIZE-1: 
       return True 
      if len(Map.Grid[self.internal_column+1][(self.internal_row)]) > 1: 
       return True 
     elif direction == "S": 
      if self.internal_row == MAPSIZE-1: 
       return True 
      if len(Map.Grid[self.internal_column][(self.internal_row)+1]) > 1: 
       return True 

     return False 

    def attack(self, direction): 
     if self.collision_check(direction): 
      print("Attack attempt.") 
      if self.direction == "N": 
       for i in range(0, len(Map.Grid[self.internal_column][self.internal_row-1])): 
       if Map.Grid[int(self.internal_column)][int(self.internal_row-1)][i].__class__.__name__ == "Character": 
        Map.Grid[self.internal_column][self.internal_row-1][i].HP -= self.damage 
        print(str(self.damage) + " damage") 
      elif self.direction == "E": 
       for i in range(0, len(Map.Grid[self.internal_column+1][self.internal_row])): 
        if Map.Grid[self.internal_column+1][self.internal_row][i].__class__.__name__ == "Character": 
         Map.Grid[self.internal_column+1][self.internal_row][i].HP -= self.damage 
         print(str(self.damage) + " damage") 
      elif self.direction == "W": 
       for i in range(0, len(Map.Grid[self.internal_column-1][self.internal_row])): 
        if Map.Grid[self.internal_column-1][self.internal_row][i].__class__.__name__ == "Character": 
         Map.Grid[self.internal_column-1][self.internal_row][i].HP -= self.damage 
         print(str(self.damage) + " damage") 
      elif self.direction == "S": 
       for i in range(0, len(Map.Grid[self.internal_column][self.internal_row+1])): 
        if Map.Grid[self.internal_column][self.internal_row+1][i].__class__.__name__ == "Character": 
         Map.Grid[self.internal_column][self.internal_row+1][i].HP -= self.damage 
         print(str(self.damage) + " damage") 

      self.moves_left = self.moves_left - 1 

    def ranged_attack(self, direction): 
      if self.direction == "S": 
       for k in range(1, (MAPSIZE - self.internal_row)): 
        for i in range(0, len(Map.Grid[self.internal_column][self.internal_row + k])): 
         if Map.Grid[self.internal_column][self.internal_row + k][i].__class__.__name__ == "Character": 
          Map.Grid[self.internal_column][self.internal_row + k][i].HP -= self.damage 
          print(str(self.damage) + " damage") 
          self.moves_left = self.moves_left - 1 
      if self.direction == "N": 
       for k in range(1, self.internal_row): 
        for i in range(0, len(Map.Grid[self.internal_column][self.internal_row - k])): 
         if Map.Grid[self.internal_column][self.internal_row - k][i].__class__.__name__ == "Character": 
          Map.Grid[self.internal_column][self.internal_row - k][i].HP -= self.damage 
          print(str(self.damage) + " damage") 
          self.moves_left = self.moves_left - 1 
      if self.direction == "W": 
       for k in range(1, self.internal_column): 
        for i in range(0, len(Map.Grid[self.internal_column - k][self.internal_row])): 
         if Map.Grid[self.internal_column - k][self.internal_row][i].__class__.__name__ == "Character": 
          Map.Grid[self.internal_column - k][self.internal_row][i].HP -= self.damage 
          print(str(self.damage) + " damage") 
          self.moves_left = self.moves_left - 1 
      if self.direction == "E": 
       for k in range(1, (MAPSIZE - self.internal_column)): 
        for i in range(0, len(Map.Grid[self.internal_column + k][self.internal_row])): 
         if Map.Grid[self.internal_column + k][self.internal_row][i].__class__.__name__ == "Character": 
          Map.Grid[self.internal_column + k][self.internal_row][i].HP -= self.damage 
          print(str(self.damage) + " damage") 
          self.moves_left = self.moves_left - 1 
      else: 
       return 


class Goblin(Character): 
    def __init__(self): 
     Character.__init__(self, "Goblin", random.randint(15,20), random.randint(0,MAPSIZE-1), random.randint(0,MAPSIZE-1), 10, random.randint(0,1)) 

    def random_move(self): 
     i = random.randint(0,3) 
     if i == 0: 
      self.move("N") 
     elif i == 1: 
      self.move("S") 
     elif i == 2: 
      self.move("W") 
     elif i == 3: 
      self.move("E") 

     self.moves_left = 10 


class Archer(Character): 
    def __init__(self): 
     Character.__init__(self, "Archer", random.randint(15,20), random.randint(0,MAPSIZE-1), random.randint(0,MAPSIZE-1)) 


class Warrior(Character): 
    def __init__(self): 
     Character.__init__(self, "Warrior", random.randint(15,20), random.randint(0,MAPSIZE-1), random.randint(0,MAPSIZE-1)) 


class Scout(Character): 
    def __init__(self): 
     Character.__init__(self, "Scout", random.randint(15,20), random.randint(0,MAPSIZE-1), random.randint(0,MAPSIZE-1)) 


class Rogue(Character): 
    def __init__(self): 
     Character.__init__(self, "Rogue", random.randint(15,20), random.randint(0,MAPSIZE-1), random.randint(0,MAPSIZE-1)) 


class Wizard(Character): 
    def __init__(self): 
     Character.__init__(self, "Wizard", random.randint(15,20), random.randint(0,MAPSIZE-1), random.randint(0,MAPSIZE-1)) 


class Map(object):    #The main class; where the action happens 
    global MAPSIZE 
    wild_characters = [] 
    can_move = [] 
    no_moves = [] 
    Grid = [] 
    friendlies = [] 
    enemies = [] 
    everyone = [friendlies + enemies] 
    visible = [] 

    for row in range(MAPSIZE):  # Creating grid 
     Grid.append([]) 
     for column in range(MAPSIZE): 
      Grid[row].append([]) 

    for row in range(MAPSIZE):  #Filling grid with grass 
     for column in range(MAPSIZE): 
      TempTile = MapTile("Grass", column, row, False) 
      Grid[column][row].append(TempTile) 

    for row in range(MAPSIZE):  #Putting some rocks near the top 
     for column in range(MAPSIZE): 
      TempTile = MapTile("Rock", column, row, False) 
      if row == 1: 
       Grid[column][row].append(TempTile) 

    for i in range(10):   #Trees in random places 
     random_row = random.randint(0, MAPSIZE - 1) 
     random_column = random.randint(0, MAPSIZE - 1) 
     TempTile = MapTile("Tree", random_column, random_row, False) 
     Grid[random_column][random_row].append(TempTile) 

    def generate_hero(self):   #Generate a character and place it randomly 
     temp_hero = Character("Hero", 30, random.randint(0, MAPSIZE - 1), random.randint(0, MAPSIZE - 1) , 10, random.randint(0,1)) 
     self.Grid[temp_hero.internal_column][temp_hero.internal_row].append(temp_hero) 
     self.can_move.append(temp_hero) 
     if temp_hero.allegiance == 0: 
      self.friendlies.append(temp_hero) 
     elif temp_hero.allegiance == 1: 
      self.enemies.append(temp_hero) 

    def return_distance(self, pointA, pointB): 
     distance = math.sqrt((pointA.internal_column - pointB.internal_column)**2 + (pointA.internal_row - pointB.internal_row)**2) 
     return distance 

    def generate_goblin(self):   #Generate a character and place it randomly 
     random_row = random.randint(0, MAPSIZE - 1) 
     random_column = random.randint(0, MAPSIZE - 1) 
     temp_goblin = Goblin() 
     self.Grid[random_column][random_row].append(temp_goblin) 
     Map.wild_characters.append(temp_goblin) 

    def update(self):   
     for column in range(MAPSIZE):       #These nested loops go through entire grid 
      for row in range(MAPSIZE):       #They check if any objects internal coordinates 
       for i in range(len(Map.Grid[column][row])):  #disagree with its place on the grid and update it accordingly        
        if Map.Grid[column][row][i].internal_column != column: 
         TempChar = Map.Grid[column][row][i] 
         Map.Grid[column][row].remove(Map.Grid[column][row][i]) 
         Map.Grid[int(TempChar.internal_column)][int(TempChar.internal_row)].append(TempChar) 

        elif Map.Grid[column][row][i].internal_row != row: 
         TempChar = Map.Grid[column][row][i] 
         Map.Grid[column][row].remove(Map.Grid[column][row][i]) 
         Map.Grid[int(TempChar.internal_column)][int(TempChar.internal_row)].append(TempChar) 

     temparr = Map.no_moves[:] 
     for characterobject in temparr: #This moves any characters with moves to the can move list 
      if len(temparr) > 0: 
       if characterobject.moves_left > 0: 
        Map.can_move.append(characterobject) 
        Map.no_moves.remove(characterobject) 
      if characterobject.HP <= 0: 
       Map.no_moves.remove(characterobject) 

     arr = Map.can_move[:] # copy 
     for item in arr: 
      if item.moves_left == 0: 
       Map.can_move.remove(item) 
       Map.no_moves.append(item) 
      if item.HP <= 0: 
       Map.can_move.remove(item) 

     for column in range(MAPSIZE):       
      for row in range(MAPSIZE):       
       for i in range(len(Map.Grid[column][row])):  
        if Map.Grid[column][row][i].__class__.__name__ == "Character": 
         if Map.Grid[column][row][i].HP <= 0: 
          Map.Grid[column][row].remove(Map.Grid[column][row][i]) 
          print("Character died") 

     for column in range(MAPSIZE): 
      for row in range(MAPSIZE): 
       for i in range(len(Map.Grid[column][row])): 
        if Map.Grid[column][row][i].__class__.__name__ == "Character": 
         Map.everyone.append(Map.Grid[column][row][i]) 

     for character in Map.everyone:    
      for column in range(MAPSIZE): 
       for row in range(MAPSIZE): 
        if Map.return_distance(Map.Grid[column][row][0], character) <= 15: 
         Map.Grid[column][row].visible = True 

    def listofcharacters(self): 
     for column in range(MAPSIZE): 
      for row in range(MAPSIZE): 
       for i in range(len(Map.Grid[column][row])): 
        if Map.Grid[column][row][i].__class__.__name__ == "Character": 
         print("Column: ", Map.Grid[column][row][i].internal_column, ", Row: ", Map.Grid[column][row][i].internal_row, ", Allegiance: ", Map.Grid[column][row][i].allegiance) 





Map = Map() 
Map.generate_hero() 

while not DONE:  #Main pygame loop 
    for event in pygame.event.get():   #catching events 
     if event.type == pygame.QUIT: 
      DONE = True  
     elif event.type == pygame.MOUSEBUTTONDOWN: 
      Pos = pygame.mouse.get_pos() 
      column = Pos[0] // (TILEWIDTH + TILEMARGIN) #Translating the position of the mouse into rows and columns 
      row = Pos[1] // (TILEHEIGHT + TILEMARGIN) 
      print(str(row) + ", " + str(column)) 

      for i in range(len(Map.Grid[column][row])): 
       print(str(Map.Grid[column][row][i].name)) #print stuff that inhabits that square 

     elif event.type == pygame.KEYDOWN: 
      wild_char_arr = Map.wild_characters[:] 

      for wildcharacter in wild_char_arr: 
       if wildcharacter.name == "Goblin": 
        wildcharacter.random_move() 

      if event.key == 97:  # Keypress: a 
       print("New turn.") 
       temparr = Map.no_moves[:] 
       for item in temparr: 
        if item.moves_left == 0: 
         item.moves_left = 15 
       TURN = TURN + 1 
       print("Turn: ", TURN) 

      elif event.key == 115: # Keypress: s 
       print("Generated hero.") 
       Map.generate_hero() 

      elif event.key == 113: # Keypress: q  
       print("ranged attack") 
       Map.can_move[0].ranged_attack(Map.can_move[0].direction) 

      elif event.key == 119: # Keypress: w 
       print("Generated hero.") 
       Map.generate_hero() 

      elif event.key == 101: # Keypress: e 
       print("Generated hero.") 
       Map.generate_hero() 

      elif event.key == 114: # Keypress: r 
       print("Generated hero.") 
       Map.generate_hero() 

      elif event.key == 116: # Keypress: t 
       print("Generated hero.") 
       Map.generate_hero() 

      elif event.key == 100: # Keypress: d 
       Map.generate_goblin() 
       print("Generated goblin.") 

      elif event.key == 102: # Keypress: f 
       Map.can_move[0].attack(Map.can_move[0].direction) 

      elif len(Map.can_move) > 0: 
       Map.can_move[0].move(KeyLookup[event.key]) 

      else: 
       print("invalid") 

      Map.update() 

    Screen.fill(BLACK) 

    for row in range(MAPSIZE):   # Drawing grid 
     for column in range(MAPSIZE): 
      for i in range(0, len(Map.Grid[column][row])): 
       Color = WHITE 

       if len(Map.can_move) > 0: # Creating colored area around character showing his move range 
        if (math.sqrt((Map.can_move[0].internal_column - column)**2 + (Map.can_move[0].internal_row - row)**2)) <= Map.can_move[0].moves_left: 
         Color = MOVECOLOR 

       if len(Map.Grid[column][row]) > 1: 
        Color = RED 
       if Map.Grid[column][row][i].name == "Tree": 

        Color = GREEN 
       if str(Map.Grid[column][row][i].__class__.__name__) == "Character": 
        Color = BROWN 

      pygame.draw.rect(Screen, Color, [(TILEMARGIN + TILEWIDTH) * column + TILEMARGIN, 
              (TILEMARGIN + TILEHEIGHT) * row + TILEMARGIN, 
              TILEWIDTH, 
              TILEHEIGHT]) 

      if str(Map.Grid[column][row][i].__class__.__name__) == "Character": 
       if Map.Grid[column][row][i].direction == "N": 
        Color = RED 

        pygame.draw.rect(Screen, Color, [(TILEMARGIN + TILEWIDTH) * column + TILEMARGIN + 8, 
              (TILEMARGIN + TILEHEIGHT) * row + TILEMARGIN, 
              TILEWIDTH/4, 
              TILEHEIGHT/4]) 

      if str(Map.Grid[column][row][i].__class__.__name__) == "Character": 
       if Map.Grid[column][row][i].direction == "S": 
        Color = RED 

        pygame.draw.rect(Screen, Color, [(TILEMARGIN + TILEWIDTH) * column + TILEMARGIN + 8, 
              (TILEMARGIN + TILEHEIGHT) * row + TILEMARGIN*5 - 1 , 
              TILEWIDTH/4, 
              TILEHEIGHT/4]) 

      if str(Map.Grid[column][row][i].__class__.__name__) == "Character": 
       if Map.Grid[column][row][i].direction == "E": 
        Color = RED 

        pygame.draw.rect(Screen, Color, [(TILEMARGIN + TILEWIDTH) * column + TILEMARGIN + 15, 
              (TILEMARGIN + TILEHEIGHT) * row + TILEMARGIN*5 - 8, 
              TILEWIDTH/4, 
              TILEHEIGHT/4]) 

      if str(Map.Grid[column][row][i].__class__.__name__) == "Character": 
       if Map.Grid[column][row][i].direction == "W": 
        Color = RED 

        pygame.draw.rect(Screen, Color, [(TILEMARGIN + TILEWIDTH) * column + TILEMARGIN 
                , 
              (TILEMARGIN + TILEHEIGHT) * row + TILEMARGIN*5 - 8 , 
              TILEWIDTH/4, 
              TILEHEIGHT/4]) 


    Clock.tick(60)  
    pygame.display.flip()  

pygame.quit() 
+0

Ich denke, Sie müssen mehr Informationen darüber geben, was die Typen jedes Mitglieds erwartet werden. –

+0

Was meinst du? – Kos

+0

Nun eine der Map.Grid [Spalte] [Zeile] oder Zeichen ist eine Liste anstelle einer MapTile. Welchen Typ von Objekten haben Sie erwartet, um jeden dieser Ausdrücke zu belegen? –

Antwort

3

In Map:

friendlies = [] 
enemies = [] 
everyone = [friendlies + enemies] 

Dies bedeutet, dass everyone als Liste einer leeren Liste definiert ist: [ [] + [] ] == [ [] ]. Dies wiederum bedeutet:

for character in Map.everyone: 

character ist die leere Liste [], die Ihre Fehler verursacht.

Auch, weil dies zum Zeitpunkt der Zuweisung einmal ausgewertet wird, wenn Sie später ändern friendlies und enemies sie den Wert der everyone nicht ändern.

+0

Wie mache ich es so, dass jeder wirklich nur der kombinierte Inhalt von Freundschaftsspielen und Feinden ist? Also, wenn entweder Updates, jeder Inhalt wird es stattdessen eine leere Liste + der Inhalt sein? Aktualisieren als Freundschafts- und Gegnerupdates? – Kos

+0

Es gibt keine eingebaute Möglichkeit, zwei Listen automatisch zu einer dritten zusammenzufassen und Aktualisierungen der Quelllisten in der zusammengesetzten Liste widerzuspiegeln. Dies sollte als separate Frage gestellt werden. :) –

3

Es sieht so aus, als ob Sie eine Liste von Listen erstellen, wenn Sie nur eine Liste von Listen benötigen. Die row Liste kann Ihre MapTile s direkt enthalten; Sie müssen es nicht mit weiteren Listen füllen.

Versuchen Sie stattdessen:

for row in range(MAPSIZE):  # Creating grid 
    Grid.append([]) 

for row in range(MAPSIZE):  #Filling grid with grass 
    for column in range(MAPSIZE): 
     TempTile = MapTile("Grass", column, row, False) 
     Grid[row].append(TempTile) 

Auf diese Weise Grid nur eine Liste von Zeilen, und jede Zeile ist eine Liste von Fliesen, eine Kachel pro Spalte.

Verwandte Themen