Python Schach

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
spooky0815

Hey Ihr,

Nun wie versprochen meine erste Version von Schach.
Sie ist zwar vorerst nur eine Spieler vs. Spieler - Version, beinhaltet aber (hoffentlich :) alle Regeln, Sonderfälle, Endzustände, etc.

Die KI ist gerade am entstehen...dazu sind leider einschneidende Veränderungen am Aufbau dieser Version nötig und es wird noch einige Zeit dauern (Die KI existiert bereits, ist jedoch sehr langsam und noch nicht allzu schlau) :(

Leider habe ich beim programmieren der Version ein simples array für das Schachbrett und die Figuren benutzt, was jetzt leider sehr viel Performanz kostet (ich habe ich im Quelltext kurz erklärt).

Schön ist die Zug-Anzeige gelungen, mit der alle mögliche Züge der gewählten Figur angezeigt werden (grün=bedenkenlos, rot=bedroht, geld=bedroht aber duch eigene Figur schützt)

Schauts euch mal an...für Feedback wäre ich dankbar!

hier der link:

http://www.mvodel.de/schach.zip

Ciaoi

Matthias
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

Hi!

Wow, sehr schön, gefällt mir. :)

Der Code gefällt mir weniger. Hab ihn zwar nur kurz überflogen, schaut aber furchtbar aus :) Wenn ich das Wort global sehe, bekomme ich meistens Krämpfe. Bei kleinen Scripten is es ja nicht so schlimm, aber Dein Programm ist doch schon was grösseres. Ich würd versuchen, den ganzen Code etwas besser zu strukturieren, Stichwort Klassen ;). Und ich würde das jetzt machen (höchste Zeit), noch bevor noch weitere Funktionalität dazu kommt, sonst wird das sehr mühsam.
Ich weiß, ich hab leicht reden :)


Gruß, mawe
icepacker
User
Beiträge: 49
Registriert: Dienstag 15. November 2005, 18:48

hi
gefällt mir gut funzt alles super. von ein paar anlaufschwierigkeiten abgesehen..
du scheinst das spiel unter windows programmiert zu haben ? da du winsound importierst.
ich habe grad festgestellt das es die unter linux nicht gibt :roll:
naja ich bekomm eine fehlermeldung und das schachspiel stürzt ab.
nachdem ich aber die zeile

Code: Alles auswählen

from winsound import *
auskommentiert hatte ging alles wunderbar. also mein tip für systemunabhängigkeit:
baue für das importieren von winsound so was in der art von try-except ein damit sich das programm trotzdem starten lässt auch wenn er das modul nicht findet :wink:

lg icepacker

Ps: es kann natürlich sein das ich grad den größten schwachsinn gelabert habe :oops: , dann
entschuldigt mich bitte, bin noch grad am anfang meiner python programmierung
ubuntu linux !!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

icepacker hat geschrieben:Ps: es kann natürlich sein das ich grad den größten schwachsinn gelabert habe :oops: , dann entschuldigt mich bitte, bin noch grad am anfang meiner python programmierung
Nein, du hast schon recht. Das Modul winsound gibt es unter Linux nicht denn das win im Namen kommt natürlich von Windows nicht von to win=gewinnen ;)

Wenn die Importzeile auskommentiert wird, kann es zu Abstürzen kommen, weil Funktionen und Variablen nicht definiert sind. Überhaupt sollte man *-Importe vermeiden, schlechter Stil, siehe ModulImporte
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
spooky0815

Hey,

Vielen Dank für die Tipps...wegen der OS-Kompatibilität mach ich mich gleich drüber - dürfte kein Problem werden :)

Die import * methode ist nicht toll...weiß schon...wird geändert !

Die "globals" sind immer unschön...ich ahne es jetzt schon - ich werde wohl ein oder zwei Nächte investieren und das ganze objektorientiert Schreiben *freu*. Bei der Gelegenheit werde ich auch das uneffiziente Schachbrett-array beseitigen und dafür Listen von "Positionen mit Figuren " einführen. Das dürfte gerade in Hinsicht auf die Effizienz meiner KI und meiner "situation_patt"-Funktion extreme Vorteile bringen.

Ich meld mich A.S.A.P :)

Ciaoi

