Die Webseiten der Fachschaft Informatik am ERG Saalfeld
"Türme von Hanoi" in Python (2. Version)
import os # wegen 'cls'
import sys # wegen Anzahl der Scheiben als Parameter
import time # für die Anweisung 'sleep' für Pause
#-------------------------------------------------------------------------
from ctypes import *
STD_OUTPUT_HANDLE = -11
class COORD(Structure):
pass
COORD._fields_ = [("X", c_short), ("Y", c_short)]
def print_at(r, c, s):
h = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
windll.kernel32.SetConsoleCursorPosition(h, COORD(c, r))
c = s.encode("windows-1252")
windll.kernel32.WriteConsoleA(h, c_char_p(c), len(c), None, None)
#print_at(6, 3, "Hello")
# Quelle: https://rosettacode.org/wiki/Terminal_control/Cursor_positioning#Python
#-------------------------------------------------------------------------
### Konstanten ###
my_disc = [" ",
" ### ",
" XXXXX ",
" &&&&&&& ",
" %%%%%%%%% ",
" $$$$$$$$$$$ ",
" ############# ",
" XXXXXXXXXXXXXXX ",
" &&&&&&&&&&&&&&&&& ",
" %%%%%%%%%%%%%%%%%%% ",
" $$$$$$$$$$$$$$$$$$$$$ ",
"#######################"]
boden = " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
aktuelle_disc = 0 # nur zur "Initialisierung"
anzahl_bewegungen = 0 # Initialisierung
### Klassendefinitionen ###
class Scheibe():
def __init__(self, nummer_scheibe):
Scheibe.form = my_disc[nummer_scheibe]
def zeichnen(self, stab, scheiben_nr_auf_stab):
pos_rechts = 37 * stab - 34 # stab_a = 1, stab_b = 2, stab_c = 3
pos_oben = 17 - scheiben_nr_auf_stab
print_at(pos_oben, pos_rechts, self.form)
def loeschen(self, stab, scheiben_nr_auf_stab):
pos_rechts = 37 * stab - 34 # stab_a = 1, stab_b = 2, stab_c = 3
pos_oben = 17 - scheiben_nr_auf_stab
print_at(pos_oben, pos_rechts, my_disc[0])
class Stab():
def __init__(self,nr):
self.anzahl = 0
self.nummer = nr # z.B.: stab_a = 1, stab_b = 2, stab_c = 3
self.scheiben = [] # Liste von Scheiben, die auf diesem Stab sind
def scheibe_aufnehmen(self, nummer_scheibe):
self.scheiben.append(nummer_scheibe)
self.anzahl += 1 # Anzahl um 1 erhöhen
hilf = Scheibe(nummer_scheibe)
stab_nr = self.nummer
scheiben_nr_auf_stab = self.anzahl
hilf.zeichnen(stab_nr, scheiben_nr_auf_stab)
def scheibe_abgeben(self):
aktuelle_scheibe = self.scheiben.pop() # Rückgabe ist Nummer der Scheibe (int)
stab_nr = self.nummer
scheiben_nr_auf_stab = self.anzahl
hilf = Scheibe(scheiben_nr_auf_stab)
hilf.loeschen(stab_nr, scheiben_nr_auf_stab)
self.anzahl -= 1 # Anzahl um 1 verkleinert
return aktuelle_scheibe # das ist die Nummer der Scheibe / my_disc
class StabX(Stab):
laenge = 0
def __init__(self,nr):
super().__init__(nr)
def zeichne_stab(self):
for i in range(StabX.laenge, 0, -1):
print_at(17-i, self.nummer * 37 - 23, "|") # siehe bei Scheibe.zeichnen
def scheibe_aufnehmen(self, nummer_scheibe):
super().scheibe_aufnehmen(nummer_scheibe)
self.zeichne_stab()
def scheibe_abgeben(self):
aktuelle_scheibe = super().scheibe_abgeben()
self.zeichne_stab()
return aktuelle_scheibe
### siehe https://erasmus-reinhold-gymnasium.de/info/rekursion/hanoi.html#programm
def bewege (anzahl,stab_a,stab_b,stab_c):
if anzahl > 0:
bewege(anzahl-1,stab_a,stab_c,stab_b)
aktuelle_disc = stab_a.scheibe_abgeben()
stab_c.scheibe_aufnehmen(aktuelle_disc)
global anzahl_bewegungen
anzahl_bewegungen += 1 # Anzahl um 1 erhöhen
time.sleep(5/10) # sonst ist das Programm viel zu schnell
bewege(anzahl-1,stab_b,stab_a,stab_c)
######## Hauptprogramm ########
# Bildschirm löschen
os.system('cls')
# Quelle: https://rosettacode.org/wiki/Terminal_control/Hiding_the_cursor#Python
print("\x1b[?25l") # Cursor ausschalten
# wir lesen die Anzahl der Scheiben ein
anzahl_scheiben = int(sys.argv[1])
# wir zeichen den Boden, wo die 3 Stäbe und damit die Scheiben drauf gelegt werden
print_at(17, 0, boden)
# Wir erstellen die 3 Stäbe (also die Instanzen = Objekte)
stab_a = StabX(1)
stab_b = StabX(2)
stab_c = StabX(3)
# wir setzen die Länge der Stäbe auf anzahl_scheiben + 1
StabX.laenge = anzahl_scheiben + 1
# wir legen die Scheiben auf den stab_a
for i in range(anzahl_scheiben, 0, -1):
stab_a.scheibe_aufnehmen(i)
stab_b.zeichne_stab()
stab_c.zeichne_stab()
time.sleep(2) # 2s zum Anschauen, bevor es losgeht
# jetzt läuft die Verscheibung der Scheiben ab = das eigentliche Programm
bewege(anzahl_scheiben,stab_a,stab_b,stab_c)
# diese Anweisungen dient insbesondere dazu, dass der Pfad am Ende unter den Türmen ist
time.sleep(5/10) # Pause 1/2 sekunde
print_at(22, 3, "Bin fertig!\n")
print(" Anzahl der Bewegungen:", anzahl_bewegungen)
print("\x1b[?25h") # Cursor wieder anschalten
zurück
© ERG Saalfeld - HD. Kirmse 30.04.2023
|