Inhaltsverzeichnis

5. Programmierkonzepte

5.1 Variablen und Datentypen

5.1.1 Variablen definieren

Eine Variable ist ein Behälter für eine Grösse. Diese wird durch einen Namen repräsentiert und zeigt auf eine bestimmte Adresse im Speicher des Computers. Variablen können beliebig wieder überschrieben werden.

a = 4 # In der Variablen a wird der Wert 4 gespeichert
name = 'Rene Lehmann' # In der Variablen name wird 'Rene Lehmann' gespeichert
strasse = "Lärchenweg" # doppelte Anführungszeichen gehen auch
pi = 3.141592 # Eine Fliesskommazahl
a = "Hallo" #die Variable a wird wieder überschrieben

5.1.2 Datentypen von Variablen

Wie wir oben gesehen haben, kann man in Variablen ganz unterschiedliche Dinge speichern. Z.B.

In vielen Programmiersprachen muss man sich bei einer bestimmten Variable entscheiden, von welchem Typ sie ist und kann dann nur diesen Typ verwenden. Nicht so in Python. In Python herrscht dynamische Typisierung vor, d.h. ich kann in einer Variablen a zunächst eine Zeichenkette speichern und dann diese durch eine ganze Zahl überschreiben und danach eine Kommazahl daraus machen.

5.2 Verzweigung mit if-elif-else

if agent.get_item_count(2)>=2:
    agent.set_slot(2)
    agent.place(BACK)
    agent.move(FORWARD, 1)
    agent.place(BACK)
elif agent.get_item_count(2)==1:
    agent.set_slot(2)
    agent.place(BACK)
else:
    player.say("Nix mehr in Slot 2")

5.3 Schleife mit while

while agent.get_item_count(1)>0:
    agent.place(BACK)
    agent.move(FORWARD,1)

5.4 Liste erstellen und durchgehen

l1 = [GRASS, STONE, OAK_DOOR] # Liste erstellen
agent.set_slot(1)
for item_type in l1: # Liste durchgehen
    agent.set_item(item_type, 1, 1)
    agent.place(BACK)
    agent.move(FORWARD, 1)

Eine Liste kann man auch sehr elegant mit dem range-Befehl erstellen:

range(10) # => [0,1,2,3,4,5,6,7,8,9]
range(9,18,3) # => [9, 12,15]

5.5 Eigene Funktionen definieren


# Eine Funktion definieren, welche zwei Parameter (n, type) nimmt
def build_line(n, type):
    agent.set_item(type,1,1)
    agent.set_slot(1)
    for i in range(n):
        agent.place(BACK)
        agent.move(FORWARD,1)

# Nun kanan die Funktion aufgerufen werden
build_line(5,GRASS)
build_line(8,STONE)

Aufgaben

Evtl. ist es sinnvoll, für die folgenden Aufgaben agent.set_assist(PLACE_ON_MOVE, True) zu setzen, damit der Agent bei jeder Bewegung baut.

  1. Schreibe eine Funktion quadrat(n), welche den Agent dazu bringt, ein nicht ausgefülltes Quadrat der Länge n zu bauen (n ist ein Parameter und kann beim Aufrufen der Funktion gewählt werden).
  2. Schreibe eine Funktion quadratf(n) welche ein gefülltes Quadrat baut.
  3. Schreibe eine Funktion circle(n), welche einen „Kreis“ mit Radius n baut
  4. Schreibe eine Funktion tower(n,h) welche einen Turm mit quadratischer Grundfäche der Breite n und der Höhe h baut.
  5. Schreibe eine Funktion kugel(n), welche eine Kugel baut mit „Radius“ n.

5.6 Modulo-Arithmetik (%)

Finde heraus, was das %-Zeichen macht. Öffne dazu z.B. Thonny und gib Zahlenbeispiele ein, z.B. 14 % 5, 21 % 4, 17 % 8 etc.

Überlege dir, was das untenstehende Programm macht:

for i in range(20):
    if (i % 2) == 0:
        blocks.place(GOLD_BLOCK, world(i, 4, 0))