Matthias
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

spooky0815 hat geschrieben:Bei der Gelegenheit werde ich auch das uneffiziente Schachbrett-array beseitigen und dafür Listen von "Positionen mit Figuren " einführen.
Vielleicht kannst du ja eine passende Klasse schreiben, das ist das tolle an OOP, dass du eigene Datentypen definieren kannst.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Au, toll, ein Programm verreissen. :twisted:

Das ist aber auch echt schlimm.

Sehr viele Zeilen sind zu lang (>80 Zeichen). Dann fehlen Leerzeichen vor und nach Operatoren und nach Kommata zur besseren Lesbarkeit. Es gibt inkonsistente Einrückung z.B. in den Zeilen 337-338 und 348-349.

Schlechter Stil, der zu schlechter Wartbarkeit führt

Ein paar allgemeine Anmerkungen die für jedes Programm gelten.

Die vielen `from xxx import *` führen zu ganz vielen unbenutzten Namen, die den Namensraum des Moduls zumüllen. Hier sind mal alle Namen die Du importierst, aber nie benutzt:

setrecursionlimit, TypeType, mainloop, MacOS, prefix, maxint, Template, showwarning, LAST, TclVersion, copyright, Wm, RETRYCANCEL, strptime, NUMERIC, mktime, WARNING, DictProxyType, rstrip, splitfields, exc_value, ObjectType, OptionMenu, EXTENDED, OFF, maxunicode, askfloat, lowercase, Scrollbar, MethodType, ModuleType, image_names, atoi_error, capwords, stderr, ClassType, LambdaType, XRangeType, getfilesystemencoding, Y, lstrip, Misc, CodeType, Label, PAGES, index_error, interrupt_main, excepthook, LabelFrame, BaseWidget, image_types, index, YESNO, clock, UnicodeType, exc_type, version, Grid, callstats, Line, api_version, FLAT, CanvasText, joinfields, ABORTRETRYIGNORE, getboolean, start_new, atof_error, S, COMMAND, Bitmap, ACTIVE, path, FrameType, BASELINE, digits, tkinter, struct_time, setdlopenflags, rfind, Tcl, maketrans, LockType, askretrycancel, getrefcount, Group, setcheckinterval, replace, WRITABLE, FixTk, SEPARATOR, NSEW, Rectangle, rjust, executable, platform, rindex, NotImplementedType, getrecursionlimit, path_hooks, CHECKBUTTON, ANCHOR, RIDGE, PanedWindow, Tributton, SOLID, N, SEL_FIRST, TkVersion, meta_path, Dialog, UNITS, TupleType, join, Text, SW, OUTSIDE, expandtabs, IGNORE, YESNOCANCEL, error, localtime, wantobjects, SE, hexversion, ascii_lowercase, DictType, EXCEPTION, IntType, Polygon, DOTBOX, SINGLE, octdigits, getdefaultencoding, INSERT, BROWSE, punctuation, BuiltinFunctionType, SliceType, BEVEL, version_info, PIESLICE, FileType, sys, BuiltinMethodType, CANCEL, capitalize, Message, byteorder, BufferType, center, displayhook, stdin, getcheckinterval, exc_traceback, PROJECTING, ComplexType, getdouble, getdlopenflags, MULTIPLE, OKCANCEL, altzone, AtSelLast, ListType, get_ident, tzset, ascii_uppercase, TRUE, Widget, showerror, exec_prefix, Toplevel, call_tracing, CallWrapper, accept2dyear, exit_thread, rsplit, FIRST, ON, OK, ctime, allocate_lock, ABORT, GROOVE, Event, Scale, uppercase, BUTT, exc_clear, daylight, AtInsert, whitespace, FloatType, askinteger, atol_error, Spinbox, Arc, allocate, asctime, StringTypes, GeneratorType, ImageItem, VERTICAL, MITER, warnoptions, argv, swapcase, Place, EllipsisType, ERROR, EW, Pack, CHORD, Image, BitmapImage, AtSelFirst, RADIOBUTTON, exc_info, HIDDEN, os, DictionaryType, letters, askquestion, NoDefaultRoot, CHAR, path_importer_cache, BooleanType, HORIZONTAL, ljust, TclError, MOVETO, SUNKEN, READABLE, NE, builtin_module_names, NS, InstanceType, NW, RAISED, AtEnd, stdout, BooleanVar, settrace, setprofile, Variable, atoi, atol, atof, INFO, LongType, SEL, FALSE, SEL_LAST, getint, Radiobutton, tzname, Oval, Listbox, RETRY, ascii_letters, DoubleVar, Window, timezone, UnboundMethodType, CanvasItem, translate, QUESTION, ROUND, UNDERLINE, ARC, FunctionType, TracebackType, E, StringType, printable, Entry, hexdigits, CENTER, CASCADE, Studbutton, INSIDE, Menubutton, modules, StringVar, At, zfill, SCROLL, NoneType

