![]() |
Sieger-Prüfung "Vier gewinnt"
Hier im Forum kursieren ja die einige Lösungen. Aber keine befriedigt mich so recht.
Ich habe ein 2D Integer Array mit 7 Spalten und 6 Reihen. 0 steht für leer, 1 für Spieler eins und 2 für Spieler zwei. Dürfte Klar sein, denke ich. Mein Problem, wie überprüfe ich am geschicktesten, ob vier einsen oder vier zweien in einer Reihe sind (auch diagonal)? Mein Code Rumpf sieht bisher so aus:
Delphi-Quellcode:
Hat irgendjemand eine clevere Idee, wie man die Inline-Funktionen mit Code füllen könnte?
function TFourInARow.CheckWinner: Boolean;
function CheckRow(r: Cardinal): Boolean; var i: Integer; Prev: Integer; begin result := False; for i := ROWS-1 downto 0 do begin end; end; function CheckColumn(c: Cardinal): Boolean; begin result := False; end; function CheckDiagonal: Boolean; begin result := False; end; var c, r: Integer; FourInARow, FourInAColumn, FourInADiagonal: Boolean; begin for c := 0 to COLUMNS - 1 do begin FourInAColumn := CheckColumn(c); end; for r := 0 to ROWS - 1 do begin FourInARow := CheckRow(r); end; FourInADiagonal := CheckDiagonal; result := FourInAColumn or FourInARow or FourInADiagonal; end; |
Re: Sieger-Prüfung "Vier gewinnt"
Ein Schnellschuss: Die Aktuelle Reihe in einen String konvertieren, und nach den Substrings '1111' oder '2222' mit Pos suchen. Das für je alle möglichen Reihen (bei diagonal fallen ja ein paar weg, wo nicht 4 in eine Reihe passen ;))
Weiss nicht wie gut das ist; war die Idee die mir grad spontan kam. gruss, dizzy |
Re: Sieger-Prüfung "Vier gewinnt"
Das ist gar nicht mal soooo dumm. Aber irgendwie unelegant, finde ich. Da muss es doch was mathematisches geben.
|
Re: Sieger-Prüfung "Vier gewinnt"
wie waers damit?
folgendes mach fuer spieler 1 und 2 getrennt: du laeufst jede zeile ab, hast einen counter den du anfangs auf null setzt. findest du den spieler, erhoehst du die zahl um 1, ansonsten setz sie zurueck auf 0. wenn am ende 4 rauskommt hast du 4 in einer reihe. das gleiche kannst mit jeder spalte machen und noch diagonal. |
Re: Sieger-Prüfung "Vier gewinnt"
ich würde etwas in dieser Art verwenden:
Delphi-Quellcode:
(Analog dazu CheckColumn)
Function CheckField(Const Field : Array Of Array Of Byte;Const SameCoinCount : Byte) : Byte;
// Return value: 0 or ID of winning player Function CheckRow(Const Row : Byte) : Byte; Var X, Coin, Count : Byte; Begin X:=0; While (X <= Length(Field[Row]) - SameCoinCount) Do Begin Coin:=Field[Row,X]; If (Coin = 0) Then Begin Inc(X); Continue; end; Count:=1; While (X + Count < Length(Field[Row])) and (Field[Row,X + Count] = Coin) Do Inc(Count); If (Count >= SameCoinCount) Then Begin Result:=Coin; Exit; end; Inc(X,Count); end; Result:=0; end; Var X : Byte; Begin For X:=1 To Length(Field) Do Begin Result:=CheckRow(X - 1); If (Result > 0) Then Exit; end; Result:=0; end; |
Re: Sieger-Prüfung "Vier gewinnt"
Hmmm mathematisch... Hab grad ein wenig meinen Kopf um Vektoren und Matrizen schwirren lassen... aber das einzige was mir einfiel ist gleich der Spielsteinzählung, bzw. noch einiges aufwändiger. (Hatte gedacht: Jede Zeile/Spalte als Vektor betrachten und seine Länge berechnen. Ist die = 2 ... aber halt... ne ist auch Quatsch. Dann würde auch 010111 gewinnen... neee neee.)
Hab auch im Netz nichts gefunden wo sich jemand über die Gewinnbedingung explizit auslässt. Ich mutmaße jetzt einfach mal, dass es keine implizite mathematische Lösung dafür gibt, sondern dass da wohl doch ein uneleganter Algorithmus herhalten muss. So lange du die KI nicht mit verketteten if..then..else machst ist das ja noch locker vertretbar :mrgreen: (Habe auch für mein Tic Tac Toe die Gewinnbedingung für jede Zeile/Spalte/Diagonale einzeln geprüft - weil ich damals schon nix fand :?) gruss, dizzy |
Re: Sieger-Prüfung "Vier gewinnt"
hi luckie!
ich bin jetzt mal ganz radikal: mach das alles in EINE prozedur! alles war du brauchst ist eine weitere information: der ZULETZT gesetzte spielstein! dnhand diesen spielsteins kannst du dann prüfen ob - auf einer seite 3 gleiche - auf einer seite 2 gleiche auf der anderen seite 1 gleicher ("seite" stellvertretend für links/rechts/oben/unten/diagonal --> fertig!
Delphi-Quellcode:
ich hoff ihr versteht wie ich das mein
// Z: Zeile, S: Spalte
function Ist(Spalte, Zeile, Wer: Integer): TRUE; begin // prüfen ob es das Feld gibt und ob es "Wer" (das gleiche) ist end; procedure NeuerSpielsteinGesetzt(S, Z, W); begin ... if (Ist(S-3,Z,W) and Ist(S-2,Z,W) and Ist(S-1,Z,W)) or // nach links (Ist(S+3,Z,W) and Ist(S+2,Z,W) and Ist(S+1,Z,W)) or // nach rechts ... // nach oben/unten/linksoben/rechtsoben... (Ist(S-2,Z,W) and Ist(S-1,Z,W) and Ist(S+1,Z,W)) or // 2 links 1 rechts ... // 2 rechts 1 links, 2 oben 1 unten usw then ShowMessage('Gewonnen mit freundlicher Grüßen von Stefans zugroß geratener If Abfrage ;-)'); end; |
Re: Sieger-Prüfung "Vier gewinnt"
Zitat:
|
Re: Sieger-Prüfung "Vier gewinnt"
So, ich habe jetzt mal w3seeks methode genommen, scheint mir noch am geschicktesten. ASber irgendwo ist da der Wurm drinne. Er findet nur einen Sieger bei der untersten Reihe bzw. bei der recghtesten Spalte. Ich sehe den Wald vor lauter Bäumen nicht mehr:
Delphi-Quellcode:
Und wenn man das noch etwas vereinfachen könnte, wäre ich auch glücklich.
function TFourInARow.CheckWinnerPlayerOne: Boolean;
var c, r: Integer; FourInARow, FourInAColumn, FourInADiagonal: Boolean; cnt: Integer; function CheckRow(r: Cardinal): Boolean; var i: Integer; begin cnt := 0; for i := 0 to COLUMNS-1 do begin if Field[i, r] = 1 then Inc(cnt) end; result := cnt = 4; end; function CheckColumn(c: Cardinal): Boolean; var i: Integer; begin cnt := 0; for i := 0 to ROWS-1 do begin if Field[c, i] = 1 then Inc(cnt) end; result := cnt = 4; end; function CheckDiagonal: Boolean; begin result := False; end; begin for c := 0 to COLUMNS - 1 do begin FourInAColumn := CheckColumn(c); end; for r := 0 to ROWS - 1 do begin FourInARow := CheckRow(r); end; FourInADiagonal := CheckDiagonal; result := FourInAColumn or FourInARow or FourInADiagonal; end; |
Re: Sieger-Prüfung "Vier gewinnt"
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe es jetzt versucht zu vereinfachen, aber ich habe das Gefühl es ist schlimmer geworden und so langsam verliere ich auch die Übersicht. Ich sollte ins Bett gehen. :roll:
Delphi-Quellcode:
Und im Anhang mal das ganze Projekt.
function TFourInARow.CheckWinnerPlayerOne: Boolean;
var cnt: Integer; 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] = 1 then Inc(cnt) end; end; result := cnt = 4; end; function CheckDiagonal: Boolean; begin result := False; end; begin result := CheckRows; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:59 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