====== 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. * ganze Zahlen (Integers) * Kommazahlen (Float) * Zeichenketten (Strings) * Wahrheitswerte: True, False (bolean) * Listen (Listen sind Datenstrukturen). In Python kann eine Liste komplett unterschiedliche Dinge enthalten, d.h. die Datentypen können beliebig gemischt werden. 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. - 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). - Schreibe eine Funktion ''quadratf(n)'' welche ein gefülltes Quadrat baut. - Schreibe eine Funktion ''circle(n)'', welche einen "Kreis" mit Radius n baut - Schreibe eine Funktion ''tower(n,h)'' welche einen Turm mit quadratischer Grundfäche der Breite n und der Höhe h baut. - 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? - 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. - Versuche eine Parkettierung aus 20x20 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? - Versuche eine Parkettierung zu machen, welche aus 20x20 Blöcken besteht, welche ein diagonales Kreuz (ein waagerechtes Kreuz oder auch beides) hat. - 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)) === Lösung 4 === Damit die Funktion möglichst flexibel eingesetzt werden kann, sollte man sie //parametrisieren//, d.h. man kann der Funktion als Argumente übergeben, an welcher Position das Haus gebaut wird, bzw. welche Grösse es hat. === 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) === 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)