Delphi 4 gewinnt KI macht nicht was sie soll

striker159

Lt. Junior Grade
Registriert
Dez. 2008
Beiträge
327
ohne KI funktioniert das spiel ohne probleme.
mit KI kommt es hin und wieder zu zügen, die weder so gewollt sind, noch die ich "absichtlich" reproduzieren kann.
einfach gesagt: es kommt vor, dass die KI 2 steine setzt. und warum sie das macht, kann ich nicht herausfinden und brauche dabei eure hilfe :)

erstmal meinen (einfachen) algorithmus für die KI
1 für alle felder prüfen: Kann man in dieses Feld setzen und dadurch gewinnen?
1.1 wenn ja, dieses feld besetzen => KI siegt.
1.2 wenn nicht , dann weiter mit Punkt 2

2 für alle felder prüfen: Kann der Gegner(der Mensch)in das Feld setzen und dadurch gewinnen ?
2.1 wenn ja: Gewinnt der Gegner (der Mensch) im nächsten Zug, wenn KI seine jetzige Siegmöglichkeit besetzt, und der Mensch auf diesen gesetzten Stein einen weiteren setzt?
2.1.1 wenn nein, gegnerische (menschliche) Siegmöglichkeit durch eigenen Stein verhindern.
2.1.2 wenn ja , gewinnt der Gegner (der Mensch) zu 100% => führt Punkt 2.1.1 aus
2.2 wenn nein, weiter mit Punkt 3.

3. Ist das unterste Feld der mittleren Spalte ( Spielfeld[3,0]) frei?
3.1 wenn ja, dorthin setzen.
3.2 wenn nein , zufällige spalte auswählen und weiter mit Punkt 4

4 Für zufällige Spalte prüfen: Wenn KI in diese Spalte einen Stein setzt, könnte der Gegner auf den Stein setzen und gewinnen?
4.1 wenn ja, dann andere zufällige Spalte auswählen; Wiederhole Punkt 3
4.2 wenn nein, setzt KI den Spielstein in diese Spalte

die Klasse ( der übersicht halber hab ich die sachen weggelassen, die nicht von der ki benutzt werden):
Code:
unit Class_TSpiel;

interface

type
  TSpiel = class
  private
    Spielfeld : array[0..6] of array[0..5] of integer; // 7*6 Spielfeld  : 0=leer, 1 = spieler 1, 2=spieler 2
    Spieler: integer;   // 1= spieler 1, 2= spieler 2
    GesetzteReihe:integer; // speichert die Nummer der Reihe, in welche der letzte Stein gesetzt wurde
    GesetzteSpalte:integer; // speichert die Nummer der Spalte, in welche der letzte Stein gesetzt wurde
    KI_Sieg:boolean;       // hat KI gewonnen ?
    FeldVoll:boolean;      // kein Zug mehr möglich ?
    SpalteVoll:array[0..6] of boolean;     // ist Spalte X voll ?
    function Esiegmgl(x:integer;y:integer):boolean;  // Prüft, ob KI durch Setzen eines Steines in Feld[x,y] gewinnen würde
    function Gsiegmgl(x:integer;y:integer):boolean;  // Prüft, ob der Gegner durch Setzen eines Steines in Feld[x,y] gewinnen würde
    function links(x:integer;y:integer):integer;     //
    function linksO(x:integer;y:integer):integer;    //
    function linksU(x:integer;y:integer):integer;    //
    function rechts(x:integer;y:integer):integer;    //
    function RechtsO(x:integer;y:integer):integer;   //
    function rechtsU(x:integer;y:integer):integer;   //
    function unten(x:integer;y:integer):integer;     //
  public
    procedure setzeStein(Spalte:integer); // Setzt einen Stein des aktiven Spielers in eine bestimmte Spalte.
    procedure setzeZufallStein{(var x:integer;var y:integer)}; // Setzt einen Stein des aktiven Spielers in eine zufällige Spalte.
    procedure spielerwechsel; // Wechelt den aktiven Spieler
    procedure KI;
  end;

implementation

