Autor Beitrag
Paddii
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 28

WinXP Prof.
Blitz3D, PureBasic 4, Delphi 6
BeitragVerfasst: Do 15.03.07 20:28 
Hallöchen

wir haben in der Schule die Aufgabe bekommen das Spiel 4-Gewinnt zu programmieren, dazu haben wir ein StringGrid verwendet.
Bei der Abfrage, ob 4 Steine in einer Reihe liegen oder aufeinander stehen gibt es ein Paar Probleme (Diagonal hab ich erstmal außer Aucht gelassen).
Hier erts mal der Programmtext:
ausblenden volle Höhe 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:
var
  Form1: TForm1;
  SaveFeld: Integer;
  Wechsel: Boolean;
  Gewinner: String;

implementation

{$R *.DFM}

procedure Abfrage(Feld: TStringGrid);
var i,j:Integer;
begin
  For i:=0 to 5 do
    For j:=0 to 6 do
      If j<=3 then
      begin
        If (Feld.Cells[j,i]='O')
        and (Feld.Cells[j+1,i]='O')
        and (Feld.Cells[j+2,i]='O')
        and (Feld.Cells[j+3,i]='O') then
          Gewinner:='O'
        Else If (Feld.Cells[j,i]='X')
        and (Feld.Cells[j+1,i]='X')
        and (Feld.Cells[j+2,i]='X')
        and (Feld.Cells[j+3,i]='X') then
          Gewinner:='X';
      end
      Else If i<=2 then
      begin
        If (Feld.Cells[j,i]='O')
        and (Feld.Cells[j,i+1]='O')
        and (Feld.Cells[j,i+2]='O')
        and (Feld.Cells[j,i+3]='O') then
          Gewinner:='O'
        Else If (Feld.Cells[j,i]='X')
        and (Feld.Cells[j,i+1]='X')
        and (Feld.Cells[j,i+2]='X')
        and (Feld.Cells[j,i+3]='X') then
          Gewinner:='X';
      end;
end;

procedure TForm1.FeldClick(Sender: TObject);
var i,j: Integer;
begin
  For i:= 5 downto 0 do
    If (Feld.Cells[Feld.Col, i]='') and (Savefeld<0) then
    begin
      SaveFeld:=i;
      For j:=0 to SaveFeld do
      begin
        If Wechsel=False then Feld.Cells[Feld.Col, j]:='O'
        Else If Wechsel=True then Feld.Cells[Feld.Col, j]:='X';
        If j>0 then Feld.Cells[Feld.Col, j-1]:='';
        Feld.Refresh;
        Sleep(30);
      end;
    end;
  SaveFeld:= -1;
  If Wechsel=False then Wechsel:=True
  Else If Wechsel=True then Wechsel:=False;
  Abfrage(Feld);
  Label1.Caption:=Gewinner + ' ist Gewinner!!! :-)'
end;

procedure TForm1.FormCreate(Sender: TObject);
var i,j: Integer;
begin
  SaveFeld:= -1;
  Wechsel:= False;
  Gewinner:='Niemand';
end;

end.


Das Problem liegt darin, dass in der ersten Prozedur, in der die Überprüfung stattfindet nur entweder überprüft wird, ob die Steine in einer Reihe oder in einer Säule liegen...Irgendwie nicht beides. an dem Else If liegt es nicht, das hab ich schon mit einem einfachen if ausprobiert. Er überprüft immer das, was oben steht ich kann das auch tauschen, dann überprüft er das Andere.
Wäre super, wenn mir jemand sagen könnte, woran das liegt. :-)
jakobwenzel
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1889
Erhaltene Danke: 1

XP home, ubuntu
BDS 2006 Prof
BeitragVerfasst: Do 15.03.07 20:46 
Es muss an dem Else vor If i<=2 then liegen.
Dadurch werden bei Reihen <3 die Spalten nicht geprüft.

_________________
I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
Paddii Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 28

WinXP Prof.
Blitz3D, PureBasic 4, Delphi 6
BeitragVerfasst: Do 15.03.07 20:50 
das liegt doch nur an dem else if... ohne else funzt es aber auch nicht, es funzt trotzdem immer nur das was vorangestellt ist
wdbee
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 628
Erhaltene Danke: 1



BeitragVerfasst: Do 15.03.07 22:05 
Ich habe es nur mal überflogen, aber du solltest explizit die Blöcke angeben, die du haben willst.
Die For-Schleifen enden wegen der fehlenden Beginn-End-Anweisungen nach dem ersten IF-Statement (wenn das Else weggelassen wird).

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
  for I ...
  begin
    for J ...
    begin
      // Alle Bedingungen mit I und J abarbeiten ...
    end;
  end;


Und was soll denn die zweifach doppelte Prüfung Wenn wahr=wahr dann ... aber wenn nicht wahr = nicht wahr dann ...?
Es reicht doch, wenn wahr, dann ... ansonsten ... !

ausblenden Delphi-Quelltext
1:
2:
3:
4:
  if Wechsel then 
    Feld.Cells[Feld.Col, j] := 'X'  
  else
    Feld.Cells[Feld.Col, j] := 'O';
DrRzf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 260

Win XP Prof
D7 Enterprise
BeitragVerfasst: Fr 16.03.07 03:14 
du musst den gesamten bereich der schleife in ein begin..end setzen und das else in der mitte rauswerfen.
sonst macht er dir die zweite abfrage nur wenn die erste bedingung nicht erfüllt ist.

ausblenden volle Höhe 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:
var  
  Form1: TForm1;  
  SaveFeld: Integer;  
  Wechsel: Boolean;  
  Gewinner: String;  

 
