lehrkraefte:blc:informatik:ffprg1-2018:ffprg1-2018

This is an old revision of the document!


Freifach Einführung ins Programmieren

Direkt-Link: https://fginfo.ksbg.ch/ffprog

  • Jeweils Dienstags, 16:25 - 17:58 im H21.
  • Nach Möglichkeit soll ein eigener Laptop mitgebracht werden.
  • Wir programmieren mit TigerJython.

Wer programmiert die schlauste Schlange?

Version 0.1 (vom 8.3.2017): tjsnake.zip. Tester sind willkommen.

Anleitung

  • Archiv entpacken (wirklich entpacken, nur weil Windows die Dateien im Archiv anzeigt, sind diese deswegen noch nicht entpackt).
  • game.py in Tigerjython starten.
  • Für eigene Strategie ivo_beispiel_strategy.py kopieren und wie folgt benennen: name_xyz_strategie.py, nur Kleinbuchstaben a-z und _ (underscore). Die Datei muss mit dem eigenen Namen beginnen und mit strategie.py aufhören.
  • In game.py:
    • Die eigene Strategie importen (ganz oben im Code)
    • Eigene Strategie ganz unten in game.py eintragen.
  • Code studieren, Fragen stellen.

Dokumentation

Entweder direkt Kommentare im Code oder online.

Als Vorbereitung auf das Snake-Spiel: Wegfindung in einem Labyrinth:

wegfinden.py
from gpanel import *
 
import random 
import time
 
width = 40
 
vecs = [[1,0],[0,1],[-1,0],[0,-1]]
 
makeGPanel(0, width, 0, width)
 
# Array mit Distanzen fuer alle Punkte, gefuellt mit -1
dist = [[-1 for y in range(width)] for x in range(width)]
 
 
for i in range(800):
    x=random.randint(1,width-1)
    y=random.randint(1,width-1)
    fillRectangle(x,y,x+1,y+1)
 
 
todo=[(0,0)]
dist[0][0] = 0
 
waitTime = 0.002
 
maxDist = 0
 
setColor("red")
while len(todo)>0:
    #waitTime*=0.99
    #print(todo)
    pt = todo.pop(0) #vorne entfernen
    aktuelle_d = dist[pt[0]][pt[1]]
    if aktuelle_d>maxDist:
        maxDist = aktuelle_d
    setColor("blue")
    move(pt[0]+0.5, pt[1]+0.5)
    fillRectangle(0.5,0.5)
    time.sleep(waitTime)
    for d in range(4):
        p = (pt[0]+vecs[d][0], pt[1]+vecs[d][1])
        if (p[0]>=0 and p[0]<width and p[1]>=0 and p[1]<width):
            #print(p, getPixelColor(p[0]+0.5, p[1]+0.5))
            if getPixelColor(p[0]+0.5, p[1]+0.5)==makeColor("white"):
                setColor("red")
                move(p[0]+0.5, p[1]+0.5)
                fillRectangle(0.5,0.5)
                todo.append(p)  # Hinten anfuegen
                dist[p[0]][p[1]] = aktuelle_d + 1
                time.sleep(waitTime)
 
print(maxDist)
 
for x in range(width):
    for y in range(width):
        move(x+0.5,y+0.5)
        if dist[x][y]>=0:
            setColor(dist[x][y]/maxDist*255,255-dist[x][y]/maxDist*255,0)
            fillRectangle(0.5,0.5)
        else:
            setColor("black")
            fillRectangle(1,1)
 
 

Primzahlen auf eine Spirale darstellen.

Die Spirale soll “quadratisch” aussehen, d.h. man bewegt sich nur in die Achsenrichtungen um ganze Pixel (Bildpunkte) fort.

Man startet in der Mitte und geht dann reihum und zählt die Schritte (in Pixeln). Immer wenn die Schrittnummer prim ist, wird der entsprechende Pixel markiert.

Implementation

Die vier Richtungsvektoren werden in ein zweidimensionales Array gespeichert (Arrays sollten im Plural bezeichnet werden):

vecs=[[1,0],[0,1],[-1,0],[0,-1]];  # Vier Richtungen, im trigonometrischen Umlaufsinn

Die aktuelle Richtung wird als Zahl zwischen 0 und 3 dargestellt. Eine Drehung um 90 Grad heisst also 1 addieren oder subtrahieren und nötigenfalls wieder auf den Bereicht 0 bis 3 anpassen. Dafür eignet sich die Modulo-Operation:

dir = 0
#
#...
#
dir = (dir+1)%4  # Drehung um +90 Grad
dir = (dir+3)%4  # Drehung im -90 Grad
dir = (dir+2)%4  # Drehung um 180 Grad