Die ganzen `global` Deklarationen sorgen dafür, das die Funktionen nicht unabhängig voneinander sind und man sie damit auch nicht einzeln verstehen kann.

`time_w`, `time_s`, `time_count_w`, `time_count_s`, `mouse_lock`, `zug_50` und noch einige andere sind in Funktionen als ``global`` markiert aber auf Modulebene nicht an einen Wert gebunden. Die werden auf Modulebene erstellt wenn das erste mal so eine Funktion aufgerufen wird. Sollte das eine sein, die den Wert nur lesen will, dann gibt's einen `NameError`.

Ausnahmen nur mit ``except:`` behandeln ohne den konkreten Typ der Ausnahme anzugeben ist schlecht, weil man damit Ausnahmen unterdrückt, die einem wichtige Informationen bei der Fehlersuche bringen können. So geschehen zum Beispiel in `zeit_w()`.

Zuviele lokale Variablen und/oder Verzweigungen machen Funktionen unübersichtlich und sind ein Zeichen dafür, das man vielleicht zuviel in einer Funktion macht die besser auf mehrere Funktionen aufgeteilt werden sollte. Betrifft zum Beispiel `brett_init()` oder `start_zug()` und `zug_verlauf()`. Wenn es unübersichtlich wird, übersieht man auch leicht unbenutzte Variablen. In `brett_init()` werden die Variablen `mutex` und `zeile` beispielweise gar nicht benutzt. Das gleiche gilt für `mutex` in `setze_figur()` oder `i` und `inv` in `test_verlauf()`.

Anstelle von 0 und 1 sollte man `False` und `True` benutzen wenn man Wahrheitswerte meint, das macht das Programm lesbarer.

Und in Python muss man um einfache Bedingungen keine Klammern setzen. Das sollte man nur machen wenn es sonst nicht auf den ersten Blick ersichtlich wird, was zuerst geprüft wird.

Dokumentieren mit `docstrings` wo beschrieben wird was die Funktion tut, wofür die Parameter stehen und in etwa welchen Wertebereich sie haben und was zurückgegeben wird, falls es einen Rückgabewert gibt, ist immer eine gute Idee wenn man das Programm auch später noch verstehen möchte oder es andere verstehen sollen.

Konkrete Probleme

Bei `callback()` steht im Kommentar, das die Funktion nicht benutzt wird, aber falls sie das mal sollte, dann ist der Name `eingabe` undefiniert.