function TSpiel.Esiegmgl(x:integer;y:integer):boolean;
begin
result:=false;
  if Spielfeld[x,y]=0 then
    if ((y-1>=0) and (Spielfeld[x,y-1]>0))or (y=0) then begin
      Spielfeld[x,y]:=spieler;
      if (unten(x,y)>=3) or (links(x,y)+rechts(x,y)>=3) or (linksO(x,y,)+rechtsU(x,y)>=3) or (linksU(x,y)+rechtsO(x,y)>=3) then
        result:=true;
      Spielfeld[x,y]:=0;
    end;
end;

function TSpiel.Gsiegmgl(x:integer;y:integer):boolean;
begin
  result:=false;
  if (y>=6) then begin
    SpalteVoll[x]:=true;
    exit;
  end;
  if Spielfeld[x,y]=0 then
    if ((y-1>=0) and (Spielfeld[x,y-1]>0))or (y=0) then begin
      spielerwechsel;
      Spielfeld[x,y]:=spieler;
      spielerwechsel;
      if (unten(x,y)>=3) or (links(x,y)+rechts(x,y)>=3) or (linksO(x,y,)+rechtsU(x,y)>=3) or (linksU(x,y)+rechtsO(x,y)>=3) then
        result:=true;
      Spielfeld[x,y]:=0;
    end;
end;

function TSpiel.links(x:integer;y:integer):integer;
begin
  result:=0;
  if x>0 then
    if Spielfeld[x,y]=Spielfeld[x-1,y] then
      result:=1+links(x-1,y);
end;

function TSpiel.linksO(x:integer;y:integer):integer;
begin
  result:=0;
  if (x>0) and (y<5) then
    if Spielfeld[x,y]=Spielfeld[x-1,y+1] then
      result:=1+linksO(x-1,y+1);
end;

function TSpiel.linksU(x:integer;y:integer):integer;
begin
  result:=0;
  if (x>0) and (y>0) then
    if Spielfeld[x,y]=Spielfeld[x-1,y-1] then
      result:=1+linksU(x-1,y-1);
end;

function TSpiel.rechts(x:integer;y:integer):integer;
begin
  result:=0;
  if x<6 then
    if Spielfeld[x,y]=Spielfeld[x+1,y] then
      result:=1+rechts(x+1,y);
end;

function TSpiel.rechtsO(x:integer;y:integer):integer;
begin
  result:=0;
  if (x<6) and (y<5) then
    if Spielfeld[x,y]=Spielfeld[x+1,y+1] then
      result:=1+rechtsO(x+1,y+1);
end;

function TSpiel.rechtsU(x:integer;y:integer):integer;
begin
  result:=0;
  if (x<6) and (y>0) then
    if Spielfeld[x,y]=Spielfeld[x+1,y-1] then
      result:=1+rechtsU(x+1,y-1);
end;

function TSpiel.unten(x:integer;y:integer):integer;
begin
  result:=0;
  if y>0 then
    if Spielfeld[x,y]=Spielfeld[x,y-1] then
      result:=1+unten(x,y-1);
end;

procedure TSpiel.setzeStein(Spalte:integer);
var i:integer;
begin
  for i:=0 to 5 do
    if Spielfeld[Spalte,i]=0 then begin
      if Spieler=1 then Spielfeld[Spalte,i]:=1
      else Spielfeld[Spalte,i]:=2;
      GesetzteReihe:=i;
      GesetzteSpalte:=Spalte;
      exit;
    end;
end;

procedure TSpiel.setzeZufallStein;
var i,j,volleSpalten:integer;
begin
  randomize;
  volleSpalten:=0;
  for i:=0 to 6 do begin
    if Spielfeld[i,5]<>0 then begin
      SpalteVoll[i]:=true  ;
      volleSpalten:=volleSpalten+1;
      end
    else
      SpalteVoll[i]:=false;
  end;
  if (volleSpalten>=7) or (volleSpalten<0) then exit
  else if volleSpalten=6 then
    begin
      FeldVoll:=false;
      for i:=0 to 6 do
        if SpalteVoll[i]=false then break;
    end
  else if (volleSpalten<6) and (volleSpalten>=0) then
    repeat
      i:=random(7);
    until SpalteVoll[i]=false;
  j:=0;
  while j<6 do
    begin
      if Spielfeld[i,j]=0 then
        begin
          SetzeStein(i);
          if j=5 then
            SpalteVoll[i]:=true;
          if SpalteVoll[0] and SpalteVoll[1] and SpalteVoll[2] and SpalteVoll[3] and SpalteVoll[4] and SpalteVoll[5] and SpalteVoll[6] then
            FeldVoll:=true;
          exit;
        end
      else
        begin
          if j<5 then
            j:=j+1
          else
            begin
              j:=0;
              repeat
                i:=random(7);
              until SpalteVoll[i]=false;
            end;
        end;
      if FeldVoll then
        break;
    end;
