Ich habe die folgenden 3 Python Quellcodes selbst programmiert, die zusammen das Computerspiel Moorhuhn wiederspiegeln (am Anfang und am Ende mit einigermaßen lustigen Elementen). Insgesamt fehlen (laut Aussage eines Programmierexperten, nicht meine Aussage) die folgenden 4 Elemente:
(1)Vererbung
(2)Polymorphie (ich weiß die gibt es in Python nicht), aber es soll(te) zumindestens die Python´sche Private-Konvention realisiert werden.
(3)Datenkapselung
(4)Schnittstellen
Alles Aussagen eines Programmierers, nicht meine (ich habe nur den Code geschrieben).
Meine Frage/Bitte: An welchen Stellen eignet es sich am besten diese 4 Punkte zu realisieren?
Code: Alles auswählen
from turtle import Screen, Turtle import random, time, pygame, winsound, json, os from pygame import mixer from moorhuhn_2 import Level try: import winsound #Sound Wiedergabe Schnittstelle, bietet Zugriff auf die grundlegende Sound- Spielmaschinerie _SOUND = True except: _SOUND = False print("KEIN TON!") SCHÜSSE = 20 GESCHWINDIGKEIT = Level/10 BREITE, HÖHE = 1280, 750 TREFFER = "getroffen.wav" DANEBEN = "daneben.wav" GUT = "gameover.wav" APPLAUS = "applaus.wav" pygame.init() # Sound mixer.music.load("hintergrundmusik.wav") #lädt nur die Hintergrundmusik mixer.music.play(-1) #spielt tatsächlich die Hintergrundmusik ab; "-1" heißt: theoretisch endlos class Bildmanager(Turtle): #Konfiguration des Bildes def __init__(self, breite, höhe): #Spezielle Turtle, hat die Aufgabe die Moorhuhn-GUI zu kontrollieren Turtle.__init__(self, visible=False) self.screen = Screen() self.screen.setup(breite, höhe) self.speed(0) self.penup() self.goto(-BREITE//2 + 50, #die '+50' bewirken, daß die Schrift etwas ins Bild hineinkommt -HÖHE//2 + 20) #die '+20' bewirken, daß die Schrift etwas ins Bild hineinkommt self.pencolor("yellow") #Schriftfarbe def schrift(self, txt): #Output Text im Graphik Fenster self.clear() self.write(txt, font=("Arial", 18, "bold")) class Huhn(Turtle): def __init__(self, bilddatei, moorhuhnspiel): Turtle.__init__(self, shape=bilddatei) self.spiel = moorhuhnspiel self.penup() self.speed(0) self.onclick(self.getroffen) #wenn auf das Huhn draufgeklickt wurde, gilt es als 'getroffen' self.start_links() self.start_rechts() def start_links(self): self.hideturtle() #zuerst sind die Hühner noch nicht da..... self.setpos(-BREITE//2-20, #das ist der Bereich, von wo aus die Hühner starten; '-20' bewirkt, daß sie etwas außerhalb vom Bild starten random.randint(-HÖHE//3, HÖHE//3)) self.vx = random.randint(6,11) * GESCHWINDIGKEIT #'vx' ist die Geschwindigkeit in X-Richtung self.vy = random.randint(-3,3) * GESCHWINDIGKEIT #'vy' ist die Geschwindigkeit in Y-Richtung self.getroffen = False self.tot = False self.ausdemspiel_links = False self.showturtle() #.....jetzt sind die Hühner da def schritt_links_rechts(self): global Strafpunkt_links_rechts #die Strafpunkte beziehen sich auf nicht abgeschossene und damit entkommene Hühner Strafpunkt_links_rechts=1 #Strafpunkt=1, weil wenn Strafpunkt=0 und alle Hühner abgeschossen würden und kein Huhn entkommt, unten durch 0 geteilt werden müßte. So wird durch 1 geteilt. if self.ausdemspiel_links: time.sleep(0.01) return if self.tot: self.vy = self.vy - 0.5 * GESCHWINDIGKEIT #hier fällt das angeschossene Huhn runter x, y = self.position() x = x + self.vx #hier die X-Koordinate des herunterfallenden Huhns y = y + self.vy #hier die Y-Koordinate des herunterfallenden Huhns. Bei 'self.vy**2' fallen die Hühner nach oben :P self.goto(x,y) if x > BREITE//2 + 20 or abs(y) > HÖHE//2 + 10: #die '+20' bzw. die '+10' sorgen dafür, daß die Hühner immer etwas weiterfliegen als die Bildgröße=>Hühner sind aus dem Bild raus Strafpunkt_links_rechts=Strafpunkt_links_rechts+1 #pro entkommenes (=nicht abgeschossenes) Huhn gibt es 1 Strafpunkt if self.spiel.schuss != SCHÜSSE: self.start_links() else: #dieser Abschnitt sorgt dafür, daß die Hühner bei Spielende nicht weiterfliegen self.ausdemspiel_links = True ############################################################# def start_rechts(self): # self.hideturtle() #zuerst sind die Hühner noch nicht da..... self.setpos(BREITE//2+20, #das ist der Bereich, von wo aus die Hühner starten random.randint(-HÖHE//3, # HÖHE//3)) # self.vx = random.randint(6,11) * GESCHWINDIGKEIT #'vx' ist die Geschwindigkeit in X-Richtung self.vy = random.randint(-3,3) * GESCHWINDIGKEIT #'vy' ist die Geschwindigkeit in Y-Richtung self.getroffen = False # self.tot = False # self.ausdemspiel_rechts = False # self.showturtle() # # def schritt_rechts_links(self): # global Strafpunkt_rechts_links # Strafpunkt_rechts_links=1 # if self.ausdemspiel_rechts: # time.sleep(0.01) # return # if self.tot: # self.vy = self.vy + 0.5 * GESCHWINDIGKEIT #hier fällt das angeschossene Huhn runter x, y = self.position() # x = x - self.vx #hier die X-Koordinate des herunterfallenden Huhns y = y - self.vy #hier die Y-Koordinate des herunterfallenden Huhns self.goto(x,y) # if x < -BREITE//2 - 20 or abs(y) > HÖHE//2 + 10: # Strafpunkt_rechts_links=Strafpunkt_rechts_links+1 # if self.spiel.schuss != SCHÜSSE: # self.start_rechts() # else: # self.ausdemspiel_rechts = True # ############################################################# def getroffen(self, x, y): if self.tot or self.spiel.schuss==SCHÜSSE: #"self.spiel.schuss==SCHÜSSE" bedeutet game over return self.tot = True self.getroffen = True self.spiel.score = self.spiel.score+1 class MoorhuhnSpiel(object): def __init__(self): #Kombiniert Elemente des Moorhuhn Spiels. self.bild = bild= Bildmanager(BREITE, HÖHE) #erzeugt Grafik-Fenster bild.screen.bgpic("Bild 1280x750.png") #'bgpic' ist eine Methode, um ein Hintergrundbild zu installieren bild.schrift("Leertaste drücken, um Spiel zu beginnen!") bild.screen.register_shape("huhn01.gif") #'register_shape' bekommt einen Namen als Argument, der mit '.gif' endet=>dieser Name wird als Bilddatei aufgefaßt und diese.... bild.screen.register_shape("huhn02.gif") #....Bilddatei als Turtle shape registriert. Danach kann die Methode 'shape()' aufgerufen werden, um der Turtle diese Gestalt.... ######################################################### bild.screen.register_shape("huhn03.gif") #....zu verleihen. Bilddateien auf '*.gif' endend können jede Gestalt und alle Methoden (z.B. 'left' & 'right') ausführen. bild.screen.register_shape("huhn04.gif") # ######################################################### self.huehner_links = [Huhn("huhn01.gif", self), Huhn("huhn02.gif", self)] ##################################################### self.huehner_rechts = [Huhn("huhn03.gif", self), # Huhn("huhn04.gif", self)] # ##################################################### self.gameover = True #jetzt kann ein neues Spiel beginnen bild.screen.onclick(self.schuss, 1) bild.screen.onkey(self.spiel, "space") #"onkey" heißt soviel wie: "Wenn eine Taste gedrückt wird", hier 'space', soll die Fkt 'spiel' aufgerufen werden bild.screen.listen() #bewirkt, dass nach dem Tastendruck (s.o.) das Spiel auch tatsächlich anfängt bild.screen.getcanvas().config(cursor="circle") #get into Tkinter def spiel(self): if not self.gameover: return #altes Spiel läuft noch self.bild.schrift("SPIEL LÄUFT!") self.schuss = 0 self.score = 0 self.gameover = False for huhn in self.huehner_links: huhn.start_links() ##################################### for huhn in self.huehner_rechts: # huhn.start_rechts() # ##################################### while not self.gameover: for huhn in self.huehner_links: huhn.schritt_links_rechts() ##################################### for huhn in self.huehner_rechts: # huhn.schritt_rechts_links() # ##################################### gameover = self.schuss == SCHÜSSE for huhn in self.huehner_links: gameover = (gameover and huhn.ausdemspiel_links) ######################################################### for huhn in self.huehner_rechts: # gameover = (gameover and huhn.ausdemspiel_rechts) # ######################################################### self.gameover = gameover trefferrate = self.score/(self.schuss*Strafpunkt_links_rechts*Strafpunkt_rechts_links) #hier kommen die Strafpkte von oben ins Spiel self.bild.schrift( ("Score: %1.2f" % trefferrate) + " - Leertaste drücken!") #der Ausdruck '%1.2f' bedeutet 1 Vorkommastelle und 2 Nachkommastellen im Float System if trefferrate >= 0.7: self.klang(GUT) elif 0.4 <= trefferrate < 0.7: self.klang(APPLAUS) global Punkte Punkte=Level*trefferrate def schuss(self, x, y): if self.schuss == SCHÜSSE: return #es läuft kein Spiel, also kein Schuß self.schuss = self.schuss + 1 klangdatei = DANEBEN for huhn in self.huehner_links: if huhn.getroffen: klangdatei = TREFFER huhn.getroffen = False break ######################################### for huhn in self.huehner_rechts: # if huhn.getroffen: # klangdatei = TREFFER # huhn.getroffen = False # break # ######################################### if self.schuss == SCHÜSSE: self.bild.schrift("SPIEL VORBEI!") else: self.bild.schrift("Treffer/Schüsse: %d/%d" %(self.score, self.schuss)) #%d heißt: vz-behaftete Ganzzahl self.klang(klangdatei) def klang(self, soundfile): winsound.PlaySound(soundfile, winsound.SND_ASYNC) #der Befehl 'SND_ASYNC' sorgt dafür, daß das Abspielen des Klangs das Spiel nicht unterbricht, bzw. anhält def main(): #Hauptfunktion MoorhuhnSpiel() return "EVENTLOOP" if __name__ == "__main__": gnampf = main() print(gnampf) Screen().mainloop() #prüft permanent, ob ein Event auftritt mixer.music.stop() #Hintergrundmusik stoppt ############################################################################# # # # ## # Hier wírd eine Highscoreliste der Top 3 erstellt und verwaltet ############################################################### # # ## ############################################################################# # def Schnellfkt_Neueintrag(): Name=input("Geben Sie Ihren Namen ein! ") Neueintrag=[] Neueintrag.append(Punkte) Neueintrag_Namenseintrag=[] Neueintrag_Namenseintrag.append(Name) Neueintrag.append(Neueintrag_Namenseintrag) Highscores.append(Neueintrag) Highscores.sort(reverse=True) if Punkte>0: #man sollte zumindestens etwas getroffen haben, um in die Bestenliste zu kommen if os.path.exists("Bestenliste.json"): #falls die Datei der Bestenliste bereits schon existiert filename = 'Bestenliste.json' with open(filename) as file_object: Highscores = json.load(file_object) #hier wird die - bereits bestehende(!) - Highscoreliste geladen if len(Highscores) < 3: #hier wird dafür gesorgt, daß ein Highscore-Array der Länge 3 entsteht for i in range(len(Highscores)): if Highscores[i][0]==Punkte: #Fall 1: die Punkte sind GLEICH groß wie ein bereits existierender Eintrag => man braucht nicht mehr sortieren Name=input("Geben Sie Ihren Namen ein! ") Highscores[i][1].append(Name) #nur der neue Name wird (zu dem alten, bereits bestehenden) hinzufegügt break else: #Fall 2: die Punkte sind disjunkt => man muß sortieren Schnellfkt_Neueintrag() filename= 'Bestenliste.json' with open(filename, 'w') as file_object: #ab hier wird auch gespeichert json.dump(Highscores, file_object) with open(filename) as file_object: #ab hier wird die bisherige Bestenliste in der Python Shell Zeile für Zeile gedruckt bisherige_Bestenliste=json.load(file_object) #....erst laden elif Punkte < Highscores[-1][0]: print("Schade! Damit haben Sie es leider nicht in die Top 3 geschafft!") else: #der Spieler hat es in die Highscoreliste geschafft und das Highscore-Array (Liste) hat schon die Länge 3 for i in range(len(Highscores)): if Highscores[i][0] < Punkte: #größerer Wert als der kleinste vorkommende Wert gefunden => der letzte (kleinste) Wert des Arrays fliegt raus Schnellfkt_Neueintrag() #ab hier wird die bereits bestehende Liste sortiert (aber noch nicht gespeichert)<-Sortieren ist für die Highscoreliste wichtig! del(Highscores[-1]) #der letzte kleinste Wert ganz rechts im Array wird gelöscht, damit die Highscores noch immer die Top 3 repräsentieren break if Highscores[i][0]==Punkte: #gleichgroßer Wert gefunden Name=input("Geben Sie Ihren Namen ein! ") Highscores[i][1].append(Name) #nur der neue Name wird (zu dem alten, bereits bestehenden) hinzufegügt break filename= 'Bestenliste.json' with open(filename, 'w') as file_object: #ab hier wird auch gespeichert json.dump(Highscores, file_object) with open(filename) as file_object: #ab hier wird die bisherige Bestenliste in der Python Shell Zeile für Zeile gedruckt bisherige_Bestenliste=json.load(file_object) #....erst laden for i in bisherige_Bestenliste: #....dann drucken print(i) else: #falls die Datei der Bestenliste noch nicht existiert, ist dieser else-Block für die Erstellung dieser neuen Datei zuständig Highscores=[] #hier wird eine NEUE Highscoreliste erstellt Schnellfkt_Neueintrag() filename= 'Bestenliste.json' #...und der neuen Datei Ihren Namen gegeben with open(filename, 'w') as file_object: #ab hier wird auch gespeichert json.dump(Highscores, file_object) with open(filename) as file_object: #ab hier wird die neue, initiale Bestenliste zum 1x (und mit dem 1.Eintrag) in die Python Shell geladen.... bisherige_Bestenliste=json.load(file_object) print(bisherige_Bestenliste) #....und gedruckt else: #das ist der Fall, daß alle Schüsse danebengingen print("Sie haben kein einziges Morhuhn abgeschossen!" ) from moorhuhn_3 import*
Code: Alles auswählen
import pygame, time, subprocess from pygame import mixer while True: try: Level=input("Welche Geschwindigkeit (=Level) sollen die Hühner haben? ") Level=int(Level) while (Level<=0): #hier wird sichergestellt, daß nur positive Zahlen eingegeben werden print("Keine negativen Zahlen eingeben!") Level=input("Welche Zahl? ") Level=int(Level) break except ValueError as e: #hier wird sichergestellt, daß nur Integer Zahlen eingegeben werden print("Fehlermeldung! ", e) print("Fehler! Nur natürliche Zahlen eingeben!") print(Level) pygame.init() screen=pygame.display.set_mode((800,250)) #ein leeres (noch farbloses) Feld der Größe 800 x 250 wird erstellt font=pygame.font.Font(None, 38) #Schriftgröße des Textes pygame.time.set_timer(pygame.USEREVENT, 200) #die Zahl 200 gibt an, wie schnell der Text aufgeschrieben wird. Je größer die Zahl, umso langsamer def text_generator(text): tmp= ' ' for letter in text: tmp+=letter if letter != ' ': yield tmp class DynamicText(object): def __init__(self, font, text, pos): self.done=False self.font=font self.text=text self._gen=text_generator(self.text) self.pos=pos self.update() def reset(self): self._gen=text_generator(self.text) self.done=False self.update() def update(self): if not self.done: try: self.rendered=self.font.render(next(self._gen), True, (255,255,255))#Textfarbe (ich habe weiß genommen) except StopIteration: self.done=True time.sleep(2) #Pause (Zeitverzögerung), bis es mit dem Spiel richtig losgeht subprocess.Popen("moorhuhn_2.py", shell=True) def draw(self, screen): screen.blit(self.rendered, self.pos) #die blit Fkt lässt uns das Textbild verschieben text=("Dieses Moorhuhnspiel hat ein Veganer geschrieben...") message=DynamicText(font, text, (65,120)) #Position des Textes im schwarzen Feld mixer.music.load("Tastatur.wav") #lädt nur die Hintergrundmusik (Tastaturgeräusch) mixer.music.play() while True: for event in pygame.event.get(): if event.type==pygame.QUIT: break if event.type==pygame.USEREVENT: message.update() else: screen.fill(pygame.color.Color('black')) #ein leeres (jetzt schwarzes) Feld message.draw(screen) pygame.display.flip() continue mixer.music.stop() #Hintergrundmusik (Tastaturgeräusch) endet break pygame.quit()
Code: Alles auswählen
import pygame, time from pygame import mixer from pygame.locals import* pygame.init() NACHRICHT="""Befreit die Tiere! Schießt sie nicht ab! Lasst sie leben! Schafft die Jagd ab, so wie es bereits in folgenden Ländern der Fall ist: Niederlande Albanien Griechenland Indien Sri Lanka Costa Rica. Ob ein religiöser Grund, wie in Indien und Sri Lanka (Glaube an die Reinkarnation), oder ein säkularer, wie in den anderen Ländern; entscheidend ist, was all diese Länder gemeinsam haben: ES FUNKTIONIERT! Keine einzige 'negative' Konsequenz dessen, was Jäger prophezeit haben, ist in diesen Ländern eingetreten. Lest das Buch von Prof. Carlo Consiglio von der Universität Rom mit dem Titel: "Vom Widersinn der Jagd!" ISBN: 3-86150-372-7 Darin wird wissenschaftlich erklärt, weshalb weder eine 'Überbevölkerung' der Tiere, noch Ernteausfälle, Waldschäden oder Tierseuchen eintreten bzw. ausbrechen können, wenn man die Jagd von heute auf morgen abschafft. Nicht Erbarmen, sondern Gerechtigkeit sind wir den Tieren schuldig! Auch den echten Moorhühnern gegenüber!""" .split('\n') #die 'split'-Fkt teilt einen String in eine Liste auf: das Trennzeichen' ist der Zeilenneubeginn class Credits: def __init__(self, bildschirm, liste): self.bildschirm=bildschirm self.liste=liste self.schriftgröße=50 #hier wird die Schriftgröße festgelegt self.schriftfarbe=(255,255,255) #Schriftfarbe weiß self.Bildschirmmitte=self.bildschirm.height/2 +5 self.zeilenabstand=60 #hier wird der Zeilenabstand festgelegt self.timer=0.0 self.delay=0 self.Bildschirmoberfläche() def Text(self, Nachricht): font=pygame.font.SysFont('Arial', self.schriftgröße) text=font.render(Nachricht, #render=übertragen True, self.schriftfarbe) rect=text.get_rect(center=(self.bildschirm.centerx, self.bildschirm.centery+self.Bildschirmmitte)) return text, rect def Bildschirmoberfläche(self): self.text=[] for i, zeile in enumerate(self.liste): l=self.Text(zeile) l[1].y+=i*self.zeilenabstand self.text.append(l) def update(self): if pygame.time.get_ticks()-self.timer > self.delay: self.timer = pygame.time.get_ticks() for text, rect in self.text: rect.y -=1 def Übertragung(self, surf): for text, rect in self.text: surf.blit(text, rect) #die blit-Fkt läßt uns das Bild verschieben, vgl. Python Zeitschrift, Seite 85, letzter Satz im Schritt 6 screen=pygame.display.set_mode((800,600)) #Bildschirmgröße bildschirm=screen.get_rect() clock=pygame.time.Clock() running=True cred=Credits(bildschirm, NACHRICHT) mixer.music.load("Abspannmusik.wav") mixer.music.play(1) #Musik wird genau 1x gespielt while running: screen.fill((0,0,0)) #Hintergrundfarbe (0,0,0) ist schwarz cred.update() cred.Übertragung(screen) pygame.display.update() clock.tick(60) #hier ist die Geschwindigkeit des scrolleden Textes for event in pygame.event.get(): if event.type==pygame.QUIT: mixer.music.stop() running=False pygame.quit()