Kann man so etwas wie Karol auch in Python programmieren? Bestimmt! Wenn man genug Zeit dazu hat...
Aber man kann ja zumindest mal damit anfangen und dieses Projekt nutzen, um Python zu lernen! Wer möchte, darf sich gerne beteiligen!
===== Version 0.0.1 =====
Es gibt eine Klasse "Welt" und eine Klasse "Roboter". Der Roboter kann sich in der Welt bewegen und Ziegel hinlegen. Die Anzahl der Ziegel kann auch direkt festgelegt werden.
class Welt(object):
# Konstruktor
def __init__(self,laenge=10,breite=10,hoehe=10):
self.Laenge = laenge
self.Breite = breite
self.Hoehe = hoehe
# eine zweidimensionale Liste anlegen und mit Nullen füllen
self.Ziegel = []
for j in range(laenge):
reihe = []
for i in range(breite):
reihe.append(0)
self.Ziegel.append(reihe)
# Anzahl der Ziegel an einer bestimmten Position direkt eingeben
def setZiegel(self,x,y,anzahl):
self.Ziegel[x][y] = anzahl
# Anzahl der Ziegel an einer bestimmten Position um 1 erhöhen
def hinlegenZiegel(self,x,y):
self.Ziegel[x][y] += 1
class Roboter(object):
# Konstruktor
def __init__(self,welt,posx=0,posy=0,richtung=1):
self.Welt = welt # Richtungen: +1
self.Posx = posx # -2 +2
self.Posy = posy # -1
self.Richtung = richtung
# ein Feld nach vorne gehen
def schritt(self):
self.Posx += self.Richtung / 2
self.Posy += self.Richtung % 2
# nach rechts drehen
def rechtsDrehen(self):
if self.Richtung == 1:
self.Richtung = 2
elif self.Richtung == 2:
self.Richtung = -1
elif self.Richtung == -1:
self.Richtung = -2
else:
self.Richtung = 1
# nach links drehen
def linksDrehen(self):
self.rechtsDrehen()
self.Richtung *= -1
# einen Ziegel vor den Roboter legen
def hinlegen(self):
ziegelposx = self.Posx + self.Richtung / 2
ziegelposy = self.Posy + self.Richtung % 2
self.Welt.hinlegenZiegel(ziegelposx,ziegelposy)
Die Ausgabe erfolgt zunächst über die Kommandozeile mit diesen Prozeduren:
from RobbiDaten import *
def weltausgeben(welt):
print "Länge: ",welt.Laenge
print "Breite:",welt.Breite
print "Höhe: ",welt.Hoehe
for j in range(welt.Laenge-1,-1,-1):
for i in range(welt.Breite):
print welt.Ziegel[i][j],
print
def roboterausgeben(roboter):
print "Koordinaten:",roboter.Posx, roboter.Posy
print "Richtung: ",roboter.Richtung
def allesausgeben(welt,roboter):
print "Länge: ",welt.Laenge
print "Breite:",welt.Breite
print "Höhe: ",welt.Hoehe
for j in range(welt.Laenge-1,-1,-1):
for i in range(welt.Breite):
if roboter.Posx == i and roboter.Posy == j:
print "X",
else:
print welt.Ziegel[i][j],
print
Testen von der Python-Shell aus:
>>> w=Welt()
>>> r=Roboter(w)
>>> r.hinlegen();r.schritt()
>>> r.hinlegen();r.schritt()
>>> r.hinlegen();r.schritt()
>>> r.rechtsDrehen()
>>> r.hinlegen();r.schritt()
>>> r.hinlegen();r.schritt()
>>> r.schritt()
>>> allesausgeben(w,r)
Länge: 10
Breite: 10
Höhe: 10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 1 1 X 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Es fehlt eine Überprüfung, ob der Roboter am Rand der Welt angelangt ist sowie die Roboter-Methode "aufheben".
===== Version 0.1.0 =====
Die oben fehlende Überprüfung ist eingefügt: Der Roboter kennt nun seine Welt und kann vor jeder Aktion überprüfen, ob er sie durchführen kann. Die Koordinaten des Roboters wurden geändert und die Richtung des Roboters ist nun ein 2-dimensionaler Vektor.
Eine große Änderung besteht in der Bedienung durch eine grafische Benutzeroberfläche. Diese wurde mit dem Modul Tkinter geschrieben.
Darüber hinaus lässt sich der Roboter mit folgenden Befehlen programmieren:
* schritt
* rechtsdrehen
* linksdrehen
* hinlegen
* aufheben
* wiederhole n mal \\ ... \\ *wiederhole
Das Robbie-Programm kann gespeichert und wieder geladen werden.
So sieht das Programm bisher aus:
{{ informatik-buch:programmiersprachen:python:beispiele:bild_2.png }}
class Welt(object):
# Konstruktor
def __init__(self,laenge=10,breite=10,hoehe=10):
self.Laenge = laenge
self.Breite = breite
self.Hoehe = hoehe
# eine zweidimensionale Liste anlegen und mit Nullen füllen
self.Ziegel = [[0 for i in range(breite)] for j in range(laenge)]
# Anzahl der Ziegel an einer bestimmten Position direkt eingeben
def setZiegel(self,x,y,anzahl):
self.Ziegel[x][y] = anzahl
# Anzahl der Ziegel an einer bestimmten Position um 1 erhöhen
def hinlegenZiegel(self,x,y):
if self.Ziegel[x][y] < self.Hoehe:
self.Ziegel[x][y] += 1
# Anzahl der Ziegel an einer bestimmten Position um 1 erniedrigen
def aufhebenZiegel(self,x,y):
if self.Ziegel[x][y] > 0:
self.Ziegel[x][y] -= 1
class Roboter(object):
# Konstruktor
def __init__(self,welt,posx=0,posy=0,richtung=[1,0]):
self.Welt = welt
self.Posx = posx
self.Posy = posy
self.Richtung = richtung
# ein Feld nach vorne gehen, falls möglich
def schritt(self):
self.Posx += self.Richtung[0]
if self.Posx < 0: self.Posx = 0
if self.Posx > self.Welt.Laenge - 1:
self.Posx = self.Welt.Laenge - 1
self.Posy += self.Richtung[1]
if self.Posy < 0: self.Posy = 0
if self.Posy > self.Welt.Breite - 1:
self.Posy = self.Welt.Breite - 1
# nach rechts drehen
def rechtsDrehen(self):
if self.Richtung == [1,0]:
self.Richtung = [0,1]
elif self.Richtung == [0,1]:
self.Richtung = [-1,0]
elif self.Richtung == [-1,0]:
self.Richtung = [0,-1]
else:
self.Richtung = [1,0]
# nach links drehen
def linksDrehen(self):
if self.Richtung == [1,0]:
self.Richtung = [0,-1]
elif self.Richtung == [0,1]:
self.Richtung = [1,0]
elif self.Richtung == [-1,0]:
self.Richtung = [0,1]
else:
self.Richtung = [-1,0]
# einen Ziegel vor den Roboter legen falls möglich
def hinlegen(self):
ziegelposx = self.Posx + self.Richtung[0]
ziegelposy = self.Posy + self.Richtung[1]
if 0 <= ziegelposx < self.Welt.Laenge and 0<= ziegelposy < self.Welt.Breite:
self.Welt.hinlegenZiegel(ziegelposx,ziegelposy)
return True
else:
return False
# einen Ziegel vor dem Roboter aufheben falls möglich
def aufheben(self):
ziegelposx = self.Posx + self.Richtung[0]
ziegelposy = self.Posy + self.Richtung[1]
if 0 <= ziegelposx < self.Welt.Laenge and 0<= ziegelposy < self.Welt.Breite:
self.Welt.aufhebenZiegel(ziegelposx,ziegelposy)
return True
else:
return False
Dies war der Daten-Teil. Jetzt folgt die GUI. Was noch überhaupt nicht schön ist: der Robbi-Interpreter steht noch in der GUI, wo er eigentlich nicht hingehört.
from RobbiDaten import *
#from RobbiShell import *
#from RobbiInter import *
#from tkFileDialog import askopenfilename
from Tkinter import *
import tkFileDialog
#from tkMessageBox import *
#from tkColorChooser import askcolor
class GUI:
def __init__(self,roboter):
# Daten-Objekte
self.Roboter = roboter
self.Ziegel = [[0 for i in range(10)] for j in range(10)]
# GUI-Objekte definieren
self.fenster = Tk()
self.fenster.title("Robbi Roboter")
self.frame1 = Frame(master=self.fenster)
self.frame2 = Frame(master=self.fenster)
self.welt2d = Canvas(master=self.frame1, width=511, height=511, bg="white")
self.eingabe = Text(master=self.frame1, width=40, height=36, bg = "#f0f0f0")
self.buttonQuit = Button(master=self.frame2, text="Quit", command=self.fenster.quit)
self.buttonNeueWelt = Button(master=self.frame2, text="Neue Welt", command=self.welt2dzeichnen)
self.buttonSchritt = Button(master=self.frame2, text="Schritt", command=self.schritt)
self.buttonLinks = Button(master=self.frame2, text="Linksdrehen", command=self.linksdrehen)
self.buttonRechts = Button(master=self.frame2, text="Rechtsdrehen", command=self.rechtsdrehen)
self.buttonHinlegen = Button(master=self.frame2, text="Hinlegen", command=self.hinlegen)
self.buttonAufheben = Button(master=self.frame2, text="Aufheben", command=self.aufheben)
self.buttonAusfuehren = Button(master=self.frame1, text ="Ausführen", command=self.ausfuehrenclick)
self.buttonLaden = Button(master=self.frame1, text ="Laden", command=self.laden)
self.buttonSpeichern = Button(master=self.frame1, text ="Speichern", command=self.speichern)
# GUI-Objekte anordnen
self.frame1.pack()
self.frame2.pack()
self.welt2d.pack(expand=YES, fill=BOTH, side=LEFT)
self.eingabe.pack(side=TOP)
self.buttonNeueWelt.pack(side=RIGHT)
self.buttonQuit.pack(side=LEFT)
self.buttonSchritt.pack(side=LEFT)
self.buttonLinks.pack(side=LEFT)
self.buttonRechts.pack(side=LEFT)
self.buttonHinlegen.pack(side=LEFT)
self.buttonAufheben.pack(side=LEFT)
self.buttonAusfuehren.pack(side=LEFT)
self.buttonLaden.pack(side=LEFT)
self.buttonSpeichern.pack(side=LEFT)
# Gitter zeichnen
def welt2dzeichnen(self):
self.welt2d.create_rectangle(10,10,510,510)
for i in range(10,510,50):
self.welt2d.create_line(10,i,510,i)
for i in range(10,510,50):
self.welt2d.create_line(i,10,i,510)
# Alle Ziegel zeichnen (Zahl oder leerer String)
def ziegelzeichnen(self):
for j in range(10):
for i in range(10):
te=str(self.Roboter.Welt.Ziegel[i][j])
if te =="0":te=""
self.Ziegel[i][j]=self.welt2d.create_text(i*50+35,j*50+35,text=te)
# Roboter (Dreieck) zeichnen)
def roboterzeichnen(self):
robx = 50*self.Roboter.Posx + 35
roby = 50*self.Roboter.Posy + 35
if self.Roboter.Richtung == [0,1]:
self.dreieck=self.welt2d.create_polygon(robx-25,roby-25,robx+25,roby-25,robx,roby+25)
elif self.Roboter.Richtung == [0,-1]:
self.dreieck=self.welt2d.create_polygon(robx-25,roby+25,robx+25,roby+25,robx,roby-25)
elif self.Roboter.Richtung == [1,0]:
self.dreieck=self.welt2d.create_polygon(robx-25,roby-25,robx-25,roby+25,robx+25,roby)
elif self.Roboter.Richtung == [-1,0]:
self.dreieck=self.welt2d.create_polygon(robx+25,roby+25,robx+25,roby-25,robx-25,roby)
# Roboter bewegen und neu zeichnen
def schritt(self):
self.welt2d.delete(self.dreieck)
self.Roboter.schritt()
self.roboterzeichnen()
# Roboter nach links drehen und neu zeichnen
def linksdrehen(self):
self.welt2d.delete(self.dreieck)
self.Roboter.linksDrehen()
self.roboterzeichnen()
# Roboter nach links drehen und neu zeichnen
def rechtsdrehen(self):
self.welt2d.delete(self.dreieck)
self.Roboter.rechtsDrehen()
self.roboterzeichnen()
# Ziegel hinlegen und veränderten Ziegel neu zeichnen
def hinlegen(self):
if self.Roboter.hinlegen():
neuziegelx = self.Roboter.Posx + self.Roboter.Richtung[0]
neuziegely = self.Roboter.Posy + self.Roboter.Richtung[1]
te=str(self.Roboter.Welt.Ziegel[neuziegelx][neuziegely])
if te =="0":te=""
self.welt2d.itemconfig(self.Ziegel[neuziegelx][neuziegely],text=te)
# Ziegel aufheben und veränderten Ziegel neu zeichnen
def aufheben(self):
if self.Roboter.aufheben():
neuziegelx = self.Roboter.Posx + self.Roboter.Richtung[0]
neuziegely = self.Roboter.Posy + self.Roboter.Richtung[1]
te=str(self.Roboter.Welt.Ziegel[neuziegelx][neuziegely])
if te =="0":te=""
self.welt2d.itemconfig(self.Ziegel[neuziegelx][neuziegely],text=te)
def ausfuehrenclick(self):
eingabe = self.eingabe.get("1.0",END)
programm = eingabe.split()
for i in range(len(programm)):
if programm[i] == "wiederhole": programm[i] = "w"
elif programm[i] == "*wiederhole": programm[i] = "*w"
elif programm[i] == "schritt": programm[i] = "s"
elif programm[i] == "rechtsdrehen": programm[i] = "r"
elif programm[i] == "linksdrehen": programm[i] = "l"
elif programm[i] == "aufheben": programm[i] = "a"
elif programm[i] == "hinlegen": programm[i] = "h"
self.ausfuehren(programm)
def ausfuehren(self,liste):
print liste
merke = [0,0,0,0]
schleifenzaehler = [0,0,0,0]
schleife = -1
i = 0
while i < len(liste):
if liste[i] == "w":
schleife += 1
i += 1
schleifenzaehler[schleife] = int(liste[i])
merke[schleife]=(i+1)
elif liste[i] == "*w":
if schleifenzaehler[schleife] > 1:
schleifenzaehler[schleife] -= 1
i = merke[schleife] - 1
else:
schleife -=1
elif liste[i] == "s":
self.schritt()
elif liste[i] == "r":
self.rechtsdrehen()
elif liste[i] == "l":
self.linksdrehen()
elif liste[i] == "h":
self.hinlegen()
elif liste[i] == "a":
self.aufheben()
i += 1
def laden(self):
filename = tkFileDialog.askopenfilename()
programmdatei = open(filename,"r")
self.eingabe.delete("1.0",END)
for zeile in programmdatei:
self.eingabe.insert(END,zeile)
programmdatei.close()
def speichern(self):
filename = tkFileDialog.asksaveasfilename()
programmdatei = open(filename,"w")
programmdatei.write(self.eingabe.get("1.0",END))
programmdatei.close()
w=Welt() # Welt der Größe 10x10
r=Roboter(w) # Roboter in dieser Welt
gui = GUI(r) # Grafische Oberfläche initialisieren
gui.roboterzeichnen() # Den Roboter einzeichnen
gui.ziegelzeichnen() # Die Ziegel einzeichnen
gui.welt2dzeichnen() # Das Gitter zeichnen
gui.fenster.mainloop() # Auf Buttonklick warten