AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TicTacToe - Frage zum Programmablauf

Ein Thema von ShadowDeath · begonnen am 11. Apr 2017 · letzter Beitrag vom 12. Apr 2017
Antwort Antwort
ShadowDeath

Registriert seit: 11. Apr 2017
10 Beiträge
 
#1

TicTacToe - Frage zum Programmablauf

  Alt 11. Apr 2017, 20:18
Hallo Leute,
ich hoffe ihr könnt mir helfen, denn ich habe versucht ein TicTacToe zu programmieren doch irgendwie funktioniert es nicht ganz so wie es soll. Um genau zu sein scheint die Gewinner Abfrage nicht zu funktionieren, doch ich finde den Fehler einfach nicht. Hoffentlich kann mir jemand von euch helfen PS: Ich habe das game unten als Zip angehangen.



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)
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton4: TSpeedButton;
    SpeedButton5: TSpeedButton;
    SpeedButton3: TSpeedButton;
    SpeedButton6: TSpeedButton;
    SpeedButton7: TSpeedButton;
    SpeedButton8: TSpeedButton;
    SpeedButton9: TSpeedButton;
    SpeedButton10: TSpeedButton;
    procedure SpeedButton1Click(Sender: TObject);
    procedure SpeedButton10Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);

  private
    { Private-Deklarationen }
    Spielfeld: array[0..2, 0..2] 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.SpeedButton1Click(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 := Index mod 3;
     Y := Index div 3;
   end;
  end;

  // Wurde der Button gefunden?
  if ( X > 2 ) or ( Y > 2 ) 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();

  // 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.SpeedButton10Click(Sender: TObject);
var
  X, Y: Byte;
begin
   // Spiel intern und optisch löschen
   for X := 0 to 2 do
   begin
     for Y := 0 to 2 do
     begin
       Spielfeld[ X, Y ] := 0;
       TSpeedButton( Self.Controls[Y * 3 + 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 := 0 to 2 do
  begin
    Result := Spielfeld[ X, 0 ];
    if ( Result <> Spielfeld[ X, 1 ] ) or ( Result <> Spielfeld[ X, 2 ] ) then Result := 0;
    If Result <> 0 then Exit;
  end;

  // Gibt es einen Gewinner auf der X-Achse?
  for Y := 0 to 2 do
  begin
    Result := Spielfeld[ 0, Y ];
    if ( Result <> Spielfeld[ 1, Y ] ) or ( Result <> Spielfeld[ 2, Y ] ) then Result := 0;
    If Result <> 0 then Exit;
  end;

  // Gibt es diagonal einen Gewinner? (Von Links-Oben nach Rechts-Unten)
  for Y := 0 to 2 do
  begin
    Result := Spielfeld[ 0, 0 ];
    if ( Result <> Spielfeld[ 1, 1 ] ) or ( Result <> Spielfeld[ 2, 2 ] ) then Result := 0;
    If Result <> 0 then Exit;
  end;

  // Gibt es diagonal einen Gewinner? (Von Rechts-Oben nach Links-Unten)
  for Y := 0 to 2 do
  begin
    Result := Spielfeld[ 2, 0 ];
    if ( Result <> Spielfeld[ 1, 1 ] ) or ( Result <> Spielfeld[ 0, 2 ] ) then Result := 0;
    If Result <> 0 then Exit;
  end;

  // Gibt es noch ein freies Feld? (Das Spiel geht dann noch weiter)
  Result := 0;
  for X := 0 to 2 do
  begin
    for Y := 0 to 2 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.
Angehängte Dateien
Dateityp: zip Project1.zip (2,71 MB, 16x aufgerufen)

Geändert von ShadowDeath (12. Apr 2017 um 10:13 Uhr) Grund: falsche Tags
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Finde den Fehler einfach nicht

  Alt 11. Apr 2017, 22:10
Hallo,
F5, Strg+F5, F7 und F8 schon probiert?
Heiko
  Mit Zitat antworten Zitat
a.def
(Gast)

n/a Beiträge
 
#3

AW: Finde den Fehler einfach nicht

  Alt 11. Apr 2017, 22:23
Zitat:
Um genau zu sein scheint die Gewinner Abfrage nicht zu funktionieren, doch ich finde den Fehler einfach nicht.
Hier muss man präzisieren was denn überhaupt gewünscht ist. Denn "funktioniert nicht" kann alles bedeuten.

P.S.:
Code:
Code-Tags sind cool
aber
Delphi-Quellcode:
Delphi-Tags sind
cool-er
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.313 Beiträge
 
Delphi 12 Athens
 
#4

AW: Finde den Fehler einfach nicht

  Alt 11. Apr 2017, 23:40
PS: [DELPHI]fdfd[/DELPHI]


Zitat:
Delphi-Quellcode:
  // 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 := Index mod 3;
     Y := Index div 3;
   end;
  end;
Du versuchst also auch einer "zufälligen" Reihenfolge "Aller" Controls auf der Form zu bestimmen welcher Knopf es ist?
Ich wäre da nicht sicher, dass X und Y immer richtig sind.
Aber das würde dir auch der Debugger sagen, wenn man ihn verwendet, auf einen Knopf drückt und dann schaut was danach wirklich in X und Y steht.

PS: Alle VCL-Komponenten haben ein "Tag" property, das der Entwickler frei verwenden kann.
z.B. könnte man bei den Knöpfen 11, 12, 13, 21, ... 33 eintragen und dann

Delphi-Quellcode:
X := (Sender as TSpeedButton).Tag mod 10;
Y := (Sender as TSpeedButton).Tag div 10;
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#5

AW: Finde den Fehler einfach nicht

  Alt 12. Apr 2017, 00:05
Hallo,

bisher kann ich den Fehler auch nicht finden.

Aber:
Delphi-Quellcode:
  // Gibt es diagonal einen Gewinner? (Von Links-Oben nach Rechts-Unten)
  for Y := 0 to 2 do
  begin
    Result := Spielfeld[ 0, 0 ];
    if ( Result <> Spielfeld[ 1, 1 ] ) or ( Result <> Spielfeld[ 2, 2 ] ) then Result := 0;
    If Result <> 0 then Exit;
  end;
Die For-Schleife erscheint mir hier überflüssig, es gibt nur eine entsprechende Diagonale, da Y in der Schleife nicht genutzt wird, dürfte das dreifache Durchlaufen der Schleife überflüssig sein.
Gilt analog auch für die andere Diagonale.

Zitat:
Um genau zu sein scheint die Gewinner Abfrage nicht zu funktionieren, doch ich finde den Fehler einfach nicht.
Könntest Du das bitte präzisieren?

Funktioniert das grundsätzlich nicht oder nur ab und an oder nur bei bestimmten Konstellationen?

Der Vorschlag von himitsu ist meiner Meinung nach sehr sinnvoll. Über die "Liste" der Controls kann man zwar abfragen, ob man eine passende Komponenten gefunden hat, aber die Reichenfolge ist nicht zwingend aufsteigend nach Namen, sondern wohl von der Erstellungsreihenfolge in der IDE abhängig. Speedbutton1 muss also nicht unbedingt Self.Controls[0] sein. Allerdings müsste das auffallen, weil dann die Caption nicht korrekt gesetzt wird.

Bei himitsus Ansatz müsste meiner Meinung nach aber Spielfeld: array[0..2, 0..2] of Byte; in Spielfeld: array[1..3, 1..3] of Byte; geändert werden und die For-Schleifen entsprechend von 1 bis 3 gehen. Ebenso müsste dann
Delphi-Quellcode:
// Wurde der Button gefunden?
  if ( X > 2 ) or ( Y > 2 ) then exit;
geändert werden in
Delphi-Quellcode:
// Wurde der Button gefunden?
  if ( X > 3 ) or ( Y > 3 ) then exit;
Wobei diese Abfrage eigentlich überflüssig sein dürfte, da ja nur den SpeedButtons 1 bis 9 die Ereignisroutine zugewiesen wurde. Sollte die Bedingung also erfüllt sein, ist noch irgendwas anderes nicht in Ordnung.
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: TicTacToe - Frage zum Programmablauf

  Alt 12. Apr 2017, 09:08
Moin und willkommen in der DP.
Ich habe mal den Titel Deines Themas angepasst, damit dieser für Dritte aussagekräftiger ist.
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.655 Beiträge
 
Delphi 12 Athens
 
#7

AW: TicTacToe - Frage zum Programmablauf

  Alt 12. Apr 2017, 09:12
Dann hättest Du aber auch gleich die Code- durch Delphi-Tags ersetzen können
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:50 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 by Thomas Breitkreuz