Moin!
Mein letzter Beitrag ist ja nun schon etwas länger her; hatte leider zwischendurch nur sehr wenig Zeit (wird auch noch was so bleiben...

); egal, da aber hier noch etwas offen war, hier die Antwort:
| Zitat: |
doch der Fall kann und darf eintreten, guckst du hier:
somit wurde die gewinnbedinung zweimal erfüllt |
OK, hab mich nicht korrekt genug ausgedrückt, klar, bei deinem Beispiel ist die Gewinnbedingung doppelt erfüllt, aber vom GLEICHEN Spieler. Ich meinte aber - da es in deinem Code möglich ist, weiterzuspielen, obwohl bereits jemand gewonnen hat - dass die ERSTE erfüllte Bedingung das Spiel abbrechen muss. Und da es nicht möglich ist, dass nach einem neuen Stein sowohl Rot als auch Blau gewonnen haben, sollte das eigentlich klar gewesen sein.
Zurück zu dem eigentlichen Problem an dieser Stelle: Du hast behauptet, es dürften nicht zwei Gewinnbedingungen gleichzeitig zutreffen; ja aber warum denn nicht? Klar darf das (siehe dein Beispiel), oder nochmal als Code:
Delphi-Quelltext
1:
| Win:= HCheck(Player) or VCheck(Player) or DCheck(Player); |
Das war mein Vorschlag für die Auswertung der Gewinnbedingung, du hast als letztes diesen Code verwendet:
Delphi-Quelltext
1: 2: 3: 4:
| Win:= false; if win = false then Win:= HCheck(Player); if win = false then Win:= VCheck(Player); if win = false then Win:= DCheck(Player); |
Von der Logik ist der Code identisch, nur dass meiner effizienter ist.

Du sagst, es dürfe nicht zweimal die Gewinnbedingung zutreffen, deshalb verwendest du wohl die IF-Anweisungen. Ich möchte dir hier aber vorführen, dass das unerheblich ist:
Ich habe mal den von dir zitierten Fall (doppelte Gewinnbedingung) als Funktionswerte in den Code eingefügt. Spielen wir mal den Fall durch: Du setzt Win := FALSE, die folgende IF-Bedingung ist also immer erfüllt und damit überflüssig, du könntest also direkt schreiben:
Delphi-Quelltext
1: 2: 3:
| Win:= HCheck(Player); if win = false then Win:= VCheck(Player); if win = false then Win:= DCheck(Player); |
Damit erhält Win den Wert TRUE (aus HCheck()), die nächste IF-Anweisung würde nicht ausgeführt. Wir wollen aber mal annehmen, dass dort kein IF steht, sondern ein "or" (wie in meinem Code). Somit wird Win auf (TRUE or TRUE) = TRUE gesetzt. Wir denken uns das 3. IF auch durch ein "or" ersetzt und Win erhält (TRUE or FALSE) = TRUE zugewiesen, das Endergebnis. Zusammengefasst: für das Beispiel bewertet lautet der Code:
Delphi-Quelltext
1:
| Win:= TRUE or TRUE or FALSE; |
Und damit wäre bewiesen, dass mehrfache Gewinnbedingungen überhaupt kein Problem darstellen, du nur mit den IF-Anweisungen das "or" nachbaust.
Allerdings bezog sich mein erster Verbesserungsvorschlag (und die Aussage, dass der Code falsch sei) auf einen früherern Entwurf dieses Codes, wo du sowas hier gemacht hast:
Delphi-Quelltext
1: 2: 3: 4:
| Win:= false; Win:= HCheck(Player); Win:= VCheck(Player); Win:= DCheck(Player); |
und das ist nunmal falsch, das gibt es nix zu rütteln, da praktisch nur das Ergebnis von DCheck() Wirkung zeigt.
| F34r0fTh3D4rk hat folgendes geschrieben: |
| du hast mir aber darauf geantwortet bevor ich den fehler behoben habe |
Jau, da haben wir wohl aneinander vorbeigeredet, ausgelöst durch zeitliche Überscheidung; das "not case of" war tatsächlich eine Berichtigung von dir, bevor ich es schrieb und somit ist meine Aussage diesbezüglich hinfällig.
| F34r0fTh3D4rk hat folgendes geschrieben: |
| Gib schon zu, du hast einen Fehler erkannt, der garnet da war |
Bezogen auf die Bewertung von "Win" (s.o.) bist du allerdings selber "schuld", denn du hast erst nach meinem Beitrag die "richtige Unit" gepostet...

