![]() |
AW: TicTacToe - Frage zum Programmablauf
Ich habe es jetzt nochmal ausführlich getestet. Dabei ist mir aufgefallen, dass es manchmal funktioniert und manchmal nicht. Leider bin ich nicht in der Lage die Ursache zu finden, die fürs funktionieren/nicht funktionieren verantwortlich ist. Ich denke aber es liegt an gesagtem ControlCount. Leider weiß ich nicht, wie ich das Programm debuggen soll. In der Starter Edition ist die Debug Option leider nicht enthalten :/
|
AW: TicTacToe - Frage zum Programmablauf
Dann setz doch mal zur Überprüfung an verschiedenen Stellen Showmessage()-Boxen, welche die aktuellen Variableninhalte oder sonst was ausgeben.
So mache ich das immer, obwohl ich einen Debugger habe. |
AW: TicTacToe - Frage zum Programmablauf
Nachdem ich jetzt mal 'ne Weile mit der EXE rumgespielt habe, bin ich mir fast sicher, dass das interne Spielfeld hier
Delphi-Quellcode:
anders befüllt wird, als die optische Darstellung der Captions suggeriert.
Spielfeld[ X, Y ] := Spieler;
Um das zu prüfen, solltest Du zuerst mal mit dem Debugger schauen, was genau passiert. (Sorry, hatte den Hinweis, auf des Fehlen des Debuggers, irgendwie nicht wahrgenommen :-() Dort, wo Du dem Anwender das Ergebnis per ShowMessage anzeigst, könntest Du auch mal das Spielfeld ausgeben. Das könnte mit 'nem weiteren ShowMessage passieren:
Delphi-Quellcode:
(Hoffentlich hab' ich hier jetzt nicht X und Y vertauscht.)
ShowMessage(Format('%d %d %d',[SpielFeld[0,0],SpielFeld[1,0],SpielFeld[2,0]) + #13
+ Format('%d %d %d',[SpielFeld[0,1],SpielFeld[1,1],SpielFeld[2,1]) + #13 + Format('%d %d %d',[SpielFeld[0,2],SpielFeld[1,2],SpielFeld[2,2])); Die Anzeige sollte mit der Darstellung der Speedbutton-Captions übereinstimmen. Wenn nicht, stimmt die erwartete Reichenfolge der Speedbuttons in Self.Controls nicht mit der tatsächlichen überein. Anders kann ich mir die etwas chaotische Ergebnisermittlung, mit kaum einem richtigen Ergebnis, nicht vorstellen. |
AW: TicTacToe - Frage zum Programmablauf
Zitat:
|
AW: TicTacToe - Frage zum Programmablauf
Nimm einfach die Tag-Eigenschaft und schreib da die Koordinaten rein so wie das in #4 steht!
Die Erstellreihenfolge hat genau NICHTS mit deiner Anordnung der Buttons zu tun... |
AW: TicTacToe - Frage zum Programmablauf
Sofern ich mich nicht ganz falsch erinnere, hat die Starter durchaus einen Debugger, nur wurden einem Variableninhalte nicht beim Mouseover angezeigt, sondern diese mussten zu den überwachten Ausdrücken hinzugefügt werden. Haltepunkte setzen, durchsteppen etc. funktionierte aber ganz normal.
|
AW: TicTacToe - Frage zum Programmablauf
Schnellschuss ins Blaue:
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TPlayer = (pX = -1, pNobody = 0, pO = 1); TForm1 = class(TForm) Button11: TButton; Button12: TButton; Button13: TButton; Button21: TButton; Button22: TButton; Button23: TButton; Button31: TButton; Button32: TButton; Button33: TButton; ButtonNewGame: TButton; LabelCurrentPlayer: TLabel; procedure ButtonClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ButtonNewGameClick(Sender: TObject); private fCurrentPlayer, fLastWinner: TPlayer; dFrom13To31, dFrom11To33, FMoves: Integer; fZeilen, fSpalten: array[1..3] of Integer; procedure NewGame; procedure NextPlayer; procedure ResetPlayground; procedure UpdateStatus; function IsGameOver: Boolean; procedure DisablePlayground; public end; var Form1: TForm1; implementation uses TypInfo; {$R *.dfm} procedure TForm1.ButtonClick(Sender: TObject); var btn: TButton; x, y: Integer; begin if (Assigned(Sender)) and (Sender is TButton) then begin Inc(FMoves); btn := TButton(Sender); case fCurrentPlayer of pX: btn.Caption := 'X'; pO: btn.Caption := 'O'; end; btn.Enabled := false; x := btn.Tag mod 10; y := btn.Tag div 10; Inc(fSpalten[x], Ord(fCurrentPlayer)); Inc(fZeilen[y], Ord(fCurrentPlayer)); if (x = y) then begin Inc(dFrom11To33, Ord(fCurrentPlayer)); if (x = 2) then Inc(dFrom13To31, Ord(fCurrentPlayer)); end else begin if (Abs(x - y) = 2) then Inc(dFrom13To31, Ord(fCurrentPlayer)); end; // Gewinner ermitteln if (IsGameOver) then begin DisablePlayground; case fLastWinner of pX: ShowMessage('Winner is X'); pO: ShowMessage('Winner is O'); pNobody: ShowMessage('draw'); end; Exit; end; NextPlayer; end; end; function TForm1.IsGameOver: Boolean; var i: Integer; begin Result := False; for i := 1 to 3 do begin Result := Result or (Abs(fSpalten[i]) = 3) or (Abs(fZeilen[i]) = 3); end; Result := Result or (Abs(dFrom13To31) = 3) or (Abs(dFrom11To33) = 3); if (Result) then begin fLastWinner := fCurrentPlayer end else if (FMoves = 9) then begin Result := True; fLastWinner := pNobody; end; end; procedure TForm1.FormCreate(Sender: TObject); begin fCurrentPlayer := pX; fLastWinner := pNobody; NewGame; end; procedure TForm1.NewGame; begin ResetPlayground; NextPlayer; end; procedure TForm1.DisablePlayground; var i: Integer; begin for i := 0 to Self.ControlCount - 1 do begin if (Self.Controls[i] is TButton) and (TButton(Self.Controls[i]).Tag > 0) then begin TButton(Self.Controls[i]).Enabled := false; end; end; end; procedure TForm1.ResetPlayground; var i: Integer; begin FMoves := 0; for i := 0 to Self.ControlCount - 1 do begin if (Self.Controls[i] is TButton) and (TButton(Self.Controls[i]).Tag > 0) then begin TButton(Self.Controls[i]).Caption := EmptyStr; TButton(Self.Controls[i]).Enabled := true; end; end; for i := Low(fSpalten) to High(fSpalten) do fSpalten[i] := 0; for i := Low(fZeilen) to High(fZeilen) do fZeilen[i] := 0; dFrom13To31 := 0; dFrom11To33 := 0; end; procedure TForm1.NextPlayer; begin if (fLastWinner = pNobody) then begin fCurrentPlayer := TPlayer(Ord(fCurrentPlayer) * -1) end else begin fCurrentPlayer := TPlayer(Ord(fLastWinner) * -1); fLastWinner := pNobody; end; UpdateStatus; end; procedure TForm1.UpdateStatus; begin case fCurrentPlayer of pX: LabelCurrentPlayer.Caption := 'current player: X'; pO: LabelCurrentPlayer.Caption := 'current player: O'; end; end; procedure TForm1.ButtonNewGameClick(Sender: TObject); begin NewGame; end; end.
Delphi-Quellcode:
object Form1: TForm1
Left = 414 Top = 203 BorderStyle = bsToolWindow Caption = 'TicTacToe' ClientHeight = 264 ClientWidth = 201 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object LabelCurrentPlayer: TLabel Left = 8 Top = 8 Width = 67 Height = 13 Caption = 'current player:' end object Button11: TButton Tag = 11 Left = 8 Top = 32 Width = 57 Height = 57 TabOrder = 0 OnClick = ButtonClick end object Button12: TButton Tag = 12 Left = 72 Top = 32 Width = 57 Height = 57 TabOrder = 1 OnClick = ButtonClick end object Button13: TButton Tag = 13 Left = 136 Top = 32 Width = 57 Height = 57 TabOrder = 2 OnClick = ButtonClick end object Button21: TButton Tag = 21 Left = 8 Top = 96 Width = 57 Height = 57 TabOrder = 3 OnClick = ButtonClick end object Button22: TButton Tag = 22 Left = 72 Top = 96 Width = 57 Height = 57 TabOrder = 4 OnClick = ButtonClick end object Button23: TButton Tag = 23 Left = 136 Top = 96 Width = 57 Height = 57 TabOrder = 5 OnClick = ButtonClick end object Button31: TButton Tag = 31 Left = 8 Top = 160 Width = 57 Height = 57 TabOrder = 6 OnClick = ButtonClick end object Button32: TButton Tag = 32 Left = 72 Top = 160 Width = 57 Height = 57 TabOrder = 7 OnClick = ButtonClick end object Button33: TButton Tag = 33 Left = 136 Top = 160 Width = 57 Height = 57 TabOrder = 8 OnClick = ButtonClick end object ButtonNewGame: TButton Left = 8 Top = 224 Width = 185 Height = 25 Caption = 'neues Spiel' TabOrder = 9 OnClick = ButtonNewGameClick end end |
AW: TicTacToe - Frage zum Programmablauf
Liste der Anhänge anzeigen (Anzahl: 1)
Hab mal die Ausgabe als Screen hochgeladen. Da ist deutlich ersichtlich, dass die Positionen nicht stimmen (wie bereits von euch gesagt). Ich möchte aber nicht einfach copy & pasten, also wäre es super, wenn jemand die Zeit/Lust hätte mir das mit den Tags so zu erklären, dass ich es verstehe & selbst einbauen kann.:oops::|
|
AW: TicTacToe - Frage zum Programmablauf
Wenn Du Dein Spielfeld als Array[0..2, 0..2] of TSpeedButton deklarierst und entsprechend befüllst, kannst Du doch direkt auf den jeweiligen SpeedButton zugreifen und dort in dessen Tag-Eigenschaft schreiben bzw. daraus lesen. Das ist zwar das genaue Gegenteil von Trennung von Logik und Darstellung, macht die Sache aber viel einfacher IMO.
|
AW: TicTacToe - Frage zum Programmablauf
Zitat:
Beispiel: Der Speedbutton unten links bekommt den Namen btnX1Y1. Der unten in der Mitte btnX2Y1 und unten rechts der btnX3Y1. Als Tag gibst Du jeweils die beiden Ziffern aus dem Namen ein, also unten links Tag = 11, unten in der Mitte Tag = 21 und unten rechts Tag = 31. Analog dann auch die übrigen Speedbuttons. Den Speedbutton 10 benennst Du z. B. btnNeuesSpiel. Danach übernimmst Du den Vorschlag von himitsu aus Post ![]() Wenn ich jetzt nicht zusehr um die Ecke gedacht habe, könnte es dann schon funktionieren. Die Eigenschaft Tag ist eigentlich nichts weiter als ein Integer, der grundsätzlich erstmal für nix benötigt wird. Die Eigenschaft lässt sich aber gut für die Zuordnung von nummerischen Werten, die im Programmablauf benötigt werden, "missbrauchen". Anstatt abzufragen: "Wurde SpeedbuttonX gedrückt" (oder gar den gedrückten Button erst in einer Liste (Self.Controls) zu suchen), kann man hier halt den nummerischen Wert abfragen. Und wenn man den beim Programmdesign so wählt, dass er sich in die Programmlogik einfügt, kann man sich damit sehr viel Arbeit ersparen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:46 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