- zahlenraten.rb
from random import randint
debug = True
mini = 0
maxi = 100
zahl = randint(mini, maxi)
if debug:
print(zahl)
versuche = 1
while True:
msg = "Anzahl Versuche %d\nBereich: %d bis %d" % (versuche, mini, maxi)
tip = inputInt(msg)
if zahl < tip:
maxi = tip
elif zahl > tip:
mini = tip
else:
msgDlg("Super! %d Versuche" % (versuche))
break
versuche+=1
Snake
Implementation Bestimmung des kürzesten Wegs. Statische Variante.
Vorgehen:
Doppeltes Array mit -1 initialisieren für Distanzen (für jedes feld[x][y]). -1 heisst dann unerreichbares Feld
Todo-Liste: Array mit Koordinatenpaaren.
Apfel-Feld mit 0 initialisieren, Apfel-Koordinaten in Todo-Liste speichern:
Solange Todo-Liste nicht leer ist:
Koordinatenpaar vorne von Todo-Liste entfernen → p.
Nachbarn von p “abklappern”, nötigenfalls Distanzen eintragen, nötigenfalls Nachbar hinten an TODO-Liste anhängen.
Richtungsauswahl:
Wenn ein Nachbarfeld vom Schlangenkopf mit Distanz >= 0 existiert, zum Feld mit kleinstmöglicher Distanz gehen.
Sonst sich eine Überlebensstrategie ausdenken.
Variante: Vom Schlangenkopf aus die Distanzen bestimmen. Der kürzeste Weg zum Apfel muss dann allerdings von dort rückwärts gesucht werden. Dafür können dann Felder miteinbezogen werden, die wieder verschwinden.
Dienstag 5. 6. 2018
Dienstag 29. 5. 2018
Ziele:
Strategie mit Skalarprodukt von der letzten Stunde verstehen.
Zusatzfunktion erstellen, die die Möglichkeit einer Kopf-an-Kopf-Kollision erkennt und diese Richtung(en) vermeidet.
Weitere Verbesserungen, wie z.B. kürzeste Wege zum Apfel berechnen.
def kopfankopfok(self, a,b):
x,y = self.params.x, self.params.y
for schlange in self.params.heads:
# schlange ist hier ein Array mit 2 Einträgen
if abs(x-schlange[0])+abs(y-schlange[1])>0: # nicht eigene
if abs(a-schlange[0])+abs(b-schlange[1])==1: #dist 1
return False # Achtung Gefahr
return True # Keine Gefahr
Dienstag 22. 5. 2018
Ziel: Beispielstrategie für Snake kopieren und verbessern, dass die Äpfel direkt gefressen werden, zumindest, wenn sich der Schlangenkopf auf der gleichen $x$ oder $y$-Koordinate wie der Apfel befindet.
Variante: Sei $P$ die Position der Schlange, $A$ die position des Kopfs und $\vec{v}_0$ bis $\vec{v}_3$ die 4 Richtungsvektoren. Das Skalarprodukt zwischen dem Vektor $\vec{PA}$ und einem Richtungsvektor ist dann positiv, wenn sich die Schlange so dem Apfel nähert.
Es gilt $\vec{u} \cdot \vec{v} = |\vec{u}| \cdot |\vec{v}| \cdot \cos(\alpha)$ mit $\alpha = \angle(\vec{u}, \vec{v})$ aber auch $\vec{u} \cdot \vec{v} = u_x \cdot v_x + u_y\cdot v_y$. Das lässt sich auch auf 3 und mehr Dimensionen verallgemeinern.
# Aktuelle Position ermitteln
x,y = self.params.x, self.params.y
# print("(x,y)=(%d,%d) d=%d" % (x,y,d))
# Koordinaten vom Apfel
apfx = self.params.apple[0]
apfy = self.params.apple[1]
# Richtungsvektoren durchlaufen
for i in range(4):
# Prüfen, ob nicht Gegenrichtung von d, egal, ist eh besetzt
# Komponenten vom Richtungsvektor
vx = Board.VECS[i][0]
vy = Board.VECS[i][1]
# Skalarprodukt berechnen, wenn positiv und moeglich, dann machen.
s = vx*(apfx-x)+vy*(apfy-y)
# Neue Position
a,b = Board.move(x,y,i)
if s>0 and (self.params.feld[a][b]==Board.EMPTY or self.params.feld[a][b]==Board.APPLE):
return i
Dienstag 8. 5. 2018
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)
Dienstag 8. 5. 2018
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]
- 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
Dienstag 24. 4. 2018
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
Dienstag 3. 4. 2018
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.
Dienstag 27. 3. 2018
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.
Dienstag 5. 3. 2018
Dienstag 27. 2. 2018
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()