Die aktuelle Position wird mit zwei Variablen gespeichert. Die Position kann dann in eine Richtung verschoben werden:

x = 10
y = 32
# Verschiebung in Richtung dir (Zahl von 0 bis 3)
x = x+vecs[dir][0]
y = y+vecs[dir][1]

Lösungsvorschlag

Lösungsvorschlag

spirale.py
from gpanel import *
 
x = 100
y = 100
dir = 0
zahl = 1
 
vecs = [[1,0],[0,1],[-1,0],[0,-1]]
 
makeGPanel(0, 200, 0, 200)
 
 
def isPrime(z):
    for i in range(2,int(z**0.5)+1):
        if z%i==0:
            return False
    return True
 
for l in range(1,200):
    for i in range(2):
        for s in range(l):
            if isPrime(zahl):
                point(x,y)
            x+=vecs[dir][0]
            y+=vecs[dir][1]
            zahl+=1
        dir=(dir+1)%4

Und mehr

Implementieren Sie z.B. so was: http://www.naturalnumbers.org/sparticle.html

Sieb des Eratosthenes.

Idee: Erst wird jede 2. Zahl weggestrichen (ausser die 2), dann jede dritte, jede fünfte, jede siebte, etc. Übrig bleiben die Primzahlen.

Implementation: Array, bzw. Liste von n Wahrheitswerten (True oder False):

eratosthenes.py
import time
start = time.time()
n = 10000
prim = [i>1 for i in range(n+1)]
zwischen = time.time()-start
 
p = 2
while p*p<=n:
    # Vielfache von p wegstreichen:
    x = p*p
    while (x<=n):
        prim[x]=False
        x+=p  # Kurzform fuer i=i+p
    # Naechste Primzahl bestimmen
    p+=1
    while prim[p]==False:  # Schoener: while not prim[p]
        p+=1
 
berechnung = time.time()-start - zwischen
 
# Ausgabe:
for i in range(n+1):
    if prim[i]:
        print(i)
 
print("Initialisierung ",zwischen)        
print("Berechnung ",berechnung)
print("Total ", time.time()-start)

Mehr zu Listen und Arrays: http://www.tigerjython.ch/index.php?inhalt_links=navigation.inc.php&inhalt_mitte=grafik/listen.inc.php

Primzahlen auflisten:

import math
import time
start = time.time()
for i in range(2,500):
    prime = True
    for t in range(2,int(math.sqrt(i))+1):
        if i % t==0:
            prime = False
            break
    if prime:
        print i,
    if i%50==0:
        print
 
print
print(time.time()-start)

Optimierung: Ersetzen Sie range durch xrange. Hintergrund: range erzeugt ein ganzes Array (Feld) von entsprechend vielen Werten im Speicher. xrange ist ein Iterator und erzeugt ein Wert nach dem anderen (konstanter, kleiner Speicherbedarf). Python 3 hat kein xrange, dort funktioniert range wie xrange.

Mögliche Zusatzaufgaben

  • Zeichnen Sie $n$ Kreise, die alle durch einen gegebenen Punkt gehen und deren Zentren gleichmässig auf einem gegebenen Kreis verteilt sind. Die Hüllkurve, die man erhält ist eine der Kardioide verwandte Form (bzw. genau jene, wenn der gegebene Punkt auf dem gegebenen Kreis liegt).
  • Schreiben Sie ein Programm, das nacheinander Primzahlen ausgibt. Hinweis: a % b berechnet der Rest der Division von a durch b und wird a modulo b gelesen. Beispiele: 18 % 5 ergibt 3, 49 % 7 ergibt 0.
  • Freifach freiwillig bereits ab 15:35 (um den ersten Dienstag nachzuholen). Das Zimmer wird offen sein, ich werde aber wohl noch ca. 30 min für eine Sitzung weg sein…

Lektionsziele

  • Freifach freiwillig bereits ab 15:35 (um den ersten Dienstag nachzuholen).

Lektionsziele (mit “obligatorischen” Aufgaben, die aber auch sinngemäss abgwandelt werden können):

Dateien mit Funktionen einbinden

importtest.py
def hello():
    print("Hello world")
 
 
if __name__=="__main__":
    print("Nur wenn diese Datei ausgefuehrt wird")
othertest.py
import importtest
 
importtest.hello()
yetanother.py
import hello from importtest
hello()
  • lehrkraefte/blc/informatik/ffprg1-2018/ffprg1-2018.1526997365.txt.gz
  • Last modified: 2018/05/22 15:56
  • by Ivo Blöchliger