Autor |
Beitrag |
n1con
Hält's aus hier
Beiträge: 12
Erhaltene Danke: 1
Win7 Ultimate x64
Delphi 6, Delphi 2007
|
Verfasst: Do 08.09.11 03:55
Hallo,
ich habe vor einiger Zeit ein neues Projekt begonnen. Und zwar Vier Gewinnt.
Ich benutze dafür eine StringGrid als Spielfeld. Soweit kann das Programm sagen, welcher Spieler am Zug ist. Außerdem fällt jeder Stein an die richtige Position. Nun habe ich ein Problem damit festzustellen ob ein Spieler gewonnen hat.
Hier ist mein Quellcode den ich bisher habe:
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: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Grids, Menus, StdCtrls, ComCtrls;
type TForm1 = class(TForm) StringGrid1: TStringGrid; StatusBar1: TStatusBar; Edit1: TEdit; Edit2: TEdit; Button1: TButton; MainMenu1: TMainMenu; Neu1: TMenuItem; NeuesSpiel1: TMenuItem; Ende1: TMenuItem; Hilfe1: TMenuItem; About1: TMenuItem; MeinBlog1: TMenuItem; Label1: TLabel; procedure StringGrid1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject);
private public end; procedure naechsterspieler; var Form1: TForm1; amzug : integer; Name1, Name2 : string; gestartet : boolean;
implementation
{$R *.dfm}
function CheckWinner(x,y : integer) : Integer; var i, links, rechts, k, l : Integer; begin k:= 1; l:= 1; links:= 0; rechts:= 0; for i:= 1 to 3 do begin
if (x-3) < 0 then begin if Form1.StringGrid1.Cells[x,y] <> Form1.StringGrid1.Cells[x+i,y] then begin result:= 0; exit; end end
else if (x+3) > 7 then begin if Form1.StringGrid1.Cells[x,y] <> Form1.StringGrid1.Cells[x-i,y] then begin result:= 0; exit; end; end;
end; result:= 1;
end;
procedure TForm1.StringGrid1Click(Sender: TObject); var x,y : integer; begin if gestartet then begin x:= Stringgrid1.Col; y:= Stringgrid1.Row; if amzug = 1 then begin y:= StringGrid1.RowCount-1; if StringGrid1.Cells[x,StringGrid1.RowCount-1] = '' then begin y:= StringGrid1.RowCount-1; StringGrid1.Cells[x,y]:= 'X' end else while StringGrid1.Cells[x,y] <> '' do begin if y<=0 then begin ShowMessage('Ungültiger Zug!'); exit; end else y:= y-1; end; StringGrid1.Cells[x,y]:= 'X'; if CheckWinner(x,y) = 1 then ShowMessage('gewonnen'); end; if amzug = 2 then begin y:= StringGrid1.RowCount-1; if StringGrid1.Cells[x,StringGrid1.RowCount-1] = '' then begin y:= StringGrid1.RowCount-1; StringGrid1.Cells[x,y]:= 'O' end
else while StringGrid1.Cells[x,y] <> '' do begin if y<=0 then begin ShowMessage('Ungültiger Zug!'); exit; end else y:= y-1; end; StringGrid1.Cells[x,y]:= 'O'; if CheckWinner(x,y) = 1 then ShowMessage('gewonnen'); end; naechsterspieler; end; end;
procedure naechsterspieler; begin if amzug= 1 then begin amzug:= 2; Form1.StatusBar1.SimpleText:= Name2+' ist am Zug.'; end else begin amzug:= 1; Form1.StatusBar1.SimpleText:= Name1+' ist am Zug.'; end; end;
procedure TForm1.FormCreate(Sender: TObject); begin amzug:= 1; end;
procedure TForm1.Button1Click(Sender: TObject); var i : Integer; begin if gestartet = false then begin gestartet:= true; Name1:= Edit1.Text; Name2:= Edit2.Text; StatusBar1.SimpleText:= Name1+' ist am Zug.'; Button1.Caption:= 'Spiel Stoppen'; Label1.Caption:= ''; end
else begin gestartet:= false; Button1.Caption:= 'Spiel Starten'; for i:= 0 to (StringGrid1.RowCount - 1) do StringGrid1.Rows[i].Clear; amzug:= 1; StatusBar1.SimpleText:= ''; Label1.Caption:= 'Drücken sie zuerst auf "Spiel Starten".'; end; end;
end. |
Ich hoffe er ist soweit verständlich und ihr könnt mir weiterhelfen.
Vielen Dank
n1con
|
|
Jann1k
      