end;

procedure TSpiel.spielerwechsel;
begin
  if spieler=1 then spieler:=2
  else spieler:=1;
end;

procedure TSpiel.KI;
var i,j,Gsiegmglzaehler,spaltevollzaehler:integer;
a:boolean;
begin
// Punkt 1
 for i:=0 to 6 do
    for j:=0 to 5 do
      if Esiegmgl(i,j) then begin
      // 1.1
        KI_Sieg:=true;
        setzestein(i);
        exit;
      end;
// Punkt 2
  for i:=0 to 6 do
    for j:=0 to 5 do
      if Gsiegmgl(i,j) then   begin
          Spielfeld[i,j]:=0;
          setzestein(i);
          exit;
      end;
// Punkt 3
  if Spielfeld[3,0]=0 then begin
    setzestein(3);
    exit;
  end;
// Punkt 4
  a:=false;
  Gsiegmglzaehler:=0;
  repeat
    spaltevollzaehler:=0;
    setzeZufallStein;
    if FeldVoll then exit;
    for i:=0 to 6 do
       if spaltevoll[i] then
         spaltevollzaehler:=spaltevollzaehler+1;
    if (spaltevoll[gesetzteSpalte]=false )and ( spaltevollzaehler=6) then
      a:=false;
    if (spaltevoll[gesetzteSpalte]=false )and ( spaltevollzaehler<6) then
      begin
        if Gsiegmgl(gesetzteSpalte,gesetzteReihe+1) then
          begin
            if Gsiegmglzaehler<7-spaltevollzaehler then
              begin
                a:=true;
                Spielfeld[gesetztespalte,gesetzteReihe]:=0;
                Gsiegmglzaehler:=Gsiegmglzaehler+1
              end
            else
              a:=false;
          end
        else
          a:=false;
      end;
  until a=false;
end;

end.

hier noch ein bild zu einer situation, als 2 steine gesetzt wurden. ich habe immer wieder die prozedure KI aufgerufen, also im prinzip haben 2 KIs unendlich lang gegeneinander gespielt:
http://striker159.bplaced.net/4fehler.jpg
rot hat den schwarz markierten stein gesetzt, geld daraufhin die 2 steine mit X
 
Hat rot nicht eigentlich schon gewonnen?

Wenn du dir die dritte Zeile von oben mal anschaust, dann wirst du da 4 rote Steine finden...
 
@Zeitschlag, gelb hat auch schon gewonnen^^
Von der dritten Spalte unterste Zeile zur sechsten Spalte vierte Zeile.
@TE Kann dir leider auch nicht weiterhelfen, meine Programierkentnisse sind sehr beschränkt.


MfG
 
Zuletzt bearbeitet:
ja, 'eigentlich' wäre die situation garnicht zu stande gekommen.
ich hab dafür
einfach einen button genommen,der die prozedur KI aufruft, und das spielfeld zeichnet;
daher auch keine gewinnabfrage und so
 
SetzeStein(i); in einer while-Schleife, da sollte ne Abbruchbedingung rein ..
 
meinst du in procedure TSpiel.setzeZufallStein; ?
da hab ich ein exit drin nach setzteStein(i)

Code:
      if Spielfeld[i,j]=0 then
        begin
          SetzeStein(i);
           ...
          exit;
        end
 

Ähnliche Themen

Antworten
11
Aufrufe
6.983
Antworten
8
Aufrufe
1.834
D
  • Gesperrt
Antworten
5
Aufrufe
3.075
Zurück
Oben