Den Kommentar beim `feld`, dass das 2D-Feld ineffizient ist, würde ich nicht unterschreiben. Dein Programm geht einfach nur an einigen Stellen ziemlich ineffizient damit um. (Das Wort "Performanz" gibt's im deutschen übrigens nicht.)

Du mischt Spiellogik mit GUI-Code. Das macht die Funktionen unübersichlicher weil zwei verschiedene Dinge in einer Funktion passieren. Sie werden damit auch automatisch länger und verwenden mehr Variablen. Ausserdem kann man die GUI dann nicht einfach austauschen, z.B. weil man ein anderes Toolkit benutzen möchte, oder einen Netzwerk-Modus einbauen möchte wo die GUI nicht (nur) lokal vorhanden ist.

Bei der Zeitmessung hast Du `copy'n'paste` Programmierung verwendet. Die beiden Funktionen unterscheiden sich nur minimal und sollten deshalb zu einer zusammengefasst werden, die sich nur durch entsprechende Parameter unterscheiden. Wenn Du die Funktion verändern möchtest, dann musst Du das dann nicht mehr an zwei Stellen parallel machen, wobei man schnell mal vergessen kann *beide* Funktionen anzupassen. Macht halt doppelt Arbeit.

In der Funktion `logging()` stecken IMHO zuviele Informationen in einer einfachen Zahl (`t`). Ob es ein Zug mit "normalen" Start- und Endpositionen oder eine Rochade ist, ob ein Zug mit oder ohne Schlagen vorliegt und ob Schach oder sogar Schachmatt gegeben ist und dann das ganze nochmal in der Variante, das ein Bauer umgewandelt wurde. Die ``elif``-Kaskade sieht auch wieder nach copy'n'paste aus.

"Magische" Argumente wie bei `feld_bedroht()`, wo (x,y)==(-1,-1) plötzlich was anderes als Koordinaten bedeuten sind schlecht. Warum gibt's für das Testen auf `Schach` keine eigene Funktion? Die Funktion ist auch viel zu lang. Die Tests für die einzelnen Figuren würde ich in eigene Funktionen auslagern.

Zum Quelltext von `rochade()` fehlen mir gerade die Worte. Ich denke den müsste ich 'ne Woche lang anschauen um ihn zu verstehen. Soo kompliziert ist mir eine Rochade gar nicht in Erinnerung.

In den `test_*()` Funktionen für die Figuren sind auch einige diskussionswürdige verschachtelte `if-else` und Schleifen die das Programm wahrscheinlich langsamer machen als es sein müsste.

`start_zug()` ist wieder reichlich lang und vermischt das freie Setzen von Figuren mit dem normalen Spiel.

Es gibt auch wieder copy'n'paste, das durch einfachere und lesbarere Konstrukte ersetzt werden kann:

Code: Alles auswählen

    if (feld[v1][v2][1]=='B') and (int(feld[v1][v2][0])==(count%2)):
        booli=test_bauer(v1,v2,n1,n2,0,count)
    elif (feld[v1][v2][1]=='T') and (int(feld[v1][v2][0])==(count%2)):
        booli=test_turm(v1,v2,n1,n2,0,count)
    elif (feld[v1][v2][1]=='S') and (int(feld[v1][v2][0])==(count%2)):
        booli=test_springer(v1,v2,n1,n2,0,count)
    elif (feld[v1][v2][1]=='L') and (int(feld[v1][v2][0])==(count%2)):
        booli=test_laufer(v1,v2,n1,n2,0,count)
    elif (feld[v1][v2][1]=='D') and (int(feld[v1][v2][0])==(count%2)):
        booli=test_dame(v1,v2,n1,n2,0,count)
    elif (feld[v1][v2][1]=='K') and (int(feld[v1][v2][0])==(count%2)):
        booli=test_konig(v1,v2,n1,n2,0,count)
    else:
        booli=0
Alles hängt von dem sich immer wiederholenden Teil nach dem ``and`` ab, d.h. diese Bedingung kann man *einmal* am Anfang überprüfen. Und die variablen Teile sind die Figur und die dazugehörige Testfunktion. Die kann man in ein Dictionary stecken und daraus dann auswählen:

Code: Alles auswählen

    tests = { 'B': test_bauer, 'T': test_turm,  'S': test_springer,
              'L': test_laufer, 'D': test_dame, 'K': test_konig }
    
    figur = feld[v1][v2][1]
    farbe = int(feld[v1][v2][0])
    booli = 0
    if farbe == count % 2:
        booli = tests[figur](v1, v2, n1, n2, 0, count)
Ähnlicher Code findet sich in `mouse_click()`.

Noch etwas zur Ineffizienz: Das Programm berechnet viel zu oft alle möglichen Züge von Figuren um auf der einen Seite mögliche Züge und auf der anderen Seite Bedrohungen für die einzelnen Felder zu ermitteln. Effizienter wäre es die Zugmöglichkeiten *einmal* für jede Figur zu ermitteln und zum einen als Liste bei der entsprechenden Figur zu speichern und zum anderen bei jedem Feld zu vermerken, von welchen Figuren es betreten werden kann oder bedroht wird. Dann kann man sofort abfragen, wohin man eine Figur ziehen kann und bei einem Zug braucht man nur die Figuren neu zu berechnen die entweder auf das alte oder das neue Feld ziehen konnten.

Und das Spiel schreit geradezu nach objektorientierter Programmierung.
spooky0815

Hallo BlackJack,

Hab erstmal vielen Dank, dass du dir soviel Zeit nimmst und dir die Mühe machst, das alles zu analysieren.

Hab mir schon fast gedacht (und auch ein bisschen gehofft ;o), dass solche "Killerkommentare" kommen - bei einem Großteil hast du auch recht!

Also mal kurze Kommentare meinerseits dazu (ändern werd ich sowieso das meiste :)

> Das ist aber auch echt schlimm.
Autsch :?

> Sehr viele Zeilen sind zu lang (>80 Zeichen)
Ok...mein Notepad++ hat die Zeilen automatisch umgebrochen..sorry

> Die vielen `from xxx import *`
Bereits erwähnt..werde das schnellstmöglich ändern

> Ausnahmen nur mit ``except:`` behandeln ohne den konkreten Typ
Wollte ich zwecks "Code-Volumen" nicht machen..aber grundsätzlich richtig

> ..Zeichen dafür, das man vielleicht zuviel in einer Funktion...`brett_init()`
naja..gerade diese soll ja zentral jedes Spiel initialisieren

> werden die Variablen `mutex` und `zeile` beispielweise gar nicht benutzt.
Uups... :oops:

> Anstelle von 0 und 1 sollte man `False` und `True`
Da hat mich mein altes C wieder eingeholt...da gabs als Boolean nur 0 und !0 :)

