Dies ist mein 2. Posting. Bei einem Problem wurde mir ja schon geholfen, vielen Dank dafür nochmal.
Ich hab mal ne Handelskammer-Ausbildung gemacht als Fachinformatiker (Anwendungsentwicklung). Es war mir bisher jedoch nie vergönnt, als richtiger Programmierer zu arbeiten. Wenn ich mal programmieren durfte, dann höchstens kleinere Scripte zur Automatisierunmg irgendwelcher Listen Transaktionen. Z.B. habe ich - von der oberflächlichen Ausbildung mal abgesehen - null Erfahrung mit OOP und GUI-Programmierung. Ich dachte mir, ich frische meine rudimentären Programmierkenntnisse auf und lerne nebenbei eine neue Sprache (Python). Programmieren tue ich übrigens auf dem Raspberry.
Als erstes Programm habe ich ein kleines Geschicklichkeitsspiel zusammengeschustert. Es ging mir dabei vor allem darum, die elementaren Dinge von Python praktisch zu erproben und das Programmieren mit Fenstern zu erlernen.
Anstatt im nächsten Schritt ein neues Programm anzufangen, habe ich mir gedacht, ich baue den vorhandenen Code komplett um, indem ich ihn in eigene Klassen verpacke. Auch will ich als erstes mal lernen, wie man mit "gutem Stil" programmiert. Das bisher Gemachte könnte vielleicht einen erfahrenen Programmierer zum frösteln bringen. Für Anregungen bin ich natürlich dankbar. Vielleicht knackt ja einer auch meinen Rekord! Hier ist der Code:
Code: Alles auswählen
from tkinter import *
from random import randint
from time import sleep
from _thread import start_new_thread
from pickle import dump
from pickle import load
from os import path
def msg_about():
messagebox.showinfo("Über das Spiel", "Way2slow\n2016")
def msg_hilfe():
messagebox.showinfo("Spielregeln",
"Starte das Spiel mit der Enter-Taste. " \
"Benutze die Pfeiltasten zum Ändern der Nummer. " \
"Mit der Leertaste aktivierst Du die sie. " \
"Stimmt die Nummer mit der ersten Ziffer in dem " \
"schwarzen Display überein, erhälst Du Punkte. " \
"Andernfalls verlierst Du ein Leben. Vermeide, dass " \
"die Ziffern den linken Rand vom Display erreichen!")
def mache_nichts():
if not thread_flag: main.destroy()
def abbrechen():
global thread_flag
thread_flag=False
sleep(1)
def beenden(event=None):
if not thread_flag: main.destroy()
def skin(x):
global erste_farbe, zweite_farbe, dritte_farbe
if x=="grau":
erste_farbe="#D6D7D6"
zweite_farbe="#969696"
dritte_farbe="#3B3838"
if x=="blau":
erste_farbe="#80D1FF"
zweite_farbe="#4973CF"
dritte_farbe="#21345E"
if x=="gruen":
erste_farbe="#85C489"
zweite_farbe="#5F8C62"
dritte_farbe="#2B422B"
if x=="gelb":
erste_farbe="#E3EB88"
zweite_farbe="#ABAD64"
dritte_farbe="#5B5C35"
if x=="rot":
erste_farbe="#FFACAC"
zweite_farbe="#B57A7A"
dritte_farbe="#593C39"
if x=="lila":
erste_farbe="#FF00DB"
zweite_farbe="#7F006D"
dritte_farbe="#45003B"
if x=="bunt":
erste_farbe="#A66AC4"
zweite_farbe="#A87523"
dritte_farbe="#32D13E"
if label_oben_links.cget("text")==0:
label_oben_links.config(fg=erste_farbe, bg=erste_farbe, relief="flat")
label_oben_rechts.config(fg=erste_farbe, bg=erste_farbe, relief="flat")
else:
label_oben_links.config(bg=zweite_farbe)
label_oben_rechts.config(bg=zweite_farbe)
if label_unten_links.cget("text")==10:
label_unten_links.config(fg=erste_farbe, bg=erste_farbe, relief="flat")
label_unten_rechts.config(fg=erste_farbe, bg=erste_farbe, relief="flat")
else:
label_unten_links.config(bg=zweite_farbe)
label_unten_rechts.config(bg=zweite_farbe)
main.config(bg=erste_farbe)
label_mitte_links.config(bg=dritte_farbe)
label_mitte_rechts.config(bg=dritte_farbe)
label_punkte.config(bg=erste_farbe)
label_leben.config(bg=erste_farbe)
rahmen.config(bg=erste_farbe)
label_info.config(bg=erste_farbe)
def relief(x):
global relief_effekt
if x==1: relief_effekt="flat"
if x==2: relief_effekt="raised"
if x==3: relief_effekt="sunken"
if x==4: relief_effekt="groove"
if x==5: relief_effekt="ridge"
if label_oben_links.cget("text")==0:
label_oben_links.config(relief="flat")
label_oben_rechts.config(relief="flat")
else:
label_oben_links.config(relief=relief_effekt, borderwidth=relief_tiefe)
label_oben_rechts.config(relief=relief_effekt, borderwidth=relief_tiefe)
if label_unten_links.cget("text")==10:
label_unten_links.config(relief="flat")
label_unten_rechts.config(relief="flat")
else:
label_unten_links.config(relief=relief_effekt, borderwidth=relief_tiefe)
label_unten_rechts.config(relief=relief_effekt, \
borderwidth=relief_tiefe)
label_mitte_links.config(relief=relief_effekt, borderwidth=relief_tiefe)
label_mitte_rechts.config(relief=relief_effekt, borderwidth=relief_tiefe)
label_laufband.config(relief=relief_effekt, borderwidth=relief_tiefe)
def relief_3d(x):
global relief_tiefe
if x==1: relief_tiefe=1
if x==2: relief_tiefe=2
if x==3: relief_tiefe=3
if x==4: relief_tiefe=4
if x==5: relief_tiefe=5
if x==6: relief_tiefe=6
label_oben_links.config(borderwidth=relief_tiefe)
label_oben_rechts.config(borderwidth=relief_tiefe)
label_mitte_links.config(borderwidth=relief_tiefe)
label_mitte_rechts.config(borderwidth=relief_tiefe)
label_unten_links.config(borderwidth=relief_tiefe)
label_unten_rechts.config(borderwidth=relief_tiefe)
label_laufband.config(borderwidth=relief_tiefe)
def reihe_hoch(event):
if label_mitte_links.cget("text")==2:
label_oben_links.config(text=label_oben_links.cget("text")-1,
fg=erste_farbe, bg=erste_farbe, relief="flat")
label_oben_rechts.config(text=label_oben_rechts.cget("text")-1,
fg=erste_farbe, bg=erste_farbe, relief="flat")
label_mitte_links.config(text=label_mitte_links.cget("text")-1)
label_mitte_rechts.config(text=label_mitte_rechts.cget("text")-1)
label_unten_links.config(text=label_unten_links.cget("text")-1)
label_unten_rechts.config(text=label_unten_rechts.cget("text")-1)
if label_mitte_links.cget("text")>1:
label_oben_links.config(text=label_oben_links.cget("text")-1,
relief=relief_effekt, borderwidth=relief_tiefe)
label_oben_rechts.config(text=label_oben_rechts.cget("text")-1,
relief=relief_effekt, borderwidth=relief_tiefe)
label_mitte_links.config(text=label_mitte_links.cget("text")-1)
label_mitte_rechts.config(text=label_mitte_rechts.cget("text")-1)
label_unten_links.config(text=label_unten_links.cget("text")-1,
fg="White", bg=zweite_farbe, relief=relief_effekt,
borderwidth=relief_tiefe)
label_unten_rechts.config(text=label_unten_rechts.cget("text")-1,
fg="White", bg=zweite_farbe, relief=relief_effekt,
borderwidth=relief_tiefe)
def reihe_runter(event):
if label_mitte_links.cget("text")==8:
label_oben_links.config(text=label_oben_links.cget("text")+1)
label_oben_rechts.config(text=label_oben_rechts.cget("text")+1)
label_mitte_links.config(text=label_mitte_links.cget("text")+1)
label_mitte_rechts.config(text=label_mitte_rechts.cget("text")+1)
label_unten_links.config(text=label_unten_links.cget("text")+1,
fg=erste_farbe, bg=erste_farbe, relief="flat")
label_unten_rechts.config(text=label_unten_rechts.cget("text")+1,
fg=erste_farbe, bg=erste_farbe, relief="flat")
if label_mitte_links.cget("text")<9:
label_oben_links.config(text=label_oben_links.cget("text")+1,
fg="White", bg=zweite_farbe, relief=relief_effekt,
borderwidth=relief_tiefe)
label_oben_rechts.config(text=label_oben_rechts.cget("text")+1,
fg="White", bg=zweite_farbe, relief=relief_effekt,
borderwidth=relief_tiefe)
label_mitte_links.config(text=label_mitte_links.cget("text")+1)
label_mitte_rechts.config(text=label_mitte_rechts.cget("text")+1)
label_unten_links.config(text=label_unten_links.cget("text")+1,
relief=relief_effekt, borderwidth=relief_tiefe)
label_unten_rechts.config(text=label_unten_rechts.cget("text")+1,
relief=relief_effekt, borderwidth=relief_tiefe)
# Treffer ermitteln:
def treffer(event):
global leben, punkte
if laufband: # Wenn die Liste nicht leer ist, sonst Index-Fehler!
if label_mitte_links.cget("text")==laufband[0]:
laufband.pop(0)
punkte+=level**2
label_punkte.config(text="Punkte: "+str(format(punkte, ',d')))
if len(laufband)<5:
label_laufband.config(text=laufband, anchor=E, fg="White")
elif len(laufband)>4 and len(laufband)<8:
label_laufband.config(text=laufband, anchor=E, fg="Yellow")
else:
label_laufband.config(text=laufband, anchor=E, fg="#FF6A00")
else:
label_laufband.config(text="Autsch !!!", fg="Red", anchor=CENTER)
if leben>0:
leben-=1
label_leben.config(text="noch {} Leben".format(leben))
# Für das Laufband. Läuft im eigenen Thread:
def spiel():
global thread_flag, leben, punkte, level
thread_flag=True
leben=3
level=1
sleep_counter=1.3
main.unbind("<Return>")
label_laufband.config(text="Los geht's ... ", fg="White", anchor=E)
label_leben.config(text="noch {} Leben".format(leben), fg="Black")
label_punkte.config(text="Punkte: 0")
while (len(laufband)<10) and thread_flag and leben>0:
if level <3: skin("grau")
if level >2 and level <5: skin("blau")
if level >4 and level <7: skin("gruen")
if level >6 and level <9: skin("gelb")
if level >8 and level <11: skin("rot")
if level >10 and level <13: skin("lila")
if level >12 and level <15: skin("bunt")
for i in range(10):
if (len(laufband)<10) and thread_flag and leben>0:
sleep(sleep_counter)
laufband.append(randint(1, 9))
if len(laufband)<5:
label_laufband.config(text=laufband, fg="White", anchor=E)
elif len(laufband)>4 and len(laufband)<8:
label_laufband.config(text=laufband, fg="Yellow", anchor=E)
else:
label_laufband.config(text=laufband, fg="#FF6A00", anchor=E)
sleep_counter-=0.05
level+=1
label_laufband.config(text="GAME OVER", fg="Red", anchor=CENTER)
try: d=open("highscore.txt", "rb")
except:
messagebox.showinfo("Zugriffsfehler", \
"Highscore-Datei Zugriff nicht erfolgreich")
return
try: highscore_liste=load(d)
except EOFError:
d.close()
return
d.close()
# Zweidimensionale Liste sortieren
highscore_liste=sorted(highscore_liste,key=lambda l:l[1], reverse=True)
if punkte>highscore_liste[-1][1]:
speichere_highscore(highscore_liste)
#Aufräumen für's nächste Spiel:
laufband.clear()
leben=3
punkte=0
main.bind("<Return>", start)
thread_flag=False
def speichere_highscore(highscore_liste):
def ende(event=None):
highscore_liste[-1][0]=entry_name.get()
try: d=open("highscore.txt", "wb")
except:
messagebox.showinfo("Zugriffsfehler", \
"Highscore-Datei Zugriff nicht erfolgreich")
return
dump(highscore_liste, d)
d.close()
# toplevel_speichern.grab_release() überflüssig
toplevel_speichern.destroy()
zeige_highscore()
toplevel_speichern = Toplevel(main)
toplevel_speichern.grab_set()
toplevel_speichern.title("Name")
toplevel_speichern.resizable(width = 0, height = 0)
toplevel_speichern.bind("<Return>", ende)
Label(toplevel_speichern, text= \
"Du bist in der Top-Ten-Liste!\nDein Name:").grid(row=0, column=0)
entry_name=Entry(toplevel_speichern)
entry_name.focus_set()
entry_name.grid(row=1, column=0)
Button(toplevel_speichern, text="Ok", command=ende).grid(row=2, column=0)
highscore_liste[-1][1]=punkte
def zeige_highscore():
def string_highscore(l):
x=""
for i in range(len(l)):
if i>8: x+="Platz "+str(i+1)+": "+l[i][0]+ \
" ("+str(format(l[i][1], ',d'))+")\n"
else: x+="Platz "+str(i+1)+": "+l[i][0]+ \
" ("+str(format(l[i][1], ',d'))+")\n"
return(x)
try: d=open("highscore.txt", "rb")
except:
messagebox.showinfo("Zugriffsfehler", "Dateizugriff nicht erfolgreich")
return
try: highscore_liste=load(d)
except EOFError:
messagebox.showinfo("Highscores", "Noch keine Highscores vorhanden!")
d.close()
return
d.close()
# Zweidimensionale Liste sortieren
highscore_liste=sorted(highscore_liste,key=lambda l:l[1], reverse=True)
messagebox.showinfo("Highscores", string_highscore(highscore_liste))
def resette_highscores():
try: d=open("highscore.txt", "wb")
except:
messagebox.showinfo("Zugriffsfehler", "Dateizugriff nicht erfolgreich")
return
highscore_liste=["Jan", 9810],["Jan", 9279],["Jan", 7231],["Jan", 6501], \
["Jan", 5951],["Jan", 4825],["Jan", 4166],["Jan", 3671], \
["Jan", 3215],["Jan", 2335]
dump(highscore_liste, d)
d.close()
def start(event):
start_new_thread(spiel,())
# Initialisierung:
laufband=[]
thread_flag=False # True = Nebenthread läuft
leben=3
punkte=0
level=1
erste_farbe="#D6D7D6"
zweite_farbe="#969696"
dritte_farbe="#3B3838"
relief_effekt="groove"
relief_tiefe=2
# Toplevel Widget (Main Window):
main=Tk()
main.protocol('WM_DELETE_WINDOW', mache_nichts)
main.wm_title("Zahlenlaufband")
main.resizable(width=0, height=0)
main.configure(background=erste_farbe)
# Menü:
menubar = Menu(main)
menu_datei = Menu(menubar)
menu_datei.config(tearoff=0)
menu_datei.add_command(label="Zeige Highscores", command=zeige_highscore)
menu_datei.add_command(label="Setze Highscores zurück", \
command=resette_highscores)
menu_datei.add_command(label="Beenden", command=beenden)
menubar.add_cascade(label="Datei", menu=menu_datei)
menu_relief = Menu(menubar)
menu_relief.config(tearoff=0)
menu_relief.add_command(label="Flat", command=lambda: relief(1))
menu_relief.add_command(label="Raised", command=lambda: relief(2))
menu_relief.add_command(label="Sunken", command=lambda: relief(3))
menu_relief.add_command(label="Groove", command=lambda: relief(4))
menu_relief.add_command(label="Ridge", command=lambda: relief(5))
menubar.add_cascade(label="Relief-Stil", menu=menu_relief)
menu_relief_3d = Menu(menubar)
menu_relief_3d.config(tearoff=0)
menu_relief_3d.add_command(label="Relief-Tiefe 1",command=lambda: relief_3d(1))
menu_relief_3d.add_command(label="Relief-Tiefe 2",command=lambda: relief_3d(2))
menu_relief_3d.add_command(label="Relief-Tiefe 3",command=lambda: relief_3d(3))
menu_relief_3d.add_command(label="Relief-Tiefe 4",command=lambda: relief_3d(4))
menu_relief_3d.add_command(label="Relief-Tiefe 5",command=lambda: relief_3d(5))
menu_relief_3d.add_command(label="Relief-Tiefe 6",command=lambda: relief_3d(6))
menubar.add_cascade(label="Relief-Tiefe", menu=menu_relief_3d)
menu_hilfe = Menu(menubar)
menu_hilfe.config(tearoff=0)
menu_hilfe.add_command(label="Spielregeln", command=msg_hilfe)
menu_hilfe.add_command(label="Über das Spiel", command=msg_about)
menubar.add_cascade(label="Hilfe", menu=menu_hilfe)
main.config(menu=menubar)
# Row 0:
label_oben_links=Label(main, text=4, width=3, fg="White", relief=relief_effekt,
borderwidth=relief_tiefe, bg=zweite_farbe, font=("Arial 20"))
label_oben_links.grid(row=0, column=0)
label_punkte=Label(main, bg=erste_farbe, font=("Arial 20"))
label_punkte.grid(row=0, column=1, pady=7)
label_oben_rechts=Label(main, text=4, width=3, fg="White", relief=relief_effekt,
borderwidth=relief_tiefe, bg=zweite_farbe, font=("Arial 20"))
label_oben_rechts.grid(row=0, column=2)
# Row 1:
label_mitte_links=Label(main, text=5, width=3, relief=relief_effekt,
borderwidth=relief_tiefe, fg="White", bg=dritte_farbe,
font=("Arial 30 bold"))
label_mitte_links.grid(row=1, column=0, padx=7)
label_laufband=Label(main, width=13, text="Drücke <Enter>", fg="White",
bg="Black", font=("Arial 22"), relief=relief_effekt,
borderwidth=relief_tiefe)
label_laufband.grid(row=1, column=1)
label_mitte_rechts=Label(main, text=5, width=3, relief=relief_effekt,
borderwidth=relief_tiefe, fg="White", bg=dritte_farbe,
font=("Arial 30 bold"))
label_mitte_rechts.grid(row=1, column=2, padx=7)
#Row 2:
label_unten_links=Label(main, text=6, width=3, relief=relief_effekt,
borderwidth=relief_tiefe, fg="White", bg=zweite_farbe, font=("Arial 20"))
label_unten_links.grid(row=2, column=0)
label_leben=Label(main, bg=erste_farbe, font=("Arial 20"))
label_leben.grid(row=2, column=1, pady=7)
label_unten_rechts=Label(main, text=6, width=3, relief=relief_effekt,
borderwidth=relief_tiefe, fg="White", bg=zweite_farbe, font=("Arial 20"))
label_unten_rechts.grid(row=2, column=2)
# Row 3 (Buttons):
rahmen=Frame(main, bg=erste_farbe)
rahmen.grid(row=3, column=1)
Button(rahmen, text="Abbruch", command=abbrechen).grid(row=0, column=0,
padx=7, pady=7)
Button(rahmen, text="Ende", command=beenden).grid(row=0, column=1,
padx=7, pady=7)
# Row 4 (Info-Label):
label_info=Label(main, text="Benutze <Enter>, <Pfeile> und <Leer> zum Spielen",
bg=erste_farbe)
label_info.grid(row=4, column=0, columnspan=3)
# Key Bindings:
main.bind("<KeyPress-Up>", reihe_hoch)
main.bind("<KeyPress-Down>", reihe_runter)
main.bind("w", reihe_hoch)
main.bind("s", reihe_runter)
main.bind("<space>", treffer)
main.bind("<Control_L>", treffer)
main.bind("<Control_R>", treffer)
main.bind("<Return>", start)
main.bind("<Tab>", DISABLED)
main.bind("<Escape>", beenden)
# Prüfen, ob Highscore-Datei existiert:
if not path.isfile("highscore.txt"):
resette_highscores()
main.mainloop()