implementation  

 
{$R *.DFM}  

 
procedure Abfrage(Feld: TStringGrid);  
var i,j:Integer;  
begin  
  For i:=0 to 5 do  
    For j:=0 to 6 do
      begin //begin der schleifen   
      If j<=3 then  //begin des ersten abfrageblockes
        begin  
        If (Feld.Cells[j,i]='O')  
          and (Feld.Cells[j+1,i]='O')  
          and (Feld.Cells[j+2,i]='O')  
          and (Feld.Cells[j+3,i]='O') then  
          Gewinner:='O'  
        Else If (Feld.Cells[j,i]='X')  
          and (Feld.Cells[j+1,i]='X')  
          and (Feld.Cells[j+2,i]='X')  
          and (Feld.Cells[j+3,i]='X') then  
          Gewinner:='X';  
        end  //ende des ersten abfrageblockes
      If i<=2 then  //das else rausschmeissen
        begin  //begin des zweiten abfrageblockes
        If (Feld.Cells[j,i]='O')  
          and (Feld.Cells[j,i+1]='O')  
          and (Feld.Cells[j,i+2]='O')  
          and (Feld.Cells[j,i+3]='O') then  
          Gewinner:='O'  
        Else If (Feld.Cells[j,i]='X')  
          and (Feld.Cells[j,i+1]='X')  
          and (Feld.Cells[j,i+2]='X')  
          and (Feld.Cells[j,i+3]='X') then  
          Gewinner:='X';
        end; //ende des zweiten abfrageblockes
      end; //hier noch das end für die schleifen
end;


die nächste frage was sich stellt, ob es nicht klüger währe die spalten und zeilen separat zu überprüfen.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
For i:=0 to 5 do  
  For j:=0 to 3 do
    //abfrage auf spalten 

For i:=0 to 2 do  
  For j:=0 to 6 do
    //abfrage auf zeilen

_________________
rein statistisch gesehen darf man keiner statistik trauen die man nicht selbst gefälscht hat.
alzaimar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2889
Erhaltene Danke: 13

W2000, XP
D6E, BDS2006A, DevExpress
BeitragVerfasst: Fr 16.03.07 08:12 
Wie prüfe ich effizient, ob irgendwo 4 Steine in einer Reihe liegen (waagerecht, diagonal, senkrecht)?

Hmm. Für jeden Stein der Farbe A auf dem Spielbrett gehe ich:
Erst nach links und dann nach rechts, solange bis ein Feld eine andere Farbe hat.
Dann das Gleiche mit Oben und unten,
Dann das Gleiche mit rechts oben und links unten
Dann das Gleiche mit rechts unten und links oben.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Function FindeMaximaleReihe(aSpielfeld : TSpielFeld; aFarbe : TFarbe; aBreite, aHoehe : Integer) : Integer;
Var
  r, i, j, di, dj : Integer;

Begin
  Result := 0;
  For i:=0 to aBreite Do
    For j:= 0 to aHoehe Do
      If aSpielfeld[i,j] = aFarbe Then Begin
        r := ZaehleReihe (aSpielfeld, i, j);
        If r>Result Then
          Result := r;
      End
End;


Fehlt nur noch die Funktion, die die Anzahl der Reihen zählt:
ausblenden volle Höhe 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:
Function ZaehleReihe (aSpielfeld : TSpielfeld; aBreite, aHoehe, i,j : Integer) : Integer;
Const
//                                               |      -      \       /
  cRichtung : Array [0..3,0..1] Of Integer = ( (0,1), (1,0), (1,1), (-1,1) );

// wir müssen in beide Richtungen
  cVorzeichen : Array [0..1] Of Integer = (-1,1);
  
Var
  Farbe, k, s, r, di, dj, i0, j0 : Integer;

Begin
  Result := 0;
  Farbe := aSpielfeld[i,j];
  For k := 0 to 3 do begin // Für jede Richtung
    r := 1;
    for s := 0 to 1 do begin  // sowohl in die eine als auch in die andere Richtung
      di := cRichtung[k,0]*cVorzeichen[s];
      dj := cRichtung[k,1]*cVorzeichen[s];
      i0 := i + di;
      j0 := j + dj;
// Solange wir uns noch auf dem Spielfeld befinden und das untersuchte Feld die gleiche Farbe hat ...
      while (i0>=0) and (j0>=0) and (i0<=aBreite) or (j<=aHoehe) and (aSpielfeld[i0,j0]=Farbe) do begin
        inc (i0,di);  // weiter bewegen
        inc (j0,dj);
        inc(r);       // und den Zähler hochzählen.
        // if r= 4 then break; // <<-- wenn nur auf gewinn geprüft wird
      End;
     // if r= 4 then break; // <<--  wenn nur auf gewinn geprüft wird      
    End;
    if r>Result Then Result := r;
  End
End;


Zugegeben, nicht gerade kurz. Es hat aber den Vorteil, das die Routine (ungetestet) die Anzahl der Steine in einer Reihe zurückgibt. Wenn Du dann mal einen echten Computergegner programmieren willst, dann weisst Du dann gleich, wie gut die Stellung ist.

Die Funktion 'ZaehleReihe' kann man noch optimieren, denn es ist ja egal, ob man 4 oder 8 Steine in einer Reihe hat, gewonnen hat man in jedem Fall.

_________________
Na denn, dann. Bis dann, denn.
Paddii Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 28

WinXP Prof.
Blitz3D, PureBasic 4, Delphi 6
BeitragVerfasst: Fr 16.03.07 15:26 
ah jaa...verdammt, dass ich das übersehen hab mit dem begin-end tag...dann ist natürlich klar
und danke für die anderen ideen, die abfrage, ob 4 steine in einer Reihe sind ist absolut nicht performance optimiert, aber ich denke für das prog ist das im mom auch nicht wirklich nötig xD