das kann ich dann natürlich nicht (vorher-)sehen und habe (völlig korrekt) den Fehler in der Win-Bewertung beschrieben.
Nun, egal, einigen wir uns diesbezüglich auf "dumm gelaufen". Ändert aber nix daran, dass dein Code funktionell meinem Vorschlag entspricht (obwohl ich noch nichts von deiner Änderung wissen konnte), nur umständlicher...
| F34r0fTh3D4rk hat folgendes geschrieben: |
| muss ja nicht sein wenns auch sparender geht, lieber die procedure 1 mal korrekt laufen lassen, als einmal zuviel ohne sinn, dass dabei was rauskommt |
Langsam, bitte aufmerksam meinen Vorschlag lesen und deinen Code begutachten: Ich sagte, eine Funktion schreiben, die unabhängig vom aktuellen Spieler ermittelt, ob ein Spieler gewonnen hat. Folglich muss diese Funktion nur EIN MAL nach jedem Zug ausgeführt werden; du machst in deinem Code praktisch das gleiche, aber abhängig vom Spieler und mußt so den "richtigen Spieler"-Fall noch berücksichtigen (was bei dir ja auch zu einem Problem geführt hat; siehe "dumm gelaufen"), was bei einer spielerunabhängigen Bewertung nicht nötig wäre (und auch nur einmal ausgeführt wird -> siehe mein Code!). Insofern hat die spielerunabhängige Variante deutlich Vorteile, aber keine Nachteile.
Abschließend zu deinem aktuellen Code: Man kann immernoch weiterspielen, obwohl bereits jemand gewonnen hat; dann gibt es natürlich Probleme mit den Gewinnbedingungen. Vielleicht ist dir in einem meiner letzten Postings der Vorschlag entgangen, dass man im Gewinn-Fall einfach alle able[] auf FALSE setzt, damit man keine Steine mehr setzen kann?
Jetzt zu den binären Operatoren. Zunächst die Definition der logischen Operatoren:
Quelltext
1: 2: 3: 4: 5: 6: 7:
| and or not A|B|A^B A|B|AvB A|!A ------- ------- ---- 0|0| 0 0|0| 0 0| 1 0|1| 0 0|1| 1 1| 0 1|0| 0 1|0| 1 1|1| 1 1|1| 1 |
Bis hierhin vielleicht noch keine ergreifende Erkenntnis (das wußtest du sicher auch schon). Was du möglicherweise noch nicht gewußt hast, ist, dass man diese Operatoren auch sozusagen "am Stück" auf die binäre Darstellung eines Integers anwenden kann. Ein Integer ist eine 32-Bit-Zahl (in Delphi), also eine "Reihe" von 32 0en oder 1en. Wenn man nun folgendes tut:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var a,b, a_and_b, a_or_b: Integer;
a := 3; b := 1; a_and_b := a and b; a_or_b := a or b; |
und dabei die Integers binär betrachtet, dann werden die logischen Operatoren auf die einzelnen Bits in den Integern angewendet. Wir betrachten mal nur die letzten 4 Bits der Ergebnisvariablen oben:
Quelltext
1: 2: 3:
| a: 0011 0011 b: 0001 0001 a_and_b: 0001 a_or_b: 0011 |
Ich hoffe, damit ist klar, was da passiert; NOT dürfte klar sein, einfach alle Bits "umdrehen".
Auf deinen Anwendungsfall bezogen, machst du da sowas (hab jetzt mal direkt die möglichen Werte genommen):
Quelltext
1: 2: 3: 4: 5: 6:
| Fall-A: (1 and 1 and 1) = 1 -> (01 and 01 and 01) = 01 01 = 01 wahr Fall-B: (1 and 1 and 2) = 1 -> (01 and 01 and 10) = 01 00 = 01 falsch |
Wie man sieht, geht das in deinem Fall (weil nur 1 und 2 vorkommen) gut.
Ich möchte, zum besseren Verständnis, aber nochmal das "Problem" verdeutlichen: Es ging darum, dass
Quelltext
äquivalent zu
Quelltext
1:
| (a = 1) and (b = 1) and (c = 1) |
sein soll, was allgemein FALSCH ist! Beweis:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| a := 1; b := 1; c := 3; (1 and 1 and 3) = 1 (binär)-> (01 and 01 and 11) = 01 (1 = 1) and (1 = 1) and (3 = 1) |
Ich hoffe das war verständlich.
cu
Narses