Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   TicTacToe mit mittlerer KI und für 1vs1 (https://www.delphipraxis.net/55052-tictactoe-mit-mittlerer-ki-und-fuer-1vs1.html)

ferby 15. Okt 2005 21:41


TicTacToe mit mittlerer KI und für 1vs1
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo,

hab TicTacToe nachprogrammiert mit einer mittleren KI,
es ist auch mölich Mensch gegen Mensch zu spielen,

könnt ihr es mal testen und mir schreiben falls Fehler kommen???

danke!

devnull 15. Okt 2005 21:48

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Sieht ganz gut aus :)
Allerdings setzt die KI noch auf ein Feld, nachdem Spieler 1 gewonnen hat

mfg
devnull

malo 15. Okt 2005 21:59

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Die KI würd mich mal interessieren... scheint wohl nicht sehr intelligent zu sein.

Code:
Erster Zug:
[ ][ ][X]
[ ][O][ ]
[ ][ ][ ]
Zweiter Zug:
[ ][ ][X]
[ ][O][X]
[ ][ ][O]
Dritter Zug:
[X][ ][X]
[ ][O][X]
[O][ ][O]
Man sieht also, beim Dritten Zug hat die KI mich (absichtlich?) gewinnen lassen. Sie hat weder selber versucht, 3 in einer Reihe zu bekommen, noch, mich am Gewinnen zu hindern :gruebel:

Nikolas 15. Okt 2005 22:15

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Auch eine sichere Gewinnstrategie:

Mitte, oben mitte, unten links, oben rechts.

Benutzt du in deinem Code die random-Funktion?

Wenn ich (oben mitte, links mitte, rechts unten) spiele, gibt es keine feste Regel dafür, wo der Computer als nächstes setzen wird. Ich habe es ein paar Mal durchgespielt und jedes noch freie Feld wird irgend wann mal vom Computer besetzt.

Zeigst du mal den Code?

whiteshark 15. Okt 2005 22:53

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Schönes Spiel. :thumb:
Schade, dass die KI nicht gerade schlau ist. Aber das Spiel macht auch zu zweit Spaß.

Tubos 15. Okt 2005 23:00

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Zitat:

Schade, dass die KI nicht gerade schlau ist.
Das Spiel hat keine KI.
Wenn ich mich dem Computer nie in den Weg stelle, setzt er trotzdem keine drei Steine in Reihe. Wie gibts das?

Vom Design her ist es sehr minimalistisch, aber genauso soll TicTacToe auch sein. Gut gemacht!
Ein etwas anspruchsvollerer Computergegner wär noch ganz nett :)

gsh 16. Okt 2005 00:08

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Ich glaube die KI hat keinen Killerinstinkt :-D

Mal scherz bei seite:
Noch ne Strategie
Mitte
Mitte rechts
Links unten
Rechts oben


Was daran Wizig ist ist ja des die KI manchmal variiert auch wenn der Weg gleich ist also ist die Idee von der Random funktion doch nicht so abwägig :zwinker:

PS: @ferby: Wie wärs mit dem source von der KI würd mich brennent interessieren

ferby 16. Okt 2005 07:10

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Hallo,

Die KI funktioniert so:

die ersten zwei Züge sind fix und alle weiteren werden per random ermittlet, der Quellcode hat sicher noch viele Fehler und wird zur Zeit von mir überarbeitet. Ich möchte auch mehrer KI-Levels machen, also die KI die jetzt ist (normal) und noch eine bessere (schwer).

Hier der Quellcode:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ImgList, Menus, Ferby;

type
  TForm1 = class(TForm)
    feld: TImage;
    Image1: TImage;
    Image2: TImage;
    Image3: TImage;
    Image4: TImage;
    Image8: TImage;
    Image9: TImage;
    Image5: TImage;
    Image7: TImage;
    Image6: TImage;
    ImageList: TImageList;
    menue: TMainMenu;
    NeuesSpiel: TMenuItem;
    Einstellung1: TMenuItem;
    Hilfe: TMenuItem;
    Info: TMenuItem;
    aus: TMenuItem;
    an: TMenuItem;
    procedure AufFeldClick(Sender: TObject);
    procedure check;
    procedure NeuesSpielClick(Sender: TObject);
    procedure KIClick(Sender: TObject);
    procedure HilfeClick(Sender: TObject);
    procedure InfoClick(Sender: TObject);
    procedure KI_Zug;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  feldwert:array [1..9] of byte;
  spieler:boolean;
  KI_var:boolean=true;
  zug:byte;
  BM:TBitmap;
  wahl: byte;