Beiträge: 866
Erhaltene Danke: 43
Win 7
TurboDelphi, Visual Studio 2010
|
Verfasst: Do 08.09.11 10:19
Wenn ich deinen Code richtig verstehe, versuchst du jeweils zu prüfen, ob die nächsten drei Spielsteine von der gleichen Farbe sind. Problematisch dabei ist, dass der neu eingesetzte Spielstein nicht nur am Anfang bzw. Ende einer Viererkette stehen kann, sondern auch an einer der beiden mittleren Positionen.
Ich würde das ganze lieber so anstellen(angenommen man hat einen roten Spielstein eingeworfen):
Zähle die roten Spielsteine links vom neuen Stein bis man auf einen gelben trifft, zähle die roten Spielsteine rechts vom neuen Stein bis man auf einen gelben trifft, wenn linke Steine + rechte Steine + 1 (für den neuen Stein) >= 4 hat man gewonnen. Analog dazu kannst du die Diagonalen überprüfen. In der Senkrechten ist es einfacher, da du nur nach unten zu zählen brauchst. Das Zählen in einer Richtung kannst du leicht mit einer while Schleife realisieren, dabei aber wieder auf die Grenzen des Spielfeldes achten.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 08.09.11 10:23
Hallo,
In da.zfx.info/forum/vi...der=asc&start=34 war mal eine lustige Diskussion dazu.
Aber was Dir wirklich weiter hilft ist wohl Fiete Version von vier Gewinnt.
www.delphi-forum.de/...t=vier+gewinnt+fiete
Gruß Horst
|
|
n1con 
Hält's aus hier
Beiträge: 12
Erhaltene Danke: 1
Win7 Ultimate x64
Delphi 6, Delphi 2007
|
Verfasst: Do 08.09.11 16:28
@Jann1k: die Idee hatte ich auch mal, hab sie dann aber auch aus Frust beim ersten Widerstand wieder verworfen. (Du kennst das vllt nach 4h Programmieren) Allerdings probiere ich das nochmal so.
Euch beiden schonmal Vielen Dank für die Hilfe. Ich melde mich sobald es erste Erfolge gibt.
LG n1con
|
|
n1con 
Hält's aus hier
Beiträge: 12
Erhaltene Danke: 1
Win7 Ultimate x64
Delphi 6, Delphi 2007
|
Verfasst: Do 08.09.11 17:11
So ich bin jetzt mal soweit Jann1k's Idee nachgegangen. Das ist dabei rausgekommen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| function CheckWinner(x,y : integer) : Integer; var i, links, rechts : Integer; begin links:= 0; rechts:= 0;
for i:= 1 to 3 do begin
if (x+i) < 7 then begin if Form1.StringGrid1.Cells[x,y] = Form1.StringGrid1.Cells[x+i,y] then rechts:= rechts+1; end;
if (x-i) > 0 then begin if Form1.StringGrid1.Cells[x,y] = Form1.StringGrid1.Cells[x-i,y] then links:= links + 1; end;
end; if links+rechts+1 >= 4 then result:= 1;
end; |
Allerdings funktioniert die ganze Geschichte noch nicht ganz hundertprozentig. Einige Situationen erkennt er aber nicht alle. Die die am Rand beginnen erkennt er noch nicht. Ich hoffe ihr könnt mir nochmal helfen.
LG n1con
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 08.09.11 17:32
Hallo,
geht stringgrid nicht bei 0 los?
Also eher:
Delphi-Quelltext 1:
| if (x-i) >= 0 then begin |
Grusz Horst
Für diesen Beitrag haben gedankt: n1con
|
|
n1con 
Hält's aus hier
Beiträge: 12
Erhaltene Danke: 1
Win7 Ultimate x64
Delphi 6, Delphi 2007
|
Verfasst: Do 08.09.11 17:35
Danke ja du hast recht  jetzt funktioniert es.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Do 08.09.11 17:54
Hallo,
Jann1k meinte es wohl mehr in dieser Richtung.
Man bricht die Schleife fruehzeitig ab.
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:
| function CheckWinner(x,y : integer) : Integer; var i, sum : Integer; Spieler : string; begin Spieler := Form1.StringGrid1.Cells[x,y]: sum := 1; i := x+1; while (i < 7) do begin if Form1.StringGrid1.Cells[i,y] = Spieler then inc(sum) else break: inc(i); end; i := x-1; while (i >= 0) do begin if Form1.StringGrid1.Cells[i,y] = Spieler then inc(sum) else break: dec(i); end; if sum >= 4 then result:= 1 else result := 0; end; |
Grusz Horst
|
|
Jann1k
      
