| Autor |
Beitrag |
Paddii
      
Beiträge: 28
WinXP Prof.
Blitz3D, PureBasic 4, Delphi 6
|
Verfasst: 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:
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
      
Beiträge: 1889
Erhaltene Danke: 1
XP home, ubuntu
BDS 2006 Prof
|
Verfasst: 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 
      
Beiträge: 28
WinXP Prof.
Blitz3D, PureBasic 4, Delphi 6
|
Verfasst: 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
      
Beiträge: 628
Erhaltene Danke: 1
|
Verfasst: 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).
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| for I ... begin for J ... begin 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 ... !
Delphi-Quelltext 1: 2: 3: 4:
| if Wechsel then Feld.Cells[Feld.Col, j] := 'X' else Feld.Cells[Feld.Col, j] := 'O'; |
|
|
DrRzf
      
Beiträge: 260
Win XP Prof
D7 Enterprise
|
Verfasst: 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.
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 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 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; end; |
die nächste frage was sich stellt, ob es nicht klüger währe die spalten und zeilen separat zu überprüfen.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| For i:=0 to 5 do For j:=0 to 3 do For i:=0 to 2 do For j:=0 to 6 do |
_________________ rein statistisch gesehen darf man keiner statistik trauen die man nicht selbst gefälscht hat.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: 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.
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:
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) );
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 r := 1; for s := 0 to 1 do begin di := cRichtung[k,0]*cVorzeichen[s]; dj := cRichtung[k,1]*cVorzeichen[s]; i0 := i + di; j0 := j + dj; while (i0>=0) and (j0>=0) and (i0<=aBreite) or (j<=aHoehe) and (aSpielfeld[i0,j0]=Farbe) do begin inc (i0,di); inc (j0,dj); inc(r); End; 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 
      
Beiträge: 28
WinXP Prof.
Blitz3D, PureBasic 4, Delphi 6
|
Verfasst: 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
|
|
|