implementation

{$R *.dfm}

procedure KI_S(feld, w: byte);
begin
  if feldwert[feld]=1 then wahl:=w;
end;


procedure TForm1.KI_Zug;
var
unentschieden:boolean;
i:byte;
begin
  bm := TBitmap.create;
  inc(zug);

  wahl:=0;

  // ZUG 1
  if zug=1 then
  begin
    if feldwert[5]=1 then wahl:=1 else wahl:=5;
  end;

    // ZUG 2
  if zug=2 then
  begin
    if feldwert[1]=1 then
    begin
      KI_S(2,3);
      KI_S(3,2);
      KI_S(4,7);
      KI_S(6,2);
      KI_S(7,4);
      KI_S(8,4);
      KI_S(9,2);
    end;

    if feldwert[2]=1 then
    begin
      KI_S(3,1);
      KI_S(4,1);
      KI_S(6,3);
      KI_S(7,4);
      KI_S(8,4);
      KI_S(9,6);
    end;

    if feldwert[3]=1 then
    begin
      KI_S(4,2);
      KI_S(6,9);
      KI_S(7,2);
      KI_S(8,6);
      KI_S(9,6);
    end;

    if feldwert[4]=1 then
    begin
      KI_S(6,2);
      KI_S(7,1);
      KI_S(8,7);
      KI_S(9,8);
    end;
                                                     
    if feldwert[5]=1 then
    begin
      KI_S(2,8);
      KI_S(3,7);
      KI_S(4,6);
      KI_S(6,4);
      KI_S(7,3);
      KI_S(8,2);
      KI_S(9,3);
    end;

    if feldwert[6]=1 then
    begin
      KI_S(7,8);
      KI_S(8,9);
      KI_S(9,3);
    end;

    if feldwert[7]=1 then
    begin
      KI_S(8,9);
      KI_S(9,8);
    end;

    if feldwert[8]=1 then KI_S(9,7);

  end;

  end;

  unentschieden:=true;
  if wahl=0 then
  repeat
    wahl:=random(9)+1;
    for i:=1 to 9 do if feldwert[i]=0 then unentschieden:=false;
    if unentschieden then exit;
  until feldwert[wahl]=0;


  Imagelist.getbitmap(1,Bm);
  feldwert[wahl]:=2;
  TImage(FindComponent('Image' + inttostr(wahl))).Picture.Bitmap := BM;
end;

procedure TForm1.AufFeldClick(Sender: TObject);
var
i,nr:byte;
begin
  bm := TBitmap.create;

  // No KI
  if not ki_var then
  for i:= 1 to 9 do if (Sender = TImage(FindComponent('Image' + inttostr(i)))) then
  if (feldwert[i]=0) then
  begin
    spieler:=not spieler;
    if spieler then nr:=0 else nr:=1;
    Imagelist.getbitmap(nr,Bm);
    feldwert[i]:=nr+1;
    TImage(FindComponent('Image' + inttostr(i))).Picture.Bitmap := BM;
  end
  else
  ShowMessage('Dieses Feld ist berreits besetzt');

  // With KI
  if ki_var then
  for i:= 1 to 9 do if (Sender = TImage(FindComponent('Image' + inttostr(i)))) then
  if (feldwert[i]=0) then
  begin
    Imagelist.getbitmap(0,Bm);
    feldwert[i]:=1;
    TImage(FindComponent('Image' + inttostr(i))).Picture.Bitmap := BM;
    KI_Zug;
  end
  else
  ShowMessage('Dieses Feld ist berreits besetzt');

  check;

end;

//////////////////////////////////////////////////////////////////////////////// CHECK
function check2(wert1,wert2,wert3,art:integer): boolean;
begin
 result:=false;
 if (feldwert[wert1]=art) and (feldwert[wert2]=art) and (feldwert[wert3]=art) then result:=true;
