![]() |
Re: Sieger-Prüfung "Vier gewinnt"
Code:
das sollte >= 4 sein, hab das wort mindestens vergessen. Ich glaub nicht dass man das in eine funktion ohne es total unuebersichtlich zu machen, zusammenfassen kann. Ich wuerde jede zeile und jede spalte checken, und dann noch die diagonalen bei denen mind 4 felder sind. das sollte eigentlich genuegen.
result := cnt = 4;
Allerdings find ich auch den Ansatz von StefanDP ganz gut, setzt allerdings voraus dass man dies beim aendern eines Feldes immer prueft, wenn ein fertiges spielfeld vor liegt, wird man das nicht erkennen. |
Re: Sieger-Prüfung "Vier gewinnt"
Äh, ja. Aber wenn in der zweiten Reihe von unten dann 3 sind hat Spieler eins auch gewonnen. Probier es mal aus.
|
Re: Sieger-Prüfung "Vier gewinnt"
Code:
wie gesagt musst du den counter auf null setzen wenn das feld nicht vom gesuchten spieler ist
for i := 0 to COLUMNS-1 do
begin if Field[i, r] = 1 then Inc(cnt) else cnt := 0; end; [edit] und natuerlich auch fuer jede zeile und spalte wieder auf null setzen [/edit] |
Re: Sieger-Prüfung "Vier gewinnt"
Ein Problem sehe ich: Eine Zeile/Spalte der Form: 0 1 1 0 0 1 1 würde zu cnt=4 = true führen, obwohl das ja kein Sieg wäre. Es müssen ja nicht nur 4 Steine in einer Zeile/Spalte/Diag. sein, sondern die müssen auch noch lückenlos sein.
Delphi-Quellcode:
function CheckRows: Boolean;
var c, r: Integer; begin cnt := 0; for c := 0 to COLUMNS-1 do begin for r := 0 to ROWS-1 do begin if (Field[c, r] = 0) and (cnt > 0) then // bei Unterbrechung durch '0' zurück setzen! cnt := 0 else if Field[c, r] = 1 then Inc(cnt); end; end; result := cnt = 4; end; \\edit: *gnarf* 1.: zu langsam; 2.: nicht so elegant wie w3seek... naja ;) |
Re: Sieger-Prüfung "Vier gewinnt"
@dizzy: jetzt funktioniert gar nichts mehr. Ich habe ja das Projekt angehangen, ihr könnte da ja eure Idee ausprobieren. Ich lass das erstmal liegen für heute und gehe ins Bett, glaube ich.
|
Re: Sieger-Prüfung "Vier gewinnt"
SO! Jetzt aber. Das Problem war, dass die Schleife immer bis zum Ende durchlief. Daher fand sie auch NUR Siegbedingungen im letzten Durchgang. Lösung: Ein nicht so schönes, aber wirkungsvoll angebrachtes "exit".
Delphi-Quellcode:
(Getestet!)
function CheckRows: Boolean;
var c, r: Integer; begin for r := 0 to ROWS-1 do begin cnt := 0; for c := 0 to COLUMNS-1 do begin if Field[c, r] <> 1 then cnt := 0 else inc(cnt); if cnt = 4 then begin result := true; exit; end; // if cnt=4 end; // for c... end; // for r... result := false; end; // CheckRows Für CheckColumns einfach die beiden Schleifenköpfe gegeneinander austauschen, und für Diagonal reicht mein Hirnschmalz heute auch net mehr :) btw: für ein CheckRows waren die Schleifen ohnehin schon falsch herum verschachtelt! Eigentlich war's schon die CheckColumns :zwinker:. btw2: das "exit" könnte man jetzt noch umgehen, in dem man das ganze in repeat-until-Schleifen packt, und bei cnt=4 nen Flag setzt. Ist aber imho in diesem Fall nicht viel leichter lesbar, und zu dem weniger performant. n8i, dizzy |
Re: Sieger-Prüfung "Vier gewinnt"
Ok, hier mein Algorithmus:
Delphi-Quellcode:
Ich habs nicht ausgiebig getestet, aber sollte funktionieren
function Gewonnen(Spieler: Byte): Boolean;
const N_ZEILEN = 6; N_SPALTEN = 7; N_GEWINNT = 4; Spielfeld: array[0..N_ZEILEN-1] of array[0..N_SPALTEN-1] of Cardinal = ( (0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0) ); function GewinntZeile(Zeile: Integer): Boolean; var c, i: Integer; begin Result := false; c := 0; // wir pruefen alle punkte in dieser zeile for i := 0 to N_SPALTEN - 1 do begin // hat der spieler hier einen punkt? if Spielfeld[Zeile][i] = Spieler then begin // wir zaehlen unseren counter hoch Inc(c); if c = N_GEWINNT then begin // wir haben N_GEWINNT aufeinanderfolgendende punkte des spielers, er hat somit gewonnen! Result := true; Exit; end; end else begin // dieser punkt ist nicht gesetzt oder gehoert nicht dem spieler! Wir setzen den counter auf 0 // da die reihe unterbrochen wurde c := 0; end; end; end; function GewinntSpalte(Spalte: Integer): Boolean; var c, i: Integer; begin Result := false; c := 0; // wir pruefen alle punkte in dieser spalte for i := 0 to N_ZEILEN - 1 do begin // hat der spieler hier einen punkt? if Spielfeld[i][Spalte] = Spieler then begin Inc(c); if c = N_GEWINNT then begin // wir haben N_GEWINNT aufeinanderfolgendende punkte des spielers, er hat somit gewonnen! Result := true; Exit; end; end else begin // dieser punkt ist nicht gesetzt oder gehoert nicht dem spieler! Wir setzen den counter auf 0 // da die reihe unterbrochen wurde c := 0; end; end; end; function GewinntDiagonal(Zeile, Spalte, Delta: Integer): Boolean; var Anfang, Pos, Ende: PCardinal; c: Integer; begin Result := false; // wir holen uns die adresse des punktes von dem aus wir das spielfeld betrachten, das ist der linke bzw obere spielrand Pos := @Spielfeld[Zeile, Spalte]; // wir holen uns die adressen der punkte ueber bzw unter die wir nicht gehen duerfen Anfang := @Spielfeld[0, 0]; Ende := @Spielfeld[N_ZEILEN - 1][N_SPALTEN - 1]; c := 0; // diese schleife so lange ausfuehren bis die aktuelle position ausserhalb des spielfelds gesetzt wurde while (Cardinal(Pos) <= Cardinal(Ende)) and (Cardinal(Pos) >= Cardinal(Anfang)) do begin // ist der gesuchte spieler an der aktuellen stelle? if Pos^ = Spieler then begin // wir zaehlen hoch, wie viele punkte hintereinander schon ohne unterbrechnung waren Inc(c); if c = N_GEWINNT then begin // ok, wir haben genau N_GEWINNT punkte in folge, der spieler hat gewonnen! Result := true; Exit; end; end else begin // ok, der punkt ist nicht gesetzt oder gehoert nicht zu dem gesuchten spieler, wir setzen den counter zurueck c := 0; end; // wir springen zum naechsten punkt der getestet wird. je nachdem in welche richtung wir gehen und wie weit, gibt delta an. Inc(Pos, Delta); end; end; var i: Integer; begin Result := false; // wir laufen von der linken oberen spielecke zur linken unteren spielecke for i := 0 to N_ZEILEN - 1 do begin // sind in dieser zeile 4 aufeinanderfolgende punkte des spielers? if GewinntZeile(i) or // -(N_SPALTEN - 1) ist der abstand zum naechsten punkt der rechts oben (diagonal) liegt, der abstand ist // also negativ und um 1 geringer als das spielfeld spalten hat GewinntDiagonal(i, 0, -(N_SPALTEN - 1)) or // N_SPALTEN + 1 ist der abstand zum naechsten punkt rechts unten (diagonal), der abstand ist also positiv // und um 1 groesser als das spielfeld spalten hat GewinntDiagonal(i, 0, N_SPALTEN + 1) then begin Result := true; Exit; end; end; // wir laufen von der linken oberen zur rechten oberen spielecke for i := 0 to N_SPALTEN - 1 do begin // sind in dieser spalte 4 aufeinanderfolgende punkte des spielers? if GewinntSpalte(i) or // N_SPALTEN + 1 ist der abstand zum naechsten punkt unterhalb und rechts von diesem punkt, also um 1 groesser // als das spielfeld spalten hat GewinntDiagonal(0, i, N_SPALTEN + 1) or // N_SPALTEN - 1 ist der abstand zum naechsten punkt unterhalb und links von diesem punkt, also um genau 1 kleiner // als das spielfeld spalten hat GewinntDiagonal(0, i, N_SPALTEN - 1) then begin Result := true; Exit; end; end; end; [edit] kleiner fix, es sollte glaub ich "while (Cardinal(Pos) <= Cardinal(Ende)) and (Cardinal(Pos) >= Cardinal(Anfang)) do" statt "while (Cardinal(Pos) < Cardinal(Ende)) and (Cardinal(Pos) >= Cardinal(Anfang)) do" sein [/edit] |
Re: Sieger-Prüfung "Vier gewinnt"
Oh Gott, wie kommt das den bei mir da jetzt rein? Ich glaube, das muss ich mir noch mal richtig zu Gemühte führen.
|
Re: Sieger-Prüfung "Vier gewinnt"
Zitat:
|
Re: Sieger-Prüfung "Vier gewinnt"
Hm, w3seeks Code kompiliert, tut nur nicht das, was ich will. :gruebel:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz