Sudokuprogramm

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

So... alles überarbeitet, das neue Programm kann jetzt auch schon Testen.

Paste:
http://paste.pocoo.org/show/20280/

@ Leonidas: Bitte beachte einmal nicht den Sternenimport, ich werde jetzt nie wieder Sternenimporte verwenden (soweit es möglich ist) und diesen Import werde ich konkretisieren, wenn ich das Programm fertig hab und genau weiß, was ich alles importieren muss...
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Da wir ja davon ausgehen müssen, dass der Code ernstgemeint ist, äußere ich mich einmal dazu..

Code: Alles auswählen

class SudokuEntry(Entry):
    def __init__(self, master, x=1, y=1):
        Entry.__init__(self, master, width=3)
In der Regel erhält master einen Defaultwert (None), da man nicht zwingend das übergeordnete Widget angeben muss.

Code: Alles auswählen

if self.get() in ["1","2","3","4","5","6","7","8","9"]
Die Abfrage sieht hübsch aus, ist aber denkbar unperformant, da bei jedem Aufruf der Methode abfragen() die Liste neu erstellt wird. Wesentlich schneller wäre also, die Liste einmalig als Attribut zu setzen und dann darauf zuzugreifen.

Code: Alles auswählen

return "0" # 0 steht für "leer"
Wenn Null für leer steht, solltest du auch die Zahl und nicht den String übergeben! (vgl. Z. 17)

Code: Alles auswählen

i=1
j=1
Zur besseren Lesbarkeit deines Codes solltest du vor und nach dem Gleichheitszeichen ein Leerzeichen einfügen, siehe PEP-0008.

Code: Alles auswählen

nummer=((j-1)%3)+(9*(((j+2)/3)+3*((i-1)/3)-1))+1+3*((i-1)%3)
Ich bin mir nicht sicher, was du mit dieser Zeile bezwecken willst, aber es gibt mit Sicherheit einen Weg, weniger kryptologisch und unleserlich zum Ziel zu kommen!

Code: Alles auswählen

exec "self.neunerblock"+str(nummer)+\
"=SudokuFrame(self.sudokurahmen, relief=RIDGE, "+\
"borderwidth=3, x="+str(i)+", y="+str(j)+")"
Vergiss' exec! Du wirst es in den nächsten Monaten garantiert nicht brauchen, versprochen! Erstelle doch einfach eine Liste, in der du die einzelnen SudokuFrames speicherst, somit erleichterst du dir selbst den Zugriff und allgemein die Lesbarkeit deines Codes. Was du hier geschrieben hast, ist gelinde gesagt Schwachsinn.

Code: Alles auswählen

i=1
while i<=9:
    ..
    i=i+1
Hier liegt ein klassicher Fall für eine for-Schleife vor, da die Schleife jedes immer exakt neun Mal durchlaufen wird.

Code: Alles auswählen

Einzelzeile=[0] # Feld 1 der Zeile soll Index 1 haben
Einzelspalte=[0] # Feld 1 der Spalte soll Index 1 haben
Einzelblock=[0] # Feld 1 des Blocks soll Index 1 haben
Ich verstehe nicht, was du damit bezwecken willst. Wir Programmierer beginnen beim Zählen mit Null, warum erschwerst du dir selbst das Verständnis mit solchen Workarounds?

Code: Alles auswählen

exec "testfeld=self.Zellen["+str(feld)+"][0].abfragen()"
Siehe oben! Vergiss exec und greife über den schon vorliegenden Index einfach auf die Liste zu:

Code: Alles auswählen

testfeld = self.Zellen[feld][0].abfragen()
Die Trennung von GUI und Logik ist dir noch immer nicht geglückt, viel Erfolg damit..
I am not part of the allesburner. I am the [url=http://allesburner.de]allesburner[/url].
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Hi Vingdoloras!

Bitte sei nicht boese mit Leonidas, Redprince und Co. Wenn man das hier so ließt koennte ich mir vorstellen, dass der ein oder andere denkt, sie machen das aus reiner Schikane!
Aber das tun sie nicht! Sie vergessen nur manchmal neben den Contras auch die Pros hervorzuheben... aber schließlich willst du Hilfe bei der Problemloesung... also ist es ja eigentlich richtig so :roll:

Und nochwas:
Vingdoloras hat geschrieben:@ Leonidas: Bitte beachte einmal nicht den Sternenimport, ich werde jetzt nie wieder Sternenimporte verwenden (soweit es möglich ist) und diesen Import werde ich konkretisieren, wenn ich das Programm fertig hab und genau weiß, was ich alles importieren muss...
Vingdoloras hat geschrieben:@ Leonidas: Hab extra für dich den Sternchenimport weg gemacht Wink
Mach es doch nicht fuer Leonidas! Mach es fuer DICH und andere, die deinen Quelltext benutzen!
SternchenImporte sind etwas schreckliches! Glaubst du irgendjemand hat den kompletten Namespace im Kopf, den Tkinter mitbringt?
Und wieviele neue und potenziell nutzbare Namen werden dadurch verbraucht, die man sonst fuer eigene Zwecke nutzen koennte?!

Mein Tipp:

Code: Alles auswählen

import Tkinter as tk
tk.Frame zu schreiben ist ja nun wohl noch vertretbar, oder? Und vorallem weitaus weniger Zeitaufwaendig, als jedem genutzten Import eine eigene import-Zeile zu verpassen!

Beste Gruesse
NKoehring
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

Redprince hat geschrieben:

Code: Alles auswählen

class SudokuEntry(Entry):
    def __init__(self, master, x=1, y=1):
        Entry.__init__(self, master, width=3)
In der Regel erhält master einen Defaultwert (None), da man nicht zwingend das übergeordnete Widget angeben muss.
Änder ich sofort!
Redprince hat geschrieben:

Code: Alles auswählen

if self.get() in ["1","2","3","4","5","6","7","8","9"]
Die Abfrage sieht hübsch aus, ist aber denkbar unperformant, da bei jedem Aufruf der Methode abfragen() die Liste neu erstellt wird. Wesentlich schneller wäre also, die Liste einmalig als Attribut zu setzen und dann darauf zuzugreifen.
Änder ich ebenfalls!
Redprince hat geschrieben:

Code: Alles auswählen

return "0" # 0 steht für "leer"
Wenn Null für leer steht, solltest du auch die Zahl und nicht den String übergeben! (vgl. Z. 17)
Bei mir hat das Testen nicht funktioniert, weil die Funktion die Zahl zurückgab, der Testmechanismus aber geschaut hat, ob der String zurückgegeben wurde. Ich hab es in der Abfragen-Funktion geändert, aber wenn du willst, mach ich es andersrum.
Redprince hat geschrieben:

Code: Alles auswählen

i=1
j=1
Zur besseren Lesbarkeit deines Codes solltest du vor und nach dem Gleichheitszeichen ein Leerzeichen einfügen, siehe PEP-0008.
Da ist es wohl mal wieder mit mir durchgegangen, wird auch berichtigt!
Redprince hat geschrieben:

Code: Alles auswählen

nummer=((j-1)%3)+(9*(((j+2)/3)+3*((i-1)/3)-1))+1+3*((i-1)%3)
Ich bin mir nicht sicher, was du mit dieser Zeile bezwecken willst, aber es gibt mit Sicherheit einen Weg, weniger kryptologisch und unleserlich zum Ziel zu kommen!
Aus i und j werden jeweils die Feldnummern berechnet, die in einer Zeile/Spalte/einem Block vorkommen. Die Formeln sind von meinem Vater (ich will ihm nicht die Schuld in die Schuhe schieben), aber ich habe selber eine Weile rumprobiert, ob man diese Formel nicht verkürzen könnte, aber glaub mir, Mathematik ist eines meiner Lieblingsfächer in der Schule und ich habe nichts* gefunden.
* Ich habe schon etwas gefunden, denn
3*((i-1)/3)
KÖNNTE man ja nach den Regeln der Mathematik extrem vereinfachen, da erst durch drei geteilt wird und dann mit drei multipliziert, aber schau dir das mal genau an... alle Teile der Formel sind Integer, also liefert Python bei Division auch nur Integer zurück, was diese Formel (anscheinend, mein Vater hat sie halt entwickelt, ich kann ihn ja mal fragen, was ihn zu sowas getrieben hat) ausnutzt.
Jedenfalls ließe sich das vielleicht auch mit Python-Code schreiben, aber ich bin mir sicher, dass DAS wirklich zu viele Zeilen wären.
Redprince hat geschrieben:

Code: Alles auswählen

exec "self.neunerblock"+str(nummer)+\
"=SudokuFrame(self.sudokurahmen, relief=RIDGE, "+\
"borderwidth=3, x="+str(i)+", y="+str(j)+")"
Vergiss' exec! Du wirst es in den nächsten Monaten garantiert nicht brauchen, versprochen! Erstelle doch einfach eine Liste, in der du die einzelnen SudokuFrames speicherst, somit erleichterst du dir selbst den Zugriff und allgemein die Lesbarkeit deines Codes. Was du hier geschrieben hast, ist gelinde gesagt Schwachsinn.
EDIT: :oops: Hab die Codestelle mit ner anderen verwechselt, bei der hier werde ich auf jeden Fall schaun, was ich machen kann!
Redprince hat geschrieben:

Code: Alles auswählen

i=1
while i<=9:
    ..
    i=i+1
Hier liegt ein klassicher Fall für eine for-Schleife vor, da die Schleife jedes immer exakt neun Mal durchlaufen wird.
Stimmt!
Redprince hat geschrieben:

Code: Alles auswählen

Einzelzeile=[0] # Feld 1 der Zeile soll Index 1 haben
Einzelspalte=[0] # Feld 1 der Spalte soll Index 1 haben
Einzelblock=[0] # Feld 1 des Blocks soll Index 1 haben
Ich verstehe nicht, was du damit bezwecken willst. Wir Programmierer beginnen beim Zählen mit Null, warum erschwerst du dir selbst das Verständnis mit solchen Workarounds?
Sudoku ist ein reines Zahlenspiel (damit meine ich, dass alles, was der Spieler/der Nutzer des Programms nur Zahlen eingibt und [fast] alle Werte, mit denen das Script arbeitet, Zahlen sind). Daher werden im Lösungsmechanismus ziemlich oft Zahlen vorkkommen. Ziemlich Ziemlich oft. Es werden einmal solche Zahlen vorkommen, die in den Feldern eingetragen sind. Das sind Werte von 1 bis 9. Es werden aber auch Indizes vorkommen, die nnormalerweise bei 0 anfangen. Nun stell dir mal vor, du vergisst in einem Riesencode, der eine Riesenmenge an Zahlen beinhaltet, EIN- oder ZWEIMAL, für Feld x den richtigen Index x-1 zu verwenden und schreibst nur x.
Was passiert dann? In vielen Fällen wird das Programm trotzdfem laufen, aber ein falsches Ergebnis liefern, also hast du nichtmal ein Traceback mit Zeilenangabe. Das wird ein Gesuche...
Zusätzlich ist es intuitiver, wenn die erste Zeile

Code: Alles auswählen

sudoku.Zeilen[1]
ist. Daher werde ich diesen Teil des Codes nicht ändern, 'tschuldigung...
Redprince hat geschrieben:

Code: Alles auswählen

exec "testfeld=self.Zellen["+str(feld)+"][0].abfragen()"
Siehe oben! Vergiss exec und greife über den schon vorliegenden Index einfach auf die Liste zu:

Code: Alles auswählen

testfeld = self.Zellen[feld][0].abfragen()
Das ist wirklich Blindheit gewesen :oops: , hab den Fehler entdeckt, kurz bevor ich deinen Post gelesen hab :wink:
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

nkoehring hat geschrieben:Hi Vingdoloras!

Bitte sei nicht boese mit Leonidas, Redprince und Co. Wenn man das hier so ließt koennte ich mir vorstellen, dass der ein oder andere denkt, sie machen das aus reiner Schikane!
Aber das tun sie nicht! Sie vergessen nur manchmal neben den Contras auch die Pros hervorzuheben... aber schließlich willst du Hilfe bei der Problemloesung... also ist es ja eigentlich richtig so :roll:
Ich habe nie gesagt/gedacht, dass sie mich niedermachen wollen... wenigstens nicht nur :wink:
nkoehring hat geschrieben:Und nochwas:
Vingdoloras hat geschrieben:@ Leonidas: Bitte beachte einmal nicht den Sternenimport, ich werde jetzt nie wieder Sternenimporte verwenden (soweit es möglich ist) und diesen Import werde ich konkretisieren, wenn ich das Programm fertig hab und genau weiß, was ich alles importieren muss...
Vingdoloras hat geschrieben:@ Leonidas: Hab extra für dich den Sternchenimport weg gemacht Wink
Mach es doch nicht fuer Leonidas! Mach es fuer DICH und andere, die deinen Quelltext benutzen!
SternchenImporte sind etwas schreckliches! Glaubst du irgendjemand hat den kompletten Namespace im Kopf, den Tkinter mitbringt?
Und wieviele neue und potenziell nutzbare Namen werden dadurch verbraucht, die man sonst fuer eigene Zwecke nutzen koennte?!
Ja, ich wollte Leo nur mal ne Freude machen :D
nkoehring hat geschrieben:Mein Tipp:

Code: Alles auswählen

import Tkinter as tk
tk.Frame zu schreiben ist ja nun wohl noch vertretbar, oder? Und vorallem weitaus weniger Zeitaufwaendig, als jedem genutzten Import eine eigene import-Zeile zu verpassen!
:D :D :D :D :D Noch besser :D :D :D :D :D
BlackJack

Das mit den Indizes und dem Start bei 1 ist Unsinn. Starte mal bei 0 und überarbeite dann zum Beispiel die Formel für `nummer`. Die wird dann auf einen Schlag schonmal kürzer, weil die ganzen Indexanpassungen nicht mehr gemacht werden müssen. Es hat einen Grund warum Informatiker bei 0 anfangen ─ weil es einfacher und für Rechner natürlicher ist.

Bei vielen Programmiersprachen fingen Indizes früher bei 1 an, oder der Programmierer konnte sich den Startindex sogar aussuchen. Fast alle neueren Sprachen fangen bei 0 an, weil man aus der Erfahrung mit den ganzen "off by one"-Fehlern gelernt hat, die dadurch entstehen, das der Programmierer ständig bei irgendwelchen Indizes eins dazu zählen oder abziehen musste und es dann doch hier und da vergass oder falsch gemacht hat.

Bei der Formel ist "vereinfachen" vielleicht nicht der richtige Weg sondern eben doch "viele" Zeilen schreiben, die man dafür dann aber versteht. Der kürzeste Quelltext ist nicht immer der verständlichste. Alternativ könnte man die Formel in einem Kommentar verständlich erklären.
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

BlackJack hat geschrieben:Das mit den Indizes und dem Start bei 1 ist Unsinn. Starte mal bei 0 und überarbeite dann zum Beispiel die Formel für `nummer`. Die wird dann auf einen Schlag schonmal kürzer, weil die ganzen Indexanpassungen nicht mehr gemacht werden müssen.
Die Formel wird dann kürzer? Glaube ich eher nicht...
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

Vingdoloras hat geschrieben:
BlackJack hat geschrieben:Das mit den Indizes und dem Start bei 1 ist Unsinn. Starte mal bei 0 und überarbeite dann zum Beispiel die Formel für `nummer`. Die wird dann auf einen Schlag schonmal kürzer, weil die ganzen Indexanpassungen nicht mehr gemacht werden müssen.
Die Formel wird dann kürzer? Glaube ich eher nicht...
Ich glaub doch:

Code: Alles auswählen

nummer = ((j-1)%3)+(9*(((j+2)/3)+3*((i-1)/3)-1))+1+3*((i-1)%3)
nummer = (j%3)+(9*(((j+1)/3)+3*(i/3)-1))+1+3*(i%3)
Also entweder ich habe was vergessen oder die Formel ist tatsaechlich kuerzer geworden, weil jetzt diese Rumrechnereien wegfallen ;)
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Vingdoloras hat geschrieben:Bei mir hat das Testen nicht funktioniert, weil die Funktion die Zahl zurückgab, der Testmechanismus aber geschaut hat, ob der String zurückgegeben wurde. Ich hab es in der Abfragen-Funktion geändert, aber wenn du willst, mach ich es andersrum.
Mir ist es vollkommen egal, wie du es machst, allerdings kann es kein guter Stil sein, bewusst einen Integer als String zurückzugeben, weil man selbst irgendwo im eigenen Code einen Fehler eingebaut hat, der das natürliche Verhalten mit einer Fehlermeldung straft!
I am not part of the allesburner. I am the [url=http://allesburner.de]allesburner[/url].
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

Das Programm ordnet die Felder ganz falsch zu, ich muss was ändern...
Antworten