Entwickler-Ecke

Algorithmen, Optimierung und Assembler - [Delphi] KI bei 3 gewinnt


glotzer - Mi 07.04.10 14:22
Titel: [Delphi] KI bei 3 gewinnt
Es geht um das bekannte spiel 3 gewinnt.

Die KI versucht immer zu gewinnen, dabei soll sie aus 3 wegen wählen:
-wenn sie in der nächsten runde gewinnen kann, dann soll sie das tun
-wenn der gegner gewinnen kann, soll sie es verhindern
-wenn das nicht geht soll zufällig ein stein gesetzt werden



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
[...]

type
  TSpielsteine = array[0..20..2of integer;

[...]

Var
  Spielsteine : TSpielsteine; //Spielbrett

[...]

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  Spielfeld := TBitmap.Create;
  Spielfeld.Height := 601;
  Spielfeld.Width  := 601;
  Spielfeld.Canvas.Pen.Width := 1;
  Form1.Canvas.Font.Size := 12;
  NewGame;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var x,y: integer;
    patt : boolean;
begin
 CleanPuffer;
 DrawSpielfeldToPuffer;
 DrawSteineToPuffer;
 DrawPuferToForm;
 DrawWhosTurnToForm;    

 if CheckWin(Spielsteine) <> 0 then
 begin
   Timer1.Enabled := false;
   if CheckWin(Spielsteine) = 2 then
   begin
     Form1.Canvas.Font.Color := ClRed;
     Form1.Canvas.TextOut(64020'Sie haben verloren!            ');
   end else
   begin
     Form1.Canvas.Font.Color := ClGreen;
     Form1.Canvas.TextOut(64020'Sie haben gewonnen!            ');
   end;
   exit;
 end;

 //Patt test
 patt := true;
 for x:= 0 to 2 do
 begin
    for y:= 0 to 2 do
    begin
       if SpielSteine[x,y] = 0 then patt := false
    end;
 end;
 if patt and Timer1.Enabled then
 begin
     Timer1.Enabled := false;
     Form1.Canvas.Font.Color := ClPurple;
     Form1.Canvas.TextOut(64020'Leider kein Sieger, Patt!            ');
     exit;
 end;
 
 if not YourTurn then KITurn;
end;

[...]


procedure TForm1.KITurn;
var tmp : Tpoint;
    x,y: integer;
    done : boolean;
    Steine: TSpielsteine;
begin
    tmp.X := 0;
    tmp.Y := 0;
    done := false;
    //Fals Gewinn möglich
    Steine := Spielsteine;
    for x:= 0 to 2 do
    begin
       for y:= 0 to 2 do
       begin
          if Steine[x,y] = 0 then Steine[x,y] := 4// 4 heißt KI stein
          if CheckWin(Steine) = 2 then
          begin
             tmp.X := x;
             tmp.Y := y;
             done := true;
             Form1.Canvas.TextOut(64050'win');
          end;
          Steine[x,y] := 0;                  //0 ist freies feld
       end;
    end;

    //Fals Gegner Gweinnen könnte
    Steine := Spielsteine;
    if not done then
    begin
       for x:= 0 to 2 do
       begin
          for y:= 0 to 2 do
          begin
             if Steine[x,y] = 0 then Steine[x,y] := 1;  // 1 Ist Spielerstein
             if CheckWin(Steine) = 1 then
             begin
                tmp.X := x;
                tmp.Y := y;
                done := true;
                Form1.Canvas.TextOut(64050'los');
             end;
             Steine[x,y] := 0;
          end;
       end;
    end;

    //Fals nichts anderes geht, zufällige Stein wahl
    if not done then
    begin
       tmp.X := random(3);
       tmp.Y := random(3);
       while (Spielsteine[tmp.X,tmp.Y] <> 0do
       begin
           tmp.X := random(3);
           tmp.Y := random(3);
       end;
       Form1.Canvas.TextOut(64050'ran');
    end;

if Spielsteine[tmp.X,tmp.y] = 0 then
begin
   Spielsteine[tmp.X,tmp.Y] := 4;
   yourTurn := true;
end else
begin
   yourTurn := false;
end;
end;

function TForm1.CheckWin(Steine: TSpielsteine): Integer;
var x,y: integer;
begin
  result := 0;
  //vertikal
  for y := 0 to 2 do
  begin
     if (Steine[0,y]+Steine[1,y]+Steine[2,y]) = 3 then result := 1;
     if (Steine[0,y]+Steine[1,y]+Steine[2,y]) = 12 then result := 2;
  end;
  //horiontal
  for x := 0 to 2 do
  begin
     if (Steine[x,0]+Steine[x,1]+Steine[x,2]) = 3 then result := 1;
     if (Steine[x,0]+Steine[x,1]+Steine[x,2]) = 12 then result := 2;
  end;
  //diagonal
  if (Steine[0,0]+Steine[1,1]+Steine[2,2]) = 3 then result := 1;
  if (Steine[0,0]+Steine[1,1]+Steine[2,2]) = 12 then result := 2;

  if (Steine[0,2]+Steine[1,1]+Steine[2,0]) = 3 then result := 1;
  if (Steine[0,2]+Steine[1,1]+Steine[2,0]) = 12 then result := 2;   
end;

end.


mein problem ist das diese ki (TForm1.KITurn) extrem unberechenbar ist... manchmal macht sie was sie soll, aber meistens wird einfach der zufall verwendet...
kann mir dabei jemand helfen? ich habe einfach keine idee mehr was falsch ist


Hidden - Mi 07.04.10 17:39

Hi :)

Meiner Ansicht nach Fehlt da ein begin-end-Block:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
          if Steine[x,y] = 0 then begin
            Steine[x,y] := 4// 4 heißt KI stein
            if CheckWin(Steine) = 2 then begin
              tmp.X := x;
              tmp.Y := y;
              done := true;
              Form1.Canvas.TextOut(64050'win');
            end;
            Steine[x,y] := 0;                  //0 ist freies feld
          end;


E: Wenn du dann prüfst, ob der Spieler gewinnen kann, natürlich auch. :)

lg,


glotzer - Mi 07.04.10 17:44

JA!!!! das wars, tausend dank.

weil das begin/end nicht da war wurde in der Steinkopie sämtliche steine gelöscht... und dann kann der test ja nix werden