end;

procedure tform1.check;
var
i : byte;
unentschieden:boolean;
begin

  // Abfrage ob ein Spieler gewonnen hat
  for i:=1 to 2 do
  if
  check2(1,2,3,i) or
  check2(4,5,6,i) or
  check2(7,8,9,i) or
  check2(1,4,7,i) or
  check2(2,5,8,i) or
  check2(3,6,9,i) or
  check2(1,5,9,i) or
  check2(3,5,7,i)
  then
  begin
    if (i=2) and (ki_var) then showmessage('Die KI hat gewonnen') else
    showmessage('Spieler '+inttostr(i)+' hat gewonnen');
    NeuesSpielClick(nil)
  end;

  // Unentschieden?
  unentschieden:=true;
  for i:=1 to 9 do if feldwert[i]=0 then unentschieden:=false;
  if unentschieden then
  begin
    showmessage('Das Spiel ist Unentschieden ausgegangen');
    NeuesSpielClick(nil)
  end;

end;

//////////////////////////////////////////////////////////////////////////////// MENÜ
// Neues Spiel
procedure TForm1.NeuesSpielClick(Sender: TObject);
var
i:byte;
begin
  for i:=1 to 9 do
  begin
    feldwert[i]:=0;
    TImage(FindComponent('Image' + inttostr(i))).Picture.Bitmap := nil;
  end;

  spieler:=false;
  zug:=0;
end;

// KI Klick
procedure Tform1.KIClick(Sender: TObject);
begin
  an.checked:=false;
  aus.checked:=false;

  if sender=an then an.checked:=true
  else aus.checked:=true;

  ki_var:=an.checked;
end;

// Hilfe
procedure TForm1.HilfeClick(Sender: TObject);
begin
showmessage('Hilfe:' +#10#10+ '1) Die KI ist ausgeschalten:' +#10+ 'Zwei menschliche Spieler drücken immer abwechselnd auf ein leeres Feld.' +#10+ 'Sobald jemand drei X bzw drei O übereinander, nebeneinander, oder quer hat, hat dieser Spieler gewonnen.' +#10#10+ '2) Die KI ist eingeschalten:' +#10+ 'Jetzt spielt nur ein menschlicher Spieler gegen den Computer' +#10#10+ 'Viel Spaß!');
end;

// Info
procedure TForm1.InfoClick(Sender: TObject);
begin
  copyright('TicTacToe','2.00');
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  randomize;
end;

end.

Das der Quellcode noch nicht perfekt ist weiß ich selbst :) ,
solltet ihr Rechtschreibfehler finden dann bitte melden!

gsh 16. Okt 2005 10:30

Re: TicTacToe mit mittlerer KI und für 1vs1
 
naja hab die funktionen etwas überflogen

Etwas noch was einzubauen wäre
wenn der Computer drannen ist und sieht des er schon zwei steine in einer Reihe hat dann muss er den richtigen stein an die richtige stelle setzen (außer natürlich ist belegt)

Nicodius 25. Okt 2005 09:22

Re: TicTacToe mit mittlerer KI und für 1vs1
 
also wir haben das von der schule aus machen müssen


normal wird das so realisiert dass die KI in einem array "nachsehen kann" wies derweil ausschaut

2d array mit 9 feldern (1-3..1-3) und wenn ein x am feld ist heißt es -1 und wenn ein o am feld ist isses im array ein +1 nicht belegte felder sind eine 0


damit haste ma ne korrekte schöne abfrage ob wer gewonnen hat


dann kann die ki mit schleifen durchrechenen wo der beste zug wäre (zuerst gewinnchance abfrage dann defensivabfrage)


usw

wenn du willst kan nich dir mal den code (leider erst im november weil pc in der reperatur is) mitteilen

:)

grüsse

Nico

zerodivide 25. Okt 2005 09:53

Re: TicTacToe mit mittlerer KI und für 1vs1
 
TicTacToe müsste sich relativ schnell durchrechnen lassen.

Es sollte also möglich sein ein Bewertungsschema für einen Zug einzuführen.

erster Vorschlag:

