Python city Simulator

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Ronald_MacDonald
User
Beiträge: 4
Registriert: Mittwoch 13. Mai 2020, 14:12

Hallo zusammen,

Ich muss als Aufgabe eine "City-Simulation" Application programmieren.
Es geht darum eine random Karte zu generieren, diese grafisch (so rastermässig) auszugeben und dann ein paar Autos und Menschen automatisch drüber laufen zu lassen. Sprich das das Programm alle paar Sekunden von selbst aktualisiert und dann wie erwähnt die Autos fahren und die Menschen über die Strassen umherlaufen.

Anbei habe ich einmal alles was ich schon habe reinkopiert... Irgendwie hänge ich aber nun ein wenig wie es weiter geht. Zudem bin ich mir bewusst, dass mein Programm schon noch sehr kompliziert und umständlich aussieht. Da ich aber noch ein ziemlicher Amateur bin dachte ich mir das ich zuerst einmal schaue das es irgendwie läuft und ich dann zum Schluss beginne alles zu überarbeiten.
Kann mir jemand einen Tipp geben wie ich weiterfahren soll? bzw. wie ich das Programmieren könnte das sich Autos etc. über die Karte bewegen können?

Vielen Dank für die Hilfe

class Car:
def __init__(self):
self.car = ("\U0001F697")

class Person:
def __init__(self):
self.person = ("\U0001F6B9")

class Create: #Hier wird die Grundkarte erstellt
def __init__(self):
self.grid = None
self.starttime = None
self.endtime= None
self.vote = None
gras = "\033[32m\U0001F7E9" #gestrichelt
water = "\033[34m\U0001F7E6" #blue / getrichelt
empty_street = "\033[37m\U00002B1C" #white/grey
house = "\033[30m\U00002B1B" #black
self.symbols = [self.empty_street, water, house, gras]

def choice(self): #Hier hat der Benutzer die Wahl ob er eine random Karte will oder eine bestehende basierend auf einer bekannten stadt...
self.vote = int(input('Wollen Sie eine zufällige Karte (1) erstellen, oder einen Karten-Ausschnitt von xyz (2) wählen? '))
return self.vote

def random_grid_maker(self):
x1 = random.randint(1, 30)
x2 = random.randint(1, 30)
x3 = random.randint(1, 30)
x4 = random.randint(1, 30)
x5 = random.randint(1, 30)
n = 30
self.grid = [[0] * n for i in range(n)]
for i in range(n):
for j in range(n):
if i == x1 or i == x2 or i == x3 or i == x4 or i == x5:
self.grid[j] = "\033[37m\U00002B1C" #white/grey
elif j == x1 or j == x2 or j == x3 or j == x4 or j == x5:
self.grid[j] = "\033[37m\U00002B1C" #white/grey
elif i == x1+1 or i == x2+1 or i == x3+1 or i == x4+1 or i == x5+1:
self.grid[j] = "\033[30m\U00002B1B" #black
elif j == x1+1 or j == x2+1 or j == x3+1 or j == x4+1 or j == x5+1:
self.grid[j] = "\033[30m\U00002B1B" #black
elif i == x1-1 or i == x2-1 or i == x3-1 or i == x4-1 or i == x5-1:
self.grid[j] = "\033[30m\U00002B1B" #black
elif j == x1-1 or j == x2-1 or j == x3-1 or j == x4-1 or j == x5-1:
self.grid[j] = "\033[30m\U00002B1B" #black
else:
self.grid[j] = "\033[32m\U0001F7E9" #grün gestrichelt
for row in self.grid:
print(''.join([str(elem) for elem in row]))
return self.grid

def realistic(self):
x1 = 5
x2 = 10
x3 = 15
x4 = 20
x5 = 25
n = 30
self.grid = [[0] * n for i in range(n)]
for i in range(n):
for j in range(n):
if i == x1 or i == x2 or i == x3 or i == x4 or i == x5:
self.grid[j] = "\033[37m\U00002B1C" #white/grey
elif j == x1 or j == x2 or j == x3 or j == x4 or j == x5:
self.grid[j] = "\033[37m\U00002B1C" #white/grey
elif i == x1+1 or i == x2+1 or i == x3+1 or i == x4+1 or i == x5+1:
self.grid[j] = "\033[30m\U00002B1B" #black
elif j == x1+1 or j == x2+1 or j == x3+1 or j == x4+1 or j == x5+1:
self.grid[i][j] = "\033[30m\U00002B1B" #black
elif i == x1-1 or i == x2-1 or i == x3-1 or i == x4-1 or i == x5-1:
self.grid[i][j] = "\033[30m\U00002B1B" #black
elif j == x1-1 or j == x2-1 or j == x3-1 or j == x4-1 or j == x5-1:
self.grid[i][j] = "\033[30m\U00002B1B" #black
else:
self.grid[i][j] = "\033[32m\U0001F7E9" #grün gestrichelt
for row in self.grid:
print(''.join([str(elem) for elem in row]))
return self.grid


def execute_1(self): # Hier wird alles aufgerufen, dass man nicht alles separat aufrufen muss...
self.choice()
if self.vote == 1:
self.random_grid_maker()
elif self.vote == 2:
self.realistic()
else:
raise Exception('Falsche Eingabe, Sie müssen die Zahl 1 oder zwei wählen')
self.execute_1()