> Dokumentieren mit `docstrings`
Wurde schon teilweise realisiert...

> Bei `callback()` steht im Kommentar, das die Funktion nicht benutzt wird,
> aber falls sie das mal sollte, dann ist der Name `eingabe` undefiniert.
Problem erkannt und erledigt ;)

> Das Wort "Performanz" gibt's im deutschen übrigens nicht.
http://de.wikipedia.org/wiki/Performanz :lol:

> Du mischt Spiellogik mit GUI-Code
stimmt...das ist nun wirklich ein guter Tip!

> Bei der Zeitmessung hast Du `copy'n'paste` Programmierung verwendet
Ja aber bewußt...ich wollte es erst mit Parametern machen, wie du es auch geschrieben hast...leider ist mir bei diesem speziellen Problem keine Lösung eingefallen, da ich ja auf verschiedene "Stopp-variablen" zugreifen muß. Ich versuche ne "schönere" Lösung zu finden.

> In der Funktion `logging()` stecken IMHO zuviele Informationen
Wollte nur die korrekte Schachnotation verwenden
http://de.wikipedia.org/wiki/Schach

> "Magische" Argumente wie bei `feld_bedroht()`
Richtig...hab ich selbst erst im Verlauf der Programmierung gemerkt und als unschön empfunden :(
Da merkt man mal wieder, das ein gut ausgearbeitetes Konzept Gold wert ist...bei mir war es eher nicht der Fall...ich habe immer von Zeit zu Zeit mal weitergeproggt - Naja - Shit happens...

> Zum Quelltext von `rochade()` fehlen mir gerade die Worte.
> Soo kompliziert ist mir eine Rochade gar nicht in Erinnerung.
8) Tja...Rochade ist nicht allzu schwer, aber die Bedingungen, die nötig sind um diese GÜLTIG zu vollziehen, sind echt hässlich:
http://de.wikipedia.org/wiki/Rochade
Ich habe an den Tests der Funktion immer kurz die konkrete Regel als Kommentar genannt...das ganze in Kombination mit der Option des "Brett Drehens - invertieren" wird das ziemlich *würg* :))

> In den `test_*()` Funktionen
Kann sein..ich hoffe aber nicht...hab viel hin und her überlegt und getestet. Naja Fehler sind aber keinesfalls ausgeschlossen.

> `start_zug()` ist wieder reichlich lang und vermischt das freie Setzen von
> Figuren mit dem normalen Spiel.
Muß geändert werden - Danke

> Alles hängt von dem sich immer wiederholenden Teil nach dem ``and``..
Uui..deine Lösung ist wirklich gut..danke!!

