Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPlease (https://www.delphipraxis.net/25275-fehler-warsch-eine-abfrage-tic-tac-toe-ki-helpplease.html)

M4ST3R86 3. Jul 2004 22:23


Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPlease
 
das ist eine demo zu Tic tac toe mit zufallssetzung des pc'S. Mit 2d array, Das problem ist wenn ich starte und ein X setze dann sagt der direkt X hat gewonnen und hört auf den pc zu setzen aber wieso frage ich mich. Ich hoffe hier kann mir einer helfen bin kurz vor dem verzweifeln.

Zum Programm: ich habe ein leeres image ein x image und ein o image die lade ich dann in die image ja nach fall.

Hier meine ICQ: 261738606 wenn einer die exe haben will.




Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, jpeg, ExtCtrls, StdCtrls;

type
  TFieldType = ( ftX, ftO, ftNone );

  TForm1 = class(TForm)
    ImageK0: TImage;
    ImageK8: TImage;
    ImageK4: TImage;
    ImageK1: TImage;
    ImageK2: TImage;
    ImageK5: TImage;
    ImageK3: TImage;
    ImageK6: TImage;
    ImageK7: TImage;
    Label1: TLabel;
    ImageO: TImage;
    ImageX: TImage;
    Memo1: TMemo;
    Button1: TButton;
    ImageBlank: TImage;
    procedure ImageK0Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    bMovePlayerX : boolean;
    bGameOver : boolean;
    GameBoard : array[ 0..2,0..2 ] of TFieldType;

    function CheckForFreeField( nFieldIdx : integer ) : boolean;
    procedure SetField( img : TImage; nFieldIdx : integer; fieldType : TFieldType );
    procedure ResetGameBoard();
    procedure SimpleKI();
    function FindField( nIdx : integer ) : TImage;
    function CheckForWinner( ft : TFieldType ) : boolean;
    function HasWinner() : TFieldType;
    procedure ProcessWinnerFunc();
    function IsGameOver() : boolean;
    procedure ClearImages;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//Sucht ein TImage Objekt, aus der Objektliste von Form1, mit dem Tag 'nIdx'
function TForm1.FindField( nIdx : integer ) : TImage;
var
  i : integer;
begin
  //Durchlauf aller Komponenten auf Form1
  for i := 0 to Form1.ComponentCount - 1 do begin
    //Falls Komponente 'i' von Typ TImage ist UND Komponente 'i' den Tag 'nIdx' hat, diese
    //als Funktionsrückgabewert festlegen und aus der Schleife springen
    if ( Form1.Components[ i ] is TImage ) and ( ( Form1.Components[ i ] as TImage ).Tag = nIdx ) then begin
      result := Form1.Components[ i ] as TImage;

      break;
    end;
  end;
end;

//Resetet das Spielfeld
procedure TForm1.ResetGameBoard();
var
  i,x,y : integer;
begin
   for x := 0 to 2 do
   begin
   for y := 0 to 2 do
   begin
  //Setzt alle Einträge des Arrays 'GameBoard' auf den Wert ftNone
   GameBoard[x,y] := ftNone;
  //Setzt die globale Variable 'bGameOver' auf false
  bGameOver := false;
  end;
  end;
end;

//Prüft ob das Spielfeld 'nFieldIdx' noch frei ist
function TForm1.CheckForFreeField( nFieldIdx : integer ) : boolean;
var x,y : integer;
begin
  //Result standardmäßig auf false
  result := false;

  //Wenn 'nFieldIdx' größer als 8 ist false zurückgeben
  if ( nFieldIdx > 8 ) then
    result := false;

   for x := 0 to 2 do
   begin
   for y := 0 to 2 do
   begin
  //Wenn das Spielfeld 'nFielIdx' den Wert ftNone hat, true zurückgeben
  if ( GameBoard[ x,y ] = ftNone ) then
   result := true;
   end;
   end;
end;

//Setzt das Spielfeld 'nFieldIdx' auf den wert 'fieldType' und weist 'img' das passende Bild zu
procedure TForm1.SetField( img : TImage; nFieldIdx : integer; fieldType : TFieldType );
var x,y : integer;
begin
  //Ist das Feld 'nFieldIdx' noch frei?
  if ( CheckForFreeField( nFieldIdx ) ) then begin
    //Setzt das Feld 'nFieldIdx' auf den Wert 'fieldType'
    for x := 0 to 2 do
   begin
   for y := 0 to 2 do
   begin
    GameBoard[ x,y ] := fieldType;
    end;
    end;
    //Je nach 'fieldType' das passende Bild an 'img' übergeben
    case fieldType of
      ftX : img.Picture.Assign( ImageX.Picture );
      ftO : img.Picture.Assign( ImageO.Picture );
    end;
  end;
end;

//Event der allen Spielfeldern( Visell: TImage ) zugewießen wurde
procedure TForm1.ImageK0Click(Sender: TObject);
var
  nFieldNum : integer;
  nCurrImg : TImage;
begin
  //Falls der Sender nicht von Typ TImage ist abbrechen
  if not ( Sender is TImage ) then
    exit;

  //Wenn 'bGameOver' auf true gesetzt ist, ebenfalls abbrechen
  if bGameOver then
    exit;

  //Den Sender einer Hilfvariable übergeben
  nCurrImg := ( Sender as TImage );
  //Den Tag (Feldnummer) des Senders einer Hilfvariable übergeben
  nFieldNum := nCurrImg.Tag;

  //Überprüfen ob das geklickte Feld frei ist, falls nicht aus der
  //Funktion springen
  if ( not CheckForFreeField( nFieldNum ) ) then begin
    Label1.Caption := 'Move again';
    exit;
  end;

  //Passendes Bild bzw. passender Feldtype auswählen
  if ( bMovePlayerX ) then
    SetField( nCurrImg, nFieldNum, ftX )
  else
    SetField( nCurrImg, nFieldNum, ftO );

  //Prüfen ob jemand gewonnen hat oder alle Felder belegt sind (unendschieden)
  ProcessWinnerFunc();

  //Wenn 'bGameOver' auf true gesetzt wurde aus der Funktion springen
  if ( bGameOver ) then
    exit;

  //'bMovePlayerX' negieren'???
  bMovePlayerX := not bMovePlayerX;
  //Zufallszug für den Computer ausführen
  SimpleKI();
  //Nochmals Prüfen ob jemand gewonnen hat
  ProcessWinnerFunc();
end;

//Create Event von Form1
procedure TForm1.FormCreate(Sender: TObject);
begin
  //PlayerX fängt an
  bMovePlayerX := true;
  //Spielfeld reseten
  ResetGameBoard;
  Randomize;
end;

//Gane billige ZufallsKI
procedure TForm1.SimpleKI();
var
  x,y,rndIdx   : integer;
  nCurrField : TImage;
begin
  //Zufallswert zwischen 0 und 8
  x := random (2);
  y := random (2);

  //Solang kein freies Feld für den jeweiligen Zufallswert gefunden wurde...

   while not CheckForFreeField( rndIdx ) do begin
    //...Neuen Zufallswert ermitteln
    x := random (2);
    y := random (2);
    end;



  //Finden des entprechenden TImage Objektes für den Index 'rndIdx'
  nCurrField := FindField(rndIdx);

  //Setzten des entsprechenden Wertes
  if ( bMovePlayerX ) then
    SetField( nCurrField,rndIdx, ftX )
  else
    SetField( nCurrField,rndIdx, ftO );

  //Negieren von 'bMovePlayerX' (heisst das echt negieren???)
  bMovePlayerX := not bMovePlayerX;
end;

//Prüft ob einer der beidem Player gewonnen hat
function TForm1.CheckForWinner( ft : TFieldType ) : boolean;
var
  y,x,i : integer;
begin
  {//Standardgemäß hat mal keiner gewonnen
  result := false;

  //Zähler auf 0
  x := 0;
  y :=0;
  i:=0;

  //Folgende zwei Schleifen könnte man in eine Funktion zusammenfassen

  //Kleiner test
  {while i < 8 do begin
    if ( GameBoard[ y,x ] = ft ) and ( GameBoard[ y,x + 1 ] = ft ) and ( GameBoard[ y,x + 2 ] = ft ) then begin
      result := true;
      break;
    end;
    end;
    end;
    inc( i, 3 );
  end;

  //Zähler auf 0
  i := 0;

  //Nochmal ein kleiner test
  while i <> 3 do begin
    if ( GameBoard[ y,x ] = ft ) and ( GameBoard[ y,x + 3 ] = ft ) and ( GameBoard[ y,x + 6 ] = ft ) then begin
      result := true;
      break;
    end;

    inc( i, 1 );
  end;

  //Diagonale Reihen überpüfen
  if ( GameBoard[ 0,0 ] = ft ) and ( GameBoard[ 1,1 ] = ft ) and ( GameBoard[ 2,2 ] = ft ) then
    result := true;

  //Ebenfalls diagonal
  if ( GameBoard[ 0,2 ] = ft ) and ( GameBoard[ 1,1 ] = ft ) and ( GameBoard[ 2,0 ] = ft ) then
    result := true; }
end;

//Checkt ob es einen Gewinner gibt, wenn ja wird der entsprechende Typ zurückgegeben
function TForm1.HasWinner() : TFieldType;
begin
  //Standard auf ftNone
  result := ftNone;

  //Hat SpielerX gewonnen? Falls ja Rückgabewert auf ftX setzen
  if ( CheckForWinner( ftX ) ) then
    result := ftX
  //Falls nicht, hat vielleicht SpielerO gewonnen?
  else if ( CheckForWinner( ftO ) ) then
    result := ftO;


end;

///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////



//Hilfsfunktion, auswerten des Gewinners
procedure TForm1.ProcessWinnerFunc();
var
  winner : TFieldType;
begin
  //Gewinnertyp zuweisen
  winner := HasWinner();

  //Wenn SpielerX gewonnen hat, das dem Spieler deutlich machen
  if ( winner = ftX ) then begin
    label1.Caption := 'Player ''x'' has won';
    bGameOver := true;
  end
  //Wenn SpielerO gewonnen hat, ebenfalls ausgeben
  else if ( winner = ftO ) then begin
    label1.Caption := 'Player ''o'' has won';
    bGameOver := true;
  end;

  //Wenn jemand gewonnen hat, können wir uns den Rest sparen
  if ( bGameOver ) then exit;

  //Prüfen ob alle Felder belegt wurden
  bGameOver := IsGameOver();

  //Wenn 'bGameOver' auf true gesetzt wurde UND keiner gewonnen hat,
  //ist unentschieden angesagt.
  if ( bGameOver ) and ( winner = ftNone ) then
    label1.Caption := 'Nobody has won';
end;

//Prüft ob alle Spielfelder mit einem Wert (nicht ftNone) belegt sind
function TForm1.IsGameOver() : boolean;
var
  i,x,y : integer;
begin
  //Standard mal auf true
  result := true;

  //Schleife die immer Feld 'i' überprüft
  for x := 0 to 2 do begin
  for y := 0 to 2 do begin
    //Falls ein Feld auf ftNone gesetzt ist, false zurückgeben
    //und aus der Schleife springen
    if ( GameBoard[ x,y ] = ftNone ) then begin
      result := false;
      break;
    end;
    end;
  end;
end;

//Belegt alle TImage Objekte mit dem weisen Standardbild
procedure TForm1.ClearImages();
var
  currImg : TImage;
  i : integer;
begin
  for i := 0 to 8 do begin
    currImg := FindField( i );

    //Falls currImg nicht nil ist
    if ( currImg <> nil ) then
      currImg.Picture := ImageBlank.Picture;
  end;
end;

//Event für Button1 (New game)
procedure TForm1.Button1Click(Sender: TObject);
begin
  //Board reseten
  ResetGameBoard;
  //Images mit Standardbild versehen
  ClearImages;
end;

end.

M4ST3R86 4. Jul 2004 12:10

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
kann mir keiner helfen?

scp 4. Jul 2004 12:27

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
So, jetzt hatte ich mal Zeit den etwas längeren Code-Schnipsel zu überblicken. Was mir zunächst auffällt:

In TForm1.ResetGameBoard wird bGameOver 9x auf false gesetzt, macht zwar keinen Fehler ist aber unnötig.

In TForm1.CheckForFreeField wird nFieldIdx in der Schleife nicht verwendet, das heisst er prüft alle Felder und es kommt nie das richtige Ergebnis raus

In TForm1.SetField das gleiche: nFieldIdx wird in der Schleife nicht verwendet, also setzt er ALLE Felder auf den gewünschten Spieler. Ausserdem ist case fieldType of NICHT mehr in der Schleife drin, auch wenn es nach deinem Code-Aufbau so aussieht.

xineohp 4. Jul 2004 12:34

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
moin,

hier liegt der Hund begraben:

formal:
1. Warum hast du das alles auskommentiert?
2. die markierten end;'s sind zuviel!

logisch:
1. Gameboard ist ein zweidimensionales array auf das mit den Koordinaten[x,y] zugegriffen wird nicht per durchlaufendem Index!
-->Für was hast du die Zählervariable (i) wenn du sie nie einsetzt! Die Schleife "//Kleiner test" führt dreimal exakt die gleichen Abfragen durch! Wenn dann müsste i y heißen und von 0 bis 2 laufen.
-->"//Nochmal ein kleiner test" müsste analog aufgebaut sein, mit x als Laufvariable und y,y+1,y+2


Zitat:

Zitat von M4ST3R86
Delphi-Quellcode:
//Prüft ob einer der beidem Player gewonnen hat
function TForm1.CheckForWinner( ft : TFieldType ) : boolean;
var
  y,x,i : integer;
begin
  {//Standardgemäß hat mal keiner gewonnen
  result := false;

  //Zähler auf 0
  x := 0;
  y :=0;
  i:=0;

  //Folgende zwei Schleifen könnte man in eine Funktion zusammenfassen

  //Kleiner test
  {while i < 8 do begin
    if ( GameBoard[ y,x ] = ft ) and ( GameBoard[ y,x + 1 ] = ft ) and ( GameBoard[ y,x + 2 ] = ft ) then begin
      result := true;
      break;
    end;
    end;   <--- überflüssig/falsch
    end;   <--- überflüssig/falsch
    inc( i, 3 );
  end;

  //Zähler auf 0
  i := 0;

  //Nochmal ein kleiner test
  while i <> 3 do begin
    if ( GameBoard[ y,x ] = ft ) and ( GameBoard[ y,x + 3 ] = ft ) and ( GameBoard[ y,x + 6 ] = ft ) then begin
      result := true;
      break;
    end;

    inc( i, 1 );
  end;

  //Diagonale Reihen überpüfen
  if ( GameBoard[ 0,0 ] = ft ) and ( GameBoard[ 1,1 ] = ft ) and ( GameBoard[ 2,2 ] = ft ) then
    result := true;

  //Ebenfalls diagonal
  if ( GameBoard[ 0,2 ] = ft ) and ( GameBoard[ 1,1 ] = ft ) and ( GameBoard[ 2,0 ] = ft ) then
    result := true; }
end;


M4ST3R86 4. Jul 2004 13:29

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
gutt mit den 2 ends habe ich es jetzt verbessert. aber bei den anderen sachen die ihr sagt, währe nett wenn ihr gerade ein kleines beispiel geben würdet bitte.

gehts das?

Mirilin 4. Jul 2004 13:39

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
:hi:


So als kleines Beispiel, wie Du es umschreiben könntest :)
Delphi-Quellcode:
function TForm1.CheckForFreeField(x,y : Byte):Boolean;
begin
  Result := GameBoard[x,y] = ftNone;
end;
mfg Tobias

[Edit]
Das Feld (GameBoard) sieht ja so aus :
Code:
y _ _ _ 
0|_|_|_|
1|_|_|_|
2|_|_|_|
  0 1 2 x

M4ST3R86 4. Jul 2004 13:50

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
nö das klappt nicht der meckert wegen boolean da rum, glaube nicht das das von dir was bringt?

das kann doch nicht alles sein oder?

xineohp 4. Jul 2004 15:15

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
moin,

Du mischst deine Darstellungselement mit den logischen Elementen. Soll heißen:
Warum prüfst du in "CheckForFreeField" ob ImageKx = ImageX? es ist doch viel einfacher zu prüfen ob Gameboard[x,y]=ftnone ist! ( siehe Mirilin )

M4ST3R86 4. Jul 2004 22:14

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
das prob ist das der kein boolean will. der zeigt da nen fehler an

scp 4. Jul 2004 22:35

Re: Fehler (warsch.) eine Abfrage. In Tic Tac Toe KI. HelpPl
 
Zitat:

Zitat von M4ST3R86
das prob ist das der kein boolean will. der zeigt da nen fehler an

Wieso "will" er kein boolean? Kannst du mal die genaue Fehlermeldung sagen? Schliesslich steht ja bei der Funktion, das der Rückgabewert boolean ist.

Probiers mal mit Klammern:

Delphi-Quellcode:
function TForm1.CheckForFreeField(x,y : Byte):Boolean;
begin
  Result := (GameBoard[x,y] = ftNone);
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:30 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz