![]() |
AW: TicTacToe - Frage zum Programmablauf
Erstmal danke nahpets, dass du dir die Zeit genommen hast mir das zu erklären. Die Gewinn-Abfrage funktioniert jetzt auch. :) Leider ist ein neues Problem aufgetreten: Der Neustart Button hat den Geist aufgegeben. Beim Klicken sagt er, dass eine Zugriffsverletzung vorliegt? Ich habe aus der 3 eine 10 gemacht, da wir ja weiter oben mit 10 Teilen (Beim Kommentar 'Spiel intern und optisch löschen'). & Sorry für die dämlichen Fragereien, aber ich arbeite noch nicht solange mit Delphi :x
Aktueller Code:
Delphi-Quellcode:
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Buttons; type TForm1 = class(TForm) btnX1Y3: TSpeedButton; btnX2Y3: TSpeedButton; btnX1Y2: TSpeedButton; btnX2Y2: TSpeedButton; btnX3Y3: TSpeedButton; btnX3Y2: TSpeedButton; btnX1Y1: TSpeedButton; btnX2Y1: TSpeedButton; btnX3Y1: TSpeedButton; btnNeuesSpiel: TSpeedButton; procedure btnX1Y3Click(Sender: TObject); procedure btnNeuesSpielClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private-Deklarationen } Spielfeld: array[1..3, 1..3] of Byte; Spieler, Starter, Gewinner: Byte; function ErmittelGewinner() : Byte; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} // FELD 1 bis Feld 9 procedure TForm1.btnX1Y3Click(Sender: TObject); var X, Y: Byte; Index: Byte; begin // Ist der Sender überhaupt ein Speedbutton? If not (Sender is TSpeedButton) then Exit; // Ist das Spiel schon vorbei? If Gewinner <> 0 then begin ShowMessage( 'Das Spiel ist bereits vorbei. Bitte starte ein neues Spiel.' ); Exit; end; // Welcher Button wurde gedrückt? X := 90; Y := 90; for Index := 0 to Self.ControlCount - 1 do begin If Sender = Self.Controls[ Index ] then begin X := (Sender as TSpeedButton).Tag mod 10; Y := (Sender as TSpeedButton).Tag div 10; end; end; // Wurde der Button gefunden? if ( X > 3 ) or ( Y > 3 ) then exit; // Ist das gewünschte Feld noch frei? If Spielfeld[ X, Y ] <> 0 then begin ShowMessage( 'Das Feld ist schon besetzt. Bitte wähle ein anderes aus.' ); Exit; end; // Zug optisch ausführen case Spieler of 1: TSpeedButton( Sender ).Caption := 'X'; 2: TSpeedButton( Sender ).Caption := 'O'; else begin ShowMessage( 'Unerwarteter Fehler!' ); Exit; end; end; // Zug intern ausführen Spielfeld[ X, Y ] := Spieler; // Spieler wechseln Spieler := Spieler mod 2 + 1; // Sieger ermitteln Gewinner := ErmittelGewinner(); //ShowMessage( Format( 'Spieler %d hat gewonnen.', [ Gewinner ] ) ); // Entsprechend des Siegers eine Meldung ausgeben case Gewinner of 0: Exit; 1,2: ShowMessage( Format( 'Spieler %d hat gewonnen.', [ Gewinner ] ) ); 3: ShowMessage( 'Das Spiel endet unentschieden.' ); end; end; // NEUES SPIEL procedure TForm1.btnNeuesSpielClick(Sender: TObject); var X, Y: Byte; begin // Spiel intern und optisch löschen for X := 1 to 3 do begin for Y := 1 to 3 do begin Spielfeld[ X, Y ] := 0; TSpeedButton( Self.Controls[Y * 10 + X ] ).Caption := ''; end; end; // Entscheiden, wer die nächste Runde beginnen darf case Gewinner of 1,2: Starter := Gewinner mod 2 + 1; // Der Verlierer startet 0,3: Starter := Starter mod 2 + 1; // Spieler 2 aus der vorherigen Runde ist nun Spieler 1 end; // Vorbereitungen abschließen Spieler := Starter; Gewinner := 0; end; procedure TForm1.FormCreate(Sender: TObject); begin Spieler := 1; Starter := 1; end; function TForm1.ErmittelGewinner() : Byte; var X, Y: Byte; begin // Gewinner ermitteln // Gibt es einen Gewinner auf der Y-Achse? for X := 1 to 3 do begin Result := Spielfeld[ X, 1 ]; if ( Result <> Spielfeld[ X, 2 ] ) or ( Result <> Spielfeld[ X, 3 ] ) then Result := 0; If Result <> 0 then Exit; end; // Gibt es einen Gewinner auf der X-Achse? for Y := 1 to 3 do begin Result := Spielfeld[ 1, Y ]; if ( Result <> Spielfeld[ 2, Y ] ) or ( Result <> Spielfeld[ 3, Y ] ) then Result := 0; If Result <> 0 then Exit; end; // Gibt es diagonal einen Gewinner? (Von Links-Oben nach Rechts-Unten) for Y := 1 to 3 do begin Result := Spielfeld[ 1, 1 ]; if ( Result <> Spielfeld[ 2, 2 ] ) or ( Result <> Spielfeld[ 3, 3 ] ) then Result := 0; If Result <> 0 then Exit; end; // Gibt es diagonal einen Gewinner? (Von Rechts-Oben nach Links-Unten) for Y := 1 to 3 do begin Result := Spielfeld[ 3, 1 ]; if ( Result <> Spielfeld[ 2, 2 ] ) or ( Result <> Spielfeld[ 1, 3 ] ) then Result := 0; If Result <> 0 then Exit; end; // Gibt es noch ein freies Feld? (Das Spiel geht dann noch weiter) for X := 1 to 3 do begin for Y := 1 to 3 do begin if Spielfeld[ X, Y ] = 0 then Exit; end; end; // Es gab bisher keinen Gewinner. Freie Felder gibt es auch nicht mehr. // Das Spiel endet also unentschieden. Result := 3; end; end. |
AW: TicTacToe - Frage zum Programmablauf
Zitat:
|
AW: TicTacToe - Frage zum Programmablauf
Zitat:
EDIT: Habe es grade mit 2 getestet. Leider lässt er 12,13 & 23 so wie sie sind & cleart dafür den Neustart-Speedbutton. EDIT 2: ich habe vom Produkt nochmal 1 abgezogen, damit der neustart Button bleibt. Jetzt werden nur noch 13 & 23 nicht gecleart. :x |
AW: TicTacToe - Frage zum Programmablauf
Dashier ist jetzt so nicht mehr richtig:
Delphi-Quellcode:
Dashier sollte ausreichen:
// Welcher Button wurde gedrückt?
X := 90; Y := 90; for Index := 0 to Self.ControlCount - 1 do begin If Sender = Self.Controls[ Index ] then begin X := (Sender as TSpeedButton).Tag mod 10; Y := (Sender as TSpeedButton).Tag div 10; end; end;
Delphi-Quellcode:
Wir wollen ja, weil es nicht funktioniert, vom Durchlaufen von Self.Controls weg. Die Nutzung der Eigenschaft Tag dient ja genau der Abschaffung dieser fehleranfälligen Vorgehensweise.
X := (Sender as TSpeedButton).Tag mod 10;
Y := (Sender as TSpeedButton).Tag div 10; Wir brauchen durch die Änderung auf die Tag-Nutzung nicht mehr abfragen, welcher Button gedrückt wurde. Der Button teilt uns dies durch den Inhalt von Tag selbst mit. Der Button mit Tag = 11 sagt dadurch letztlich: "Ich bin der Butten von unten links." Der Button mit Tag = 33 sagt uns: "Ich bin der Button von oben rechts." Mit Tag mod 10 bzw. Tag div 10 wird der zweistellige Wert von Tag auf X und Y "verteilt", also in die jeweiligen Koordinaten umgerechnet. |
AW: TicTacToe - Frage zum Programmablauf
Ist erledigt. Trotzdem wird weiterhin 13 & 23 nicht gecleart.
|
AW: TicTacToe - Frage zum Programmablauf
Dieses ist so nicht korrekt, die "geographische" Lage der Buttons hat sich durch die Nutzung von Tag und die geänderten Namen nicht verändert.
Delphi-Quellcode:
Hier würd' ich es mal so versuchen:
for X := 1 to 3 do
begin for Y := 1 to 3 do begin Spielfeld[ X, Y ] := 0; TSpeedButton( Self.Controls[Y * 10 + X ] ).Caption := ''; end; end;
Delphi-Quellcode:
(Ist jetzt nur ungetestet hingedaddelt. Schreibfehler (wie immer) nicht ausgeschlossen.)
for X := 1 to 3 do for Y := 1 to 3 do Spielfeld[X,Y] := 0;
for X := 0 to Self.Controls.Count - 1 do begin if Self.Controls[X] is TSpeedButton then begin if TSpeedButton(Self.Controls[X]).Tag <> 0 then TSpeedButton(Self.Controls[X]).Caption := ''; end; end; |
AW: TicTacToe - Frage zum Programmablauf
Liste der Anhänge anzeigen (Anzahl: 1)
Hmm..
Hab mir deinen Source genommen.. - Den Startbutton aber als TBitBtn - Den Speedbuttons einen Tag von 0-9 verpasst - Entsprechende Stellen umgestellt oder bereinigt Und siehe da dein Basis-Code läuft. |
AW: TicTacToe - Frage zum Programmablauf
@nahpets: Danke, jetzt geht es :) & nochmals danke für die guten Erklärungen.
@Holger: Danke auch an dich. Ich werde mir den Code gleich anschauen :) @ALLE: Danke für eure hilfreichen Antworten und Lösungsansätze. PS: Ich habe noch ein Problem, um das ihr euch kümmern könnt, zudem ich nachher einen Thread erstellen werde ^^ (Geht um ein anderes Spiel) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:16 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