> Effizienter wäre es die Zugmöglichkeiten *einmal* für jede
> Figur zu ermitteln
Schon in Arbeit...

> Und das Spiel schreit geradezu nach objektorientierter Programmierung.
Das hab ich befürchtet...ich trauere der guten alten "Old-School-Flat-Programmierung" hinterher B)

jaja...wenn der Tag nur 48h hätte, man nicht auf Arbeit müßte und die Frauenwelt nicht so viel Zeit einnehmen würde :)

Nochmal vielen Dank für die Hinweise...das Forum ist wirklich lobenswert.

Ciaoi

Matthias[/url]
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

spooky0815 hat geschrieben:> Ausnahmen nur mit ``except:`` behandeln ohne den konkreten Typ
Wollte ich zwecks "Code-Volumen" nicht machen..aber grundsätzlich richtig
Ich hab mir deinen Code nicht angesehen... Aber bei der except Geschichte mach ich hin und wieder auch eine Allgemeine Abfrage, allerdings so:

Code: Alles auswählen

try:
    ...irgendwas tolles machen...
except Exception, e:
    print "Ein Fehler ist aufgetreten: %s" % e
    sys.exit()
Man sieht zumindest den Fehlertext...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Hier sind mal alle Namen die Du importierst, aber nie benutzt:
Nur mal interessehalber: wie hast du das rausbekommen? Mit Tools wie PyChecker oder PyLint?
spooky0815 hat geschrieben:> Das Wort "Performanz" gibt's im deutschen übrigens nicht.
http://de.wikipedia.org/wiki/Performanz :lol:
Und welche Art von Perfomanz meinst du an der Stelle? Die Performanz aus der Sprachwissenschaft oder die aus der Soziologie?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

spooky0815 hat geschrieben: > Sehr viele Zeilen sind zu lang (>80 Zeichen)
Ok...mein Notepad++ hat die Zeilen automatisch umgebrochen..sorry
Mein Editor bricht die Zeilen auch um, und rückt die umgebrochenen sogar soweit ein wie den Anfang der überlangen Zeile. Das macht aber nicht jeder Editor und es gibt auch eine Menge anderer Gelegenheiten wo man Quelltext mal zu Gesicht bekommt. Zum Beispiel wenn man sich mal ein `diff` auf der Konsole anschaut. Und da werden solche Monsterzeilen dann schnell nervig.
> ..Zeichen dafür, das man vielleicht zuviel in einer Funktion...`brett_init()`
naja..gerade diese soll ja zentral jedes Spiel initialisieren
Deswegen kann man die ja trotzdem in sinnvolle Unterfunktionen aufteilen. Zum Beispiel das setzen aller Schachfiguren einer Seite könnte man sicher auch auslagern und einmal für Schwarz und einmal für Weiss aufrufen.
> Anstelle von 0 und 1 sollte man `False` und `True`
Da hat mich mein altes C wieder eingeholt...da gabs als Boolean nur 0 und !0 :)
Hm, darum gibt's bei mir dann häufig sowas in der "globalen" Include-Datei:

Code: Alles auswählen

#define TRUE (0==0)
#define FALSE (! TRUE)
> Das Wort "Performanz" gibt's im deutschen übrigens nicht.
http://de.wikipedia.org/wiki/Performanz :lol:
Okay, dann interessiert mich genau wie Leonidas welches von beiden Du meintest. ;-)
> In der Funktion `logging()` stecken IMHO zuviele Informationen
Wollte nur die korrekte Schachnotation verwenden
http://de.wikipedia.org/wiki/Schach
Da hast Du jetzt zuviel vom Zitat gekürzt. Es stecken zu viele Informationen in *einem einzigen* Integer-Wert. Sachen die gar nichts miteinander zu tun haben. In C wäre da ein ``struct`` mit Bitfeldern oder zumindest symbolische Konstanten die man mit `&` und `|` maskiert, fällig gewesen. Aber ein Objekt mit verschiedenen Attributen für die einzelnen Informationen wäre auch nicht schlecht.
> Zum Quelltext von `rochade()` fehlen mir gerade die Worte.
> Soo kompliziert ist mir eine Rochade gar nicht in Erinnerung.
8) Tja...Rochade ist nicht allzu schwer, aber die Bedingungen, die nötig sind um diese GÜLTIG zu vollziehen, sind echt hässlich:
http://de.wikipedia.org/wiki/Rochade
Ich habe an den Tests der Funktion immer kurz die konkrete Regel als Kommentar genannt...das ganze in Kombination mit der Option des "Brett Drehens - invertieren" wird das ziemlich *würg* :))
Okay dann hatte ich die Rochade fast richtig in Erinnerung. Regel 4 war mir nicht geläufig. Aber die Regeln sind trotzdem alle einfacher zu verstehen als der Quelltext den Du dafür geschrieben hast. Das lässt sich einfache und schöner schreiben. Auf jeden Fall wenn Du andere Datenstrukturen nimmst, also zum Beispiel wenn bei jedem Feld gespeichert wird, von welchen Figuren es gerade bedroht wird.