class City_Game(Create): #Hier wird das eigentliche Spiel gestartet... damit es
def __init__(self):
Create.__init__(self)
self.grid2 = self.grid

def aufgabe_1(self):
# Hier wird der Task 1 programmiert
return

def ausgabe_2(self):
return

def update(self):
#Hier wird das Programm laufend udated... sprich der Spielfluss...
return

if __name__ == "__main__":
a = Create()
a.execute_1()
print(a)


#zip funktion... um farbe und farbcodierung hinzuzufügen...
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Ronald_MacDonald hat geschrieben: Mittwoch 13. Mai 2020, 14:27 Kann mir jemand einen Tipp geben wie ich weiterfahren soll? bzw. wie ich das Programmieren könnte das sich Autos etc. über die Karte bewegen können?
Bitte benutz die Code-Tags im Forum für Quelltext, denn in der jetzigen Form ist das nur schwer zu lesen.

Für Einsteiger ist das eine ganz schön heftige Aufgabe, finde ich. Alleine schon das Erzeugen einer halbwegs plausiblen Karte ist alles andere als trivial (eine Stichwort zum Suchen wäre hier "procedural generation"). Grundsätzlich würde ich das runden-basiert implementieren ähnlich, wie man auch zum Beispiel ein Rouge-like oder auch Conways Game of Life umsetzt. D.h. du hast eine zugrunde liegende Datenstruktur für ein 2D-Grid bzw. einen Graphen. Jeder Knoten bzw. jede Zelle ist ein Spielfeld in deiner Simulation und enthält z.B. Informationen den Geländetype, die Entitäten, die sich dort befinden, welche Felder benachbart sind, etc.. Die eigentliche Simulation läuft dann Runden basiert, indem du dein Level Feld für Feld durchgehst und für jedes der dortigen Elemente die damit verknüpfte Aktion durchführst. Die Ergebnisse schreibst du in eine neue Variante deiner Datenstruktur, die am Ende der Runde die bisher ersetzt. Das wäre ein mögliches Konzept, für die grobe Architektur. Dann ist aber noch viel Detailarbeit zu leisten.
Ronald_MacDonald
User
Beiträge: 4
Registriert: Mittwoch 13. Mai 2020, 14:12

Super, Vielen Dank für die schnelle Antwort... Dann werde ich einmal ein wenig recherchieren...
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Klassen Car und Person sind noch nicht sehr sinnvoll.
Wenn die Symbole konstant sind, dann sollten das auch Klassenkonstanten sein und vielleicht SYMBOL heißen.

Code: Alles auswählen

class Car:
    SYMBOL = "\U0001F697"

class Person:
    SYMBOL = "\U0001F6B9"
Klassen sollten nach Zuständen und nicht nach Tätigkeiten benannt werden, im Gegensatz zu Methoden, wo es genau umgekehrt ist: Create -> Map, random_grid_maker -> make_random_grid.
Der Kommentar zeigt auch deutlich, dass Du hier eher eine Funktion meinst, statt einer Klasse.

Die Methode choice hat als Methode auf der Klasse nichts zu suchen.
`self.empty_street` ist nicht definiert.
Wenn man Variablen durchnummeriert, will man eigentlich Listen benutzen. Dann sind die Tests mit `in` auch viel einfacher.
Wenn Du schon Namen für die Symbole vergeben hast, dann verwende die auch.
Statt eine Liste mit Dummy-Werten zu initialisieren und dann zu überschreiben, erstellt man die Listen direkt mit den richtigen Werten.
Die Elemente sind schon Strings, so dass es nicht nötig ist, die nochmal mit str umzuwandeln.
Eine Funktion, die ein Attribut füllt, sollte das nicht auch noch zurückgeben.
Ausgabe sollte in eine eigene Methode.

Was soll denn das 1 bei `execute`?

Code: Alles auswählen

class Map:
    GRAS = "\033[32m\U0001F7E9" #gestrichelt
    WATER = "\033[34m\U0001F7E6" #blue / getrichelt
    EMPTY_STREET = "\033[37m\U00002B1C" #white/grey
    HOUSE = "\033[30m\U00002B1B" #black
    SYMBOLS = [EMPTY_STREET, WATER, HOUSE, GRAS]

    def __init__(self):
        self.grid =  None
        
    def print_grid(self):
        for row in self.grid:
            print(''.join(row))

    def make_random_grid(self, n=30):
        positions = [random.randint(1, n) for _ in range(5)]
        self.grid = []
        for i in range(n):
            row = []
            for j in range(n):
                if i in positions or j in positions:
                    symbol = self.EMPTY_STREET
                elif (i in [p+1 for p in positions] or j in [p+1 for p in positions]
                        or j in [p-1 for p in positions] or j in [p-1 for p in positions])
                    symbol = self.HOUSE
                else:
                    symbol = self.GRAS
                row.append(symbol)
            self.grid.append(row)
Warum bindest Du grid zusätzlich an grid2 in City_Game? Vererbung ist hier auch die falsche Struktur. Ein City_Game ist ja keine Karte, sondern enthält vielleicht eine Karte.
Antworten