Für jedes noch zur Verfügung stehende Feld prüfen:
sofortige Gewinnchance +3
Gewinnchance im nächsten Zug +1
Vereitelung einer gegnerischen Gewinnchance +2

Aus den Feldern mit der höchsten Punktzahl zufällig eins wählen.

Greetz

ferby 2. Nov 2005 14:35

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

ich habe die KI jetzt ein weinig überarbeitet,
es ist jetzt möglich zwischen der alten KI (KI Leicht) und zwischen meiner neuen KI (KI Schwer) zu wählen,
eigentlich sollte es jetzt unmöglich sein gegen die KI Schwer zu gewinnen,
ihr könnt es mal ausprobieren.




Bin für positive und negative kritik offen,

ferby

faux 2. Nov 2005 15:42

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Hallo!
Ja, das hast du super gemacht! Jetzt kann man wirklich nur noch durch ein Unentschieden einer Niederlage entgehen. :D
Jetzt würde mich der Quellcode interessieren. Hast du einfach alle Möglichkeiten aufgelistet (wie oben) oder hast du eine Function, die erkennt, wo der Stein am passendsten wäre?

Grüße
Faux

ferby 2. Nov 2005 16:13

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Hallo,

Eigentlich war das schon mit dem Auflisten von vorher total dum,

ich habe nur ein wenig Quelltext hinzugefügt und zwar in der procedure KI_Zug

Delphi-Quellcode:
  // ZUG 3 oder höher
  if (zug>2) and (KI_schwer.checked) then
  begin
    for i:=1 to 2 do
    begin
      KI_S2(1,2,3,i);
      KI_S2(4,5,6,i);
      KI_S2(7,8,9,i);
      KI_S2(1,4,7,i);
      KI_S2(2,5,8,i);
      KI_S2(3,6,9,i);
      KI_S2(3,5,7,i);
      KI_S2(1,5,9,i);
    end;
  end;
wobei KI_S2 das ist:

Delphi-Quellcode:
procedure KI_S2(a,b,c,wert:byte);
begin
  if (feldwert[a]=wert) and (feldwert[b]=wert) and (feldwert[c]=0) then wahl:=c;
  if (feldwert[b]=wert) and (feldwert[c]=wert) and (feldwert[a]=0) then wahl:=a;
  if (feldwert[c]=wert) and (feldwert[a]=wert) and (feldwert[b]=0) then wahl:=b;
end;

Im Prinzip könnte ich sogar den ganzen zug eins und zwei Weglasen (also die ganze KI besteht nur noch aus dem was ich jetzt hinzugefügt habe), und sie wäre noch immer fast unbesiegbar.


Ferby

Thorben77 2. Nov 2005 16:19

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Ganz nett :thumb:

Aber häng die Echse nochmal an den ersten Beitrag an, die meisten Leute werden wohl nicht erst runterscrollen und gucken ob da noch eine ist.

robinWie 11. Nov 2005 14:42

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Schönes Teil!
Ich hab auch mal versucht ein TicTacToe zu progen, aber manchmal hat der Computer zwei kreise gemacht. Und die KI war so gut das es unmöglich den zu besiegen :mrgreen:

zecke 11. Nov 2005 14:49

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Ich gewinn nur -.- das ist seltsam.

Ich setze oben links, Computer immer in die Mitte, ich unten rechts, er oben mitte, ich unten mitte, er mitte links, ich unten rechts und habe damit 3 -.- (also die Version 2.20)

Aber eigentlich is das Spiel witzlos, wenn zwei "Könner" gegeneinander spielen, trotzdem schön umgesetzt :thumb:

Edit: Ich korrigiere: Nicht immer, aber so in Circa 90% der Fälle gewinnt man so, auch spiegelverkehrt macht er mit.

Maximus 11. Nov 2005 15:03

Re: TicTacToe mit mittlerer KI und für 1vs1
 
@Zecke vielleicht solltest du die KI auch auf schwer stellen ;) - Dann funktioniert das nicht mehr ^^

MFG
Maximus

zecke 11. Nov 2005 15:06

Re: TicTacToe mit mittlerer KI und für 1vs1
 
Ah Du Fuchs Du :mrgreen: (Ja ich gebe zu, ich habe das Menu strikt missachtet ;))


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:47 Uhr.

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