Was ändert sich, wenn man statt %2, %3, %4 etc. schreibt?

  1. Schreibe mit Hilfe von Modulo (%) ein Programm, welches eine Linie von 40 Blocks baut, wobei immer abwechslungsweise ein Block aus EMERALD, einer aus GRANITE und einer aus Honig besteht.
  2. Versuche eine Parkettierung aus 20×20 Blöcken zu machen, welches ein Schachbrett nachahmt, d.h. die Blöcke müssen immer abwechseln (nimm z.B. Gold und Granit). Kann man hier elegant Modulo verwenden?
  3. Versuche eine Parkettierung zu machen, welche aus 20×20 Blöcken besteht, welche ein diagonales Kreuz (ein waagerechtes Kreuz oder auch beides) hat.
  4. Schreibe eine Funktion House(), welche ein Haus baut. Eine Idee wäre z.B., dass man einen gefüllten Block macht und ihn dann mit einem kleineren gefüllten Block aus 'Luft' wieder aushöhlt… danach kann man Fenster, Türe etc einfügen und das Dach machen. Man kann aber auch die Wände einzeln bauen, wenn man möchte.

Lösung 1

for i in range(40):
        if (i%3) == 0:
            blocks.place(GOLD_BLOCK,world(i,5,0))
        if (i%3) == 1:
            blocks.place(BLUE_WOOL,world(i,5,0))
        if (i%3) == 2:
            blocks.place(GREEN_WOOL,world(i,5,0))

Lösung 2

for i in range(20):
        for j in range(20):
            if (i+j) % 2 == 0:
                blocks.place(GOLD_BLOCK,pos(i,5,j))
            else:
                blocks.place(BLUE_WOOL,pos(i,5,j))

Alternative zu Nr. 2. (Léa)

def parkett3():
    for j in range(20):
        if (j % 2) == 0:
            for i in range(20):
                if (i % 2) == 0:
                    blocks.place(GOLD_BLOCK,pos(i,5,j))
                else:
                    blocks.place(BLUE_WOOL,pos(i,5,j))
        else: # (j % 2 ist hier 1)
            for i in range(20):
                if (i % 2) == 0:
                    blocks.place(BLUE_WOOL,pos(i,5,j)) 
                else:
                    blocks.place(GOLD_BLOCK,pos(i,5,j)) 

Lösung 3: Ein Kreuz (i==j oder i == 20-j

for i in range(10):
    for j in range(10):
        if (i==j or i==20-j):
            blocks.place(YELLOW_WOOL, world(i, 4, j))
        else:
            blocks.place(BLUE_WOOL,world(i,4,j))

Aufgabe 4: Ein einfaches Haus (parametrisiert)

def simple_house(xpos,ypos,zpos,breite, hoehe):
    blocks.fill(STONE_BRICKS,world(xpos,ypos,zpos),world(xpos+breite,ypos+hoehe, zpos+breite))
    blocks.fill(AIR, world(xpos+1,ypos,zpos+1),world(xpos+breite-1,ypos+hoehe-1, zpos+breite-1))
    #Tuere
    blocks.fill(AIR,world(xpos+4,ypos,zpos),world(xpos+4,ypos+1,zpos))
    blocks.place(ACACIA_DOOR,world(xpos+4,ypos,zpos))


simple_house(100,4,-18,7,10)
simple_house(140,4,-18,10,5)

6. Programmierbeispiele

A. Während sich der Spieler bewegt eine Funktion aufrufen, welche die Position zurückgibt (könnte für gesteuerte Interaktionen nützlich sein)

def on_travelled_walk():
    x = player.position().get_value(Axis.X)
    y = player.position().get_value(Axis.Y)
    z = player.position().get_value(Axis.Z)
    
    player.say("x:"+str(x)+" y:"+str(y)+" z:"+str(z))


player.on_travelled(WALK, on_travelled_walk)

Wie kann man Blöcke drehen (Z.B. Türen, Treppen etc)

Statt z.B. blocks.place(OAK_DOOR,world(0,0,0)) kann man den Block mit zugehörigem Datenwert platzieren:

blocks.place(blocks.block_with_data(OAK_DOOR, 0),world(0,0,0))

Der Daten-Wert gibt an, ob die Türe (oder Treppe) etc. geöffnet ist, nach links aufgeht etc.

Beispiel für eine Strasse (Wiederholung für den Mittelstreifen)

def strasse(xpos,ypos,zpos,laenge):
    blocks.fill(LIGHT_GRAY_CONCRETE,world(xpos,ypos,zpos),world(xpos+laenge,ypos,zpos+4))
    for i in range(xpos,xpos+laenge,2):
        blocks.place(CONCRETE,world(i,ypos,zpos+2))

strasse(700,3,700,40)