Und die Info ob eine Figur bewegt wurde, würde ich bei der Spielfigur selbst speichern. Das ist schliesslich für über die Hälfte aller Figuren eine interessante Information. Alle Bauern und die Türme und Könige können das gebrauchen.
> In den `test_*()` Funktionen
Kann sein..ich hoffe aber nicht...hab viel hin und her überlegt und getestet. Naja Fehler sind aber keinesfalls ausgeschlossen.
Es geht nicht um Fehler sondern dass es unübersichtlich ist.
> Und das Spiel schreit geradezu nach objektorientierter Programmierung.
Das hab ich befürchtet...ich trauere der guten alten "Old-School-Flat-Programmierung" hinterher B)
Ich dachte Du hast in C programmiert? Da gibt's `struct` um sich zusammengesetzte Datentypen zu schaffen. Eine Spielfigur könnte man da also auch problemlos ungefähr so beschreiben:

Code: Alles auswählen

typedef struct
{
  char row, column;
} Position; 

typedef struct
{
   char type;  /* 'B', 'K', 'D', ... */
   char color; /* 0 / 1 */
   char moved; /* schon bewegt oder nicht? */
   Position position; /* position auf brett */
   Position* possible_moves;  /* Feld von möglichen Zügen */
   ...
} Chessman;
...

Chessman* Chessman_create(char type, char color, Position position)
{
   Chessman* result = malloc(sizeof(Chessman));
   result->type = type;
   result->color = color;
   result->position = position;
   result->moved = FALSE;
   result->possible_moves = NULL;
   ...
   return result;
}
Das sieht doch fast schon wie ein Python-Objekt aus. Nur das man in C keinen "syntaktischen Zucker" für Vererbung bekommt und sich um das Freigeben des Speichers selbst kümmern muss.
BlackJack

Leonidas hat geschrieben:
BlackJack hat geschrieben:Hier sind mal alle Namen die Du importierst, aber nie benutzt:
Nur mal interessehalber: wie hast du das rausbekommen? Mit Tools wie PyChecker oder PyLint?
PyLint war so freundlich die Namen zu verraten. Das gibt am Ende ja immer eine Bewertung à la x/10 Punkten ab. Bisher dachte ich immer das ginge von 0 bis 10 -- das Schachprogramm hat eine -4 Komma irgendwas bekommen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Bisher dachte ich immer das ginge von 0 bis 10 -- das Schachprogramm hat eine -4 Komma irgendwas bekommen.
Ach, Minuswerte hatte ich auch schon. Besonders zu meiner Anfangszeit, wo ich noch nichts vom PEP 8 wusste.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Ulrichs
User
Beiträge: 6
Registriert: Montag 28. November 2005, 12:55
Kontaktdaten:

nicht schlecht aber leider in tk - mit wx wäre es wohl schneller gegangen aber weiter so :)
wofür gibt es Rootserver wenn nicht zum....
[url]http://www.Profilers-online.de[/url]

MfG ULi
ps „Ich sah ein trauriges Gesicht langsam vorüberschweben, dann schlug der Herr auf dem Dach meines Wagens auf.“
Iopodx
User
Beiträge: 68
Registriert: Sonntag 5. September 2004, 08:58

@ Threadersteller. Tu-Chemnitz!? Cool! Kommst du zufällig aus Chems?

MfG
Iopodx
Antworten