Beiträge: 866
Erhaltene Danke: 43
Win 7
TurboDelphi, Visual Studio 2010
|
Verfasst: Do 08.09.11 22:28
Kleine Anpassung von Horst_H Code, damit man auch ohne break auskommt.
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:
| function CheckWinner(x,y : integer) : Integer; var i, sum : Integer; Spieler : string; begin Spieler := Form1.StringGrid1.Cells[x,y]: sum := 1; i := x+1; while (i < 7) and (Form1.StringGrid1.Cells[i,y] = Spieler) do inc(sum) inc(i); end; i := x-1; while (i >= 0) and (Form1.StringGrid1.Cells[i,y] = Spieler) do inc(sum) dec(i); end; if sum >= 4 then result:= 1 else result := 0; end; |
@N1con: Wenn du deinen bisherigen Code ausführlich testest, siehst du dass einige Situationen fälschlicherweise als Gewonnen markiert werden. Z.B. Rot - Rot - Gelb - Rot - Rot wird als gewonnen erkannt, wenn zuletzt das zweite Rot eingeworfen wurde.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 09.09.11 00:17
Und wenn man jetzt noch etwas fleißig ist, erweitert man die Klasse so, dass sie auch für Tic Tac Toe und auf beliebig lange Reihen (vier, fünf, sechs) anwendbar ist. Eigentlich eine schöne Übung.
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Fr 09.09.11 13:24
Hallo,
ich haenge mal meine leicht geaenderte Version von developia an.
Das Prinzip ist dabei ein etwas anderes.
Ich habe fuer jede Spielfarbe fuenf Felder in Groesze des Spielfeldes.
Jeweils eins zur Bestimmung der waagerechten,senkrechten Nachbarn und der auf der Haupt und Nebendiagonalen.
Im fuenften Feld steht die an der Position die maximal erreichte Zahl an Nachbarn.Was aber wenig Sinn macht, aber egal. ( Es fehlt das Wissen an welcher Position man weitermachen sollte etc )
Betrachtet man eine waagerechte Linie, auf der zwei gleicharbige Steine mit einem Abstand liegen:
__X_X__
dann steht im Feld_waagerecht
0010100, die Steine haben nur sich selbst als Nachbarn.
Wirft man nun einen gleichfarbigen Stein in deren Mitte,
__XXX__ dann betrachtet man das Feld links und rechts davon und summiert die Anzahl aendert sich Feld_waagerecht zu.
0030300 . Also nur an den Enden wird die neue Anzahl der Nachbarn eingetragen, denn es kann auch nur an den Enden spaeter ein Spielstein hinzukommen.
Das hat den Vorteil, dass man im Prinzip auch 17 Gewinnt auf einem 200x 413 Feld spielen kann, ohne dass die Zeit zur Feststellung, ob gewonnen wurde, zunimmt gegenueber 4 gewinnt auf einem 6x7 Feld.
Der Aufwand macht aber nur Sinn, wenn der Computer auch mitspielt.
Grusz Horst
Einloggen, um Attachments anzusehen!
|
|
n1con 
Hält's aus hier
Beiträge: 12
Erhaltene Danke: 1
Win7 Ultimate x64
Delphi 6, Delphi 2007
|
Verfasst: Fr 09.09.11 14:22
Also mittlerweile sieht es bei mir so aus. Ich habe noch keine while Schleife drin, aber so funktioniert es waagerecht schon perfekt. Allerdings funktioniert senkrecht noch nicht ganz. Was habe ich da falsch gemacht?
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:
| function CheckWinner(x, y, dir : integer) : Integer; var i, links, rechts, senkrecht : Integer; begin links:= 0; rechts:= 0; senkrecht:= 0;
for i:= 1 to 3 do begin case dir of 0: begin if (x+i) <= 7 then begin if Form1.StringGrid1.Cells[x,y] = Form1.StringGrid1.Cells[x+i,y] then inc(rechts); end;
if (x-i) >= 0 then begin if Form1.StringGrid1.Cells[x,y] = Form1.StringGrid1.Cells[x-i,y] then inc(links); end; end; 1: begin if (y+i) >= 0 then begin if Form1.StringGrid1.Cells[x,y] = Form1.StringGrid1.Cells[x,y+i] then inc(senkrecht); end; end; end; end; case dir of 0: begin if (links+rechts+1) >= 4 then result:= 1; end;
1: begin if (senkrecht+1) >= 4 then result:= 1; end;
end; end; |
EDIT: Habs selber rausgefunden. Sorry. aber was haltet ihr so mittlerweile davon?
|
|
|