Sudokuprogramm

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Vingdoloras hat geschrieben:
Leonidas hat geschrieben:Ich führe nie Tkinter-Code aus, weil ich es gar nicht installiert habe
Welche Version von Python nutzt du? Tkinter gehört doch zur Standardbibliothek, oder?
Ich nutze 2.4.x, 2.5.1 und 3.0a2 (wobei 3.0 "nutzt" keiner, ich schaue es mir auch nur an). Aber dankenswerterweise hat der Windows-Installer die Option "[X] Tkinter installieren", wo man das Häkchen wegmachen kann und die meisten Distributionen haben intelligenterweise Tkinter in ein Paket wie ``python-tk`` ausgelagert, das man nicht installieren muss. Das hat auch deswegen Sinn, weil sonst Python Tk reinziehen würde, was wiederrum die X-Libs reinziehen würde, was man auf einem Server nicht braucht und eingentlich auch nicht haben will.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

DER Olf hat geschrieben:dieses mal mit Flexibler Algorithmus-Implementation und OOP-igerem GUI-Code
öhm *hust* ich hab seit einem knappen halben Jahr Informatik in der Schule, so ziemlich alles was ich weiß, habe ich aus zwei Büchern...
DER Olf hat geschrieben:also hopp hopp, google.de, Tkinter Frame
hab ich versucht, Tkinter Frame in Google... kamen berichte über das "neue" Python 1.5 und ein (mehr oder weniger nützlichers) Anwendungsbeispiel, in dem das Frame-Widget vorkam und in dessen erklärung dann im Text einmal Frame und ein paar male Tkinter vorkam, aber keine Erklärung etc. Deswegen hab ich bei Google an "Tkinter Frame" noch "2.4" rangehängt und schwupps kam DIESER Thread hier zum Vorschein :o

help(Tkinter.Frame) liefert nen Error, ich Tipp mich grad Schritt für Schritt durch die Help-Funktionen, erst modules, dann modules Tkinter... das dauert jetzt etwas länger, da mein Virenscanner im Hintergrund läuft...

Redprince hat geschrieben:
Leonidas hat geschrieben:Wenn man Variablen anfängt zu nummerieren ist man oft schon dabei das Probelm falsch anzugehen. In Python existieren Listen und for-schleifen, mit denen man beliebige Anzahlen von Widgets erstellen kann. Das würde ich dir eben raten.
Immer noch..
Ich hab's versucht, aber egal wie ichs drehe und wende, mir fällt nix ein... mir fehlt in solchen Sachen noch etwas die praktische Erfahrung, kann mich da bitte jemand aufklären?
DER Olf
User
Beiträge: 283
Registriert: Mittwoch 24. Dezember 2003, 19:32

Vingdoloras hat geschrieben:
DER Olf hat geschrieben:dieses mal mit Flexibler Algorithmus-Implementation und OOP-igerem GUI-Code
öhm *hust* ich hab seit einem knappen halben Jahr Informatik in der Schule, so ziemlich alles was ich weiß, habe ich aus zwei Büchern...
ach herrje... andere hatten nie Informatik in der Schule. Und Bücher geben generell nur Denkanströße und Beispiele - selber Denken, Ausprobieren, Fehler machen, Erfahrungen sammeln heißen hier die Stichwörter.
help(Tkinter.Frame) liefert nen Error,
Was für einen? -.- Manchmal soll man aus Fehlermeldungen tatsächlich schlau werden...[/quote]
das dauert jetzt etwas länger, da mein Virenscanner im Hintergrund läuft...
dann schalt ihn doch einfach für den Moment aus...
Ich hab's versucht, aber egal wie ichs drehe und wende, mir fällt nix ein... mir fehlt in solchen Sachen noch etwas die praktische Erfahrung, kann mich da bitte jemand aufklären?
kümmer dich mal um Listen (für viele andere sprachen: arrays)
und vorallem um zweidimensionale ;)
dann lässt sich da ganz einfach durch iterieren.

bzgl. Google:
suchwort: Tkinter Frame
2. Treffer: http://effbot.org/tkinterbook/frame.htm

was fehlt dir denn jetzt noch?
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Vingdoloras hat geschrieben:
Redprince hat geschrieben:
Leonidas hat geschrieben:Wenn man Variablen anfängt zu nummerieren ist man oft schon dabei das Probelm falsch anzugehen. In Python existieren Listen und for-schleifen, mit denen man beliebige Anzahlen von Widgets erstellen kann. Das würde ich dir eben raten.
Immer noch..
Ich hab's versucht, aber egal wie ichs drehe und wende, mir fällt nix ein... mir fehlt in solchen Sachen noch etwas die praktische Erfahrung, kann mich da bitte jemand aufklären?
Das [wiki=Tutorial]Tutorial im Wiki[/wiki] kann, speziell der Abschnitt Listen erscheint in diesem Zusammenhang sinnbehaftet. Wälz' dich durch verschiedene für Einsteiger geschriebene Artikel und probiere mit der Phyton-Shell einfach aus, wird schon nichts kaputt gehen.. Letzten Endes bist du nicht der erste, der Programmieren lernt und wirst analog dazu nicht der letzte sein, der über bereits verfasste Texte einen Zugang finden wird.
I am not part of the allesburner. I am the [url=http://allesburner.de]allesburner[/url].
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Hallo,

hier ein Referenz zu Tkinter! Bessers kannst glaube ich nicht finden.
http://docs.huihoo.com/tkinter/tkinter- ... index.html



Gruss
pyStyler
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