Autor |
Beitrag |
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Do 10.06.10 19:37
Hey,
da musst du dir ein neues Array anlegen. Die Prozedur CheckDominos würd ich umbenennen, weil man so schnell durcheinander kommt (CheckDomino <> CheckDomino s) nenn sie doch GetAllPosiblePos, BruteFocePosition oder sowas in der Art. Am anfang leerst du das Array (Bsp.: PosiblePositionList) mit SetLength(0). Dann kommen 3 Schleifen (2 hast du ja schon richtig). Schleife für X, Schleife für Y un Schleife für Drehen. Dann probierst du alle Schleifen durch, und wenn CheckDomino = TRUE, dann wird AddPosiblePos aufgerufen. Da übergibst du einfach das Domino-Record un schreibst das wie bei dem DominoList-Array in das Array rein.
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var Domino: TDomino; für alle X-Positionen mache... X-Position von Domino ändern für alle Y-Positionen mache... Y-Position von Domino ändern für alle drehungen mache... wenn CheckDomino(Domin) dann... AddPosiblePos(Domino) drehe Domino |
dann brauchst du nur noch ein beliebiges raus suchen und zu platzieren un das ganze neu zeichnen:
Quelltext 1: 2: 3:
| Domino = suche zufälliges Domino aus der Liste der möglichen Positionen PlaceDomino(Domino) Zeichne das Feld neu |
So in etwas sollte das Funktionieren...
€: galagher hat folgendes geschrieben : | Nie wieder ein Programm, bei dem auch das Programm etwas tun soll!  |
Das is doch aber grad der Reiz am Programmieren  Man brauch da nur bisl Erfahrung, und wenn du das Domino dann fertsch un auch verstanden hast, dann sollte dir das bei andern KIs, die du evtl mal programmierst leichter fallen...
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Do 10.06.10 19:54
Bergmann89 hat folgendes geschrieben : | Das is doch aber grad der Reiz am Programmieren Man brauch da nur bisl Erfahrung, und wenn du das Domino dann fertsch un auch verstanden hast, dann sollte dir das bei andern KIs, die du evtl mal programmierst leichter fallen... |
Leider fange ich immer wieder mit derartigen - grafischen - Programmen an, zulezt mit einem Mensch ärgere dich nicht, bei dem ich die Grafik, die Kegel, den Würfel, dessen Punkte, die Züge am Brett, Teile der Logik und Teile des Arrays hatte, und scheiterte an der Umsetzung im Array, weil ja jeder der 4 Spieler woanders anfängt... Alles lief mir auseinander, wurde immer komplexer und alle Ideen, die ich hatte, konnte ich letztlich nicht zusammenführen.
Ebenso hier:
www.delphi-forum.de/...ighlight=bauernspiel
Diverse Zusatzfunktionen, die Oberfläche und Interaktion mit dem Benutzer habe ich selbst entwickelt, aber die eigentliche Logik, das Spiel, stammt von alzaimar.
Dennoch gebe ich hier, bei Domino, nicht auf!
@Bergmann89:
Kann aber sein, dass ich noch oft nachfrage!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 11.06.10 17:26
Hallo!
Ich habe eine Prozedur geschrieben (besser: Copy & Paste), die genau dasselbe macht wie CheckDomino, nur trägt es die möglichen "Plätze" nicht in das Array DominoList, sondern in AllPlacesList ein. Dann dachte ich, braucht man doch nur einen "Platz" per Random auswählen und schon spielt das Programm flexibel.
Ok, hier meine Ergebnisse - kurz dazu: Es funktioniert nur leider nicht.
Zuerst die Prozedur, die alle Möglichkeiten finden soll:
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:
| procedure TForm1.FindAllPlaces(d: TDomino); var
d2: TDomino; P1, P2, P3, P4: TPoint; i: Integer;
contact: Boolean;
function GetDist(P1, P2: TPoint): Integer; begin result := Abs(P1.X-P2.X) + Abs(P1.Y-P2.Y); end;
begin contact := false;
P1 := Point(d.X, d.Y); if d.Dir = diHorz then begin P2 := Point(d.X + 1, d.Y); end else begin P2 := Point(d.X, d.Y + 1); end;
for i := 0 to High(AllPlacesList) do begin d2 := AllPlacesList[i]; P3 := Point(d2.X, d2.Y); if d2.Dir = diHorz then begin P4 := Point(d2.X + 1, d2.Y); end else begin P4 := Point(d2.X, d2.Y + 1); end;
if (GetDist(P1, P3) = 0) then exit; if (GetDist(P1, P3) = 1) then begin Contact := true; if (d.P1 <> d2.P1) then exit; end; if (GetDist(P1, P4) = 0) then exit; if (GetDist(P1, P4) = 1) then begin Contact := true; if (d.P1 <> d2.P2) then exit; end; if (GetDist(P2, P3) = 0) then exit; if (GetDist(P2, P3) = 1) then begin Contact := true; if (d.P2 <> d2.P1) then exit; end; if (GetDist(P2, P4) = 0) then exit; if (GetDist(P2, P4) = 1) then begin Contact := true; if (d.P2 <> d2.P2) then exit; end; end; if not contact and (Length(AllPlacesList) > 0) then exit;
SetLength(AllPlacesList, Length(AllPlacesList) + 1); AllPlacesList[High(AllPlacesList)] := d; end; |
Und das ist die Prozedur, die obiges verwendet:
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:
| procedure TForm1.Button1Click(Sender: TObject); var x, y, n, h, tmp: Integer; aBitmap: TBitmap; begin iTalon := 0;
aBitmap := TBitmap.Create;
try aBitmap.Assign(imgStein.Picture.Bitmap);
Domino.X := 0; Domino.Y := 0; n := 0; h := 0;
for x := 0 to Board.Width do for y := 0 to Board.Height do begin FindAllPlaces(Domino); if Domino.Dir = diVert then begin tmp := Domino.P1; Domino.P1 := Domino.P2; Domino.P2 := tmp; Domino.Dir := diHorz; end else begin Domino.Dir := diVert; Inc(h); end;
Inc(n);
if n = 3 then begin Inc(Domino.X); n := 0; end;
end;
if Domino.Dir = diHorz then Drehen90Grad(aBitmap); if Odd(h) then begin Drehen90Grad(aBitmap); Drehen90Grad(aBitmap); end;
Domino := AllPlacesList[Random(High(AllPlacesList))]; Board.Canvas.Draw(Domino.X * iStoneWidth, Domino.Y * iStoneWidth, aBitmap);
finally aBitmap.Free; end; end; |
Dabei hängt das Programm, oder es rechnet eben solange. Es klappt einfach nicht, aber es sollte doch? 1. Finde alle Möglichkeiten, 2. wähle eine aus. Was ist da falsch?
//Edit:
Mir ist klar, dass in dem Programm diverser Coder mehrfach vorkommt, ich sollte dies natürlich alles vereinfachen, aber im Moment ist mir das egal, solange es nur läuft!
--- Moderiert von Narses: Beiträge zusammengefasst---
Beim Prüfen der umgebenden Steine muss ich DominoList verwenden, nicht AllPlacesList. Jetzt hängt das Programm zwar nicht mehr, setzt aber die meisten Steine irgendwo, teilweise auf einen bereits abgelegten Stein drauf.
Wenn ich statt Random den 1. Array-Eintrag verwende - Domino := AllPlacesList[0] - legt er jeden Stein immer an der selben Position ab - übereinander.
Ich blicke da nicht durch. 
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Sa 12.06.10 02:35
Hey,
mach es mal so wie ich gesagt hab un teil den Code mal in die Prozeduren und Funktionen auf, dann kann man auch den Überblick behalten. Was du da ganz unten in dem Button machst, da blick ich nämlich auch nich mehr durch
Also:
Funktion, die prüft, ob ein Stein da abgelegt werden kann oder nicht (Bsp.: CheckDomino)
Prozedur, die das Array mit den möglichen Positionen neu füllt (Bsp.: FindAllPosiblePlaces)
Prozedur, die das Domino in der Liste der Möglichen Positionen ablegt (Bsp.: AddToPosiblePlaces)
Prozedur, die einen Domino ablegt (Bsp.: PlaceDomino)
Prozedur, die das Domino (ohne Image) dreht (Bsp.: RotateDomino)
So is der Überblick besser un du hast aussagekräftige Namen für die Prodezuren/Funktionen. Dein FindAllPlaces müsste eig. CheckDomino heißen, weil es ja gar keine Plätze sucht, sondern nur überprüft!
Bei der Suche sind die Schleifen X und Y dazu gedacht die Position vom Domino durchzuzählen, also musst du der Position vom Domino auch die Werte der Schleife zuweisen, sonst passiert gar nix. Guck dir nochma den PseudoCode aus meinem Letzten Beitrag an.
Das Drehen passiert mithilfe einer 3. Schleife in den 2 ersten Schleifen, die von 0 bis 3 geht. Damit du weißt, wie oft du die Image drehen musst, musst du dein TDomino noch um einen Wert erweitern, meinetwegen ImgRotate oder so. Das ImgRotate musst du natürlich auch den aktuekllen Wert der Schleife geben.
Wenn CheckDomino mit den aktuellen Werten dann TRUE ist, legst du mit AddToPosiblePlaces den Stein im Array ab, in dem du später die Position per Zufall raus suchst.
Wenn du dann dein Domino per Zufall aus dem Array raus gesucht hast, drehst du die Image mit ner Schleife so oft, wie ImgRotate es dir vorgibt und dann legst du das Domino ab (PlaceDomino).
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 12.06.10 09:00
Hallo!
Ich verstehe nicht, warum mein Ansatz nicht funktioniert.
Bergmann89 hat folgendes geschrieben : | Funktion, die prüft, ob ein Stein da abgelegt werden kann oder nicht (Bsp.: CheckDomino) |
Also wie CheckDomino, aber mit einem anderen Array und ohne den Aufruf PlaceDomino?
Bergmann89 hat folgendes geschrieben : | Prozedur, die das Array mit den möglichen Positionen neu füllt (Bsp.: FindAllPosiblePlaces) |
Das macht CheckDomino doch schon mit PlaceDomino:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TForm1.PlaceDomino(d: TDomino); begin SetLength(DominoList, Length(DominoList) + 1); DominoList[High(DominoList)] := d; end; |
Bergmann89 hat folgendes geschrieben : | Prozedur, die das Domino in der Liste der Möglichen Positionen ablegt (Bsp.: AddToPosiblePlaces) |
Das verstehe ich leider absolut gar nicht... In ein Array? Das tut doch PlaceDomino auch?
Bergmann89 hat folgendes geschrieben : | Prozedur, die einen Domino ablegt (Bsp.: PlaceDomino) |
Das verstehe ich wieder! Wie PlaceDomino, aber in ein anderes Array.
Bergmann89 hat folgendes geschrieben : | Prozedur, die das Domino (ohne Image) dreht (Bsp.: RotateDomino) |
Also einfach dieses als eingene Prozedur schreiben und dann einfach nur die Prozedur aufrufen?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| if Domino.Dir = diVert then begin tmp := Domino.P1; Domino.P1 := Domino.P2; Domino.P2 := tmp; Domino.Dir := diHorz; end else Domino.Dir := diVert; |
Bergmann89 hat folgendes geschrieben : | Dein FindAllPlaces müsste eig. CheckDomino heißen, weil es ja gar keine Plätze sucht, sondern nur überprüft! |
Das füllt doch aber ein Array, und zwar immer dann, wenn ein Stein passt?
--- Ok, ich werde sehen, wie weit ich komme.
--- Moderiert von Narses: Beiträge zusammengefasst---
Hallo!
Ok, ich war nicht faul und habe folgendes gebastelt:
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:
| var DominoList, DominoPossibleList: TDominoArray;
function TForm1.Check_if_DominoPossible(d: TDomino): Boolean; var
d2: TDomino; P1, P2, P3, P4: TPoint; i: Integer;
contact: Boolean;
function GetDist(P1, P2: TPoint): Integer; begin result := Abs(P1.X-P2.X) + Abs(P1.Y-P2.Y); end;
begin result := false; contact := false;
P1 := Point(d.X, d.Y); if d.Dir = diHorz then begin P2 := Point(d.X + 1, d.Y); end else begin P2 := Point(d.X, d.Y + 1); end;
for i := 0 to High(DominoList) do begin d2 := DominoList[i]; P3 := Point(d2.X, d2.Y); if d2.Dir = diHorz then begin P4 := Point(d2.X + 1, d2.Y); end else begin P4 := Point(d2.X, d2.Y + 1); end;
if (GetDist(P1, P3) = 0) then exit; if (GetDist(P1, P3) = 1) then begin Contact := true; if (d.P1 <> d2.P1) then exit; end; if (GetDist(P1, P4) = 0) then exit; if (GetDist(P1, P4) = 1) then begin Contact := true; if (d.P1 <> d2.P2) then exit; end; if (GetDist(P2, P3) = 0) then exit; if (GetDist(P2, P3) = 1) then begin Contact := true; if (d.P2 <> d2.P1) then exit; end; if (GetDist(P2, P4) = 0) then exit; if (GetDist(P2, P4) = 1) then begin Contact := true; if (d.P2 <> d2.P2) then exit; end; end; if not contact and (Length(DominoList) > 0) then exit;
result := True; end;
procedure TForm1.FindAllPosiblePlaces; begin end;
procedure TForm1.PlacePossibleDomino(d: TDomino); begin SetLength(DominoPossibleList, Length(DominoPossibleList) + 1); DominoPossibleList[High(DominoPossibleList)] := d; end;
procedure TForm1.RotateDomino(var d: TDomino); var tmp: Integer; begin with d do if Dir = diVert then begin tmp := P1; P1 := P2; P2 := tmp; Dir := diHorz; end else Dir := diVert; end; |
Das ist alles. Ich habe keine Ahnung, was ich sonst noch tun soll...
@ Bergmann89
Ich stecke hier fest, habe aber Verständnis, dass du mir (oder sonst jemand) den Code nicht als Fertiggericht servierst. Ich möchte ja auch selber kochen, aber hier bin ich echt überfordert!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Sa 12.06.10 15:50
Hey,
langsam wirds, aber bisl was hast du noch verdreht. Dein PlacePossibleDomino ist die Prozedur, die ein Domino in der Liste der möglichen Positionen ablegt, die hieß bei mir AddToPosibilePlaces. PlaceDomino war dazu gedacht das Domino auf dem Feld, also im DominoList-Array abzulegen. Bei FindAllPosiblePlaces soll das Proggi alle Stellen des Feldes durchgehen, dazu 3 Schleifen (siehe letzer und vorletzter Beitrag von mir). Du musst auch drauf achten was wir schreiben, kahm schon vieles doppelt. Da hilft es immer, wenn man sich sowas wie ne To-Do-Liste anlegt, wo man alles rein schreibt was hier genannt wurde. Un dann kann man das systematisch abarbeiten
Ma noch ne Frage nebenbei: Wie gut bist du in Englisch? Ich hab so das Gefühl, das du mit den englischen Prozedurnamen bisl durcheinander kommst. (Vlt sollt ich die in Zukunft deutsch machen)
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 12.06.10 16:28
Hallo!
Bergmann89 hat folgendes geschrieben : | Dein PlacePossibleDomino ist die Prozedur, die ein Domino in der Liste der möglichen Positionen ablegt, |
Naja - das soll es ja auch, oder? PlacePossibleDomino = "platziere mögliches Domino" - es platziert alle Möglichkeiten im Array, je einen pro Aufruf!? Genau wie PlaceDomino, nur in ein anderes Array.
Also der Reihe nach, das soll mein Programm tun:
1. Check_if_DominoPossible - Funktion, die prüft, ob ein Stein da abgelegt werden kann oder nicht (Bsp.: CheckDomino)
2. Prozedur, die das Array mit den möglichen Positionen neu füllt (Bsp.: FindAllPosiblePlaces - hier weiss ich nicht, wie diese Prozedur aussehen soll. Was ist hier zu tun?
3. Prozedur, die das Domino in der Liste der Möglichen Positionen ablegt (Bsp.: AddToPossiblePlaces) - Was ist hier zu tun? Was, wo und wie? (Ich weiss, dass das "füge zu möglichen Plätzen hinzu" bedeutet.  )
4. PlaceDomino - Prozedur, die einen Domino ablegt - Habe ich. Funktioniert.
5. RotateDomino - Prozedur, die das Domino (ohne Image) dreht - Habe ich auch und funktioniert auch.
Bergmann89 hat folgendes geschrieben : | Ich hab so das Gefühl, das du mit den englischen Prozedurnamen bisl durcheinander kommst. |
Eher mit dem Inhalt der Prozeduren! Soweit reicht mein Englisch schon! Aber mittlerweile habe ich keinen Plan, keinen Ansatz, wie ich das zum Laufen bringe. Ich meine, es steht da als Code, aber es wird nie genutzt. Das Programm kompiliert und spielt, aber eben nur "ich lege am erstmöglichen Platz ab".
Das habe ich bereits:
Ich habe ein Array, das prüft, welcher Stein schon entnommen wurde - klappt. Daher erkennt das Programm auch, dass der letze Stein weg ist - klappt. Wechsel Spieler/Proggi - klappt. Und dass das Programm etwas Sinnvolles tut, wenn keine Steine mehr da sind, kriege ich auch hin. Und dass es das Spiel beginnt, auch - nur ist das zur Zeit eben eher langweilig, wenn es den 1. Stein immer links oben ablegt. Klar, kann ja nicht anders - das ist der erste mögliche Platz.
Ich weiss einfach nicht, wie ich was wo mache! Nein, theoretisch schon, hast du ja beschrieben, aber ich kann's nicht umsetzen. 
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Sa 12.06.10 19:14
Hey,
guck ma HIER. Da is sogar schon schöner PseudoCode, den man umsetzen kann. Das is jetzt das 3. ma das ich dir sag, das du das angucken sollst. Das is nämlich genau das, was die FindAllPlaces-Methodem machen soll. Wenn ich's jetzt noch ausführlicher hin schreib hast du Code da stehen. Und einfach 1 zu 1 kopieren bringt ja nix (haste ja auch schon festgestellt). Eig hast du alles was du zum lösen brauchst auf dieser Seite des Themas. Noch ein Kleiner Tipp, da das Ganze ja grad ziemlich durcheinander is. Kopier dir dein Projekt in einen Seperaten Ordner, lösch alles was mit dem Ablegen der Dominos, oder iwie mit der KI zu tun hat un schreib es neu. Zur Hilfe kannst du in den Alten Code, oder hier ins Forum gucken. Les dir nochma alle Beiträge genau durch, es steht eig. ausführlich genug da, was du machen musst
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: So 13.06.10 08:24
Guten Morgen!
Jetzt endlich habe ich es, aber es ist wieder langsamer geworden. Ich habe ein Array DominoPossibleList zur Aufnahme der möglichen Plätze hinzugefügt und TDomino um den Integer Rotate erweitert, der die Anzahl der Drehungen enthält.
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:
| var DominoList, DominoPossibleList: TDominoArray;
procedure TForm1.FindAllPossiblePlaces(d: TDomino); var
d2: TDomino; P1, P2, P3, P4: TPoint; i: Integer;
contact: Boolean;
function GetDist(P1, P2: TPoint): Integer; begin result := Abs(P1.X-P2.X) + Abs(P1.Y-P2.Y); end;
begin contact := false;
P1 := Point(d.X, d.Y); if d.Dir = diHorz then begin P2 := Point(d.X + 1, d.Y); end else begin P2 := Point(d.X, d.Y + 1); end;
for i := 0 to High(DominoList) do begin d2 := DominoList[i]; P3 := Point(d2.X, d2.Y); if d2.Dir = diHorz then begin P4 := Point(d2.X + 1, d2.Y); end else begin P4 := Point(d2.X, d2.Y + 1); end;
if (GetDist(P1, P3) = 0) then exit; if (GetDist(P1, P3) = 1) then begin Contact := true; if (d.P1 <> d2.P1) then exit; end; if (GetDist(P1, P4) = 0) then exit; if (GetDist(P1, P4) = 1) then begin Contact := true; if (d.P1 <> d2.P2) then exit; end; if (GetDist(P2, P3) = 0) then exit; if (GetDist(P2, P3) = 1) then begin Contact := true; if (d.P2 <> d2.P1) then exit; end; if (GetDist(P2, P4) = 0) then exit; if (GetDist(P2, P4) = 1) then begin Contact := true; if (d.P2 <> d2.P2) then exit; end; end; if not contact and (Length(DominoList) > 0) then exit;
SetLength(DominoPossibleList, Length(DominoPossibleList) + 1); DominoPossibleList[High(DominoPossibleList)] := d; end;
procedure TForm1.Button1Click(Sender: TObject); var x, y, n, h: Integer; aBitmap: TBitmap; begin aBitmap := TBitmap.Create;
try aBitmap.Assign(imgStein.Picture.Bitmap);
Domino.X := 0; Domino.Y := 0; Domino.Rotate := 0; n := 0; h := 0;
SetLength(DominoPossibleList, 0);
for x := 0 to Board.Width do for y := 0 to Board.Height do begin FindAllPossiblePlaces(Domino);
RotateDomino(Domino);
Inc(h); Domino.Rotate := h;
Inc(n);
if n = 3 then begin Inc(Domino.X); n := 0; end;
if Domino.X >= Board.Width then begin Domino.X := 0; Inc(Domino.Y); end;
if Domino.Y >= Board.Height then break; end;
caption:=inttostr(High(DominoPossibleList)); if High(DominoPossibleList) < 0 then exit;
Domino := DominoPossibleList[Random(High(DominoPossibleList))];
if (Domino.Rotate <> 4) then for n := 0 to Domino.Rotate-1 do Drehen90Grad(aBitmap);
CheckDomino(Domino);
DrawStone(aBitmap);
finally aBitmap.Free; end; end; |
@ Bergmann89
Ist zwar nicht so, wie du es gemeint hast, da blicke ich wirklich nicht durch! So funktioniert es jedenfalls, ich weiss nur nicht, warum es wieder langsamer ist. Kann man vielleicht noch optimieren.
//Edit: @ Bergmann89 - Danke dir für deine vielen Tipps!
//Edit:
Jetzt verstehe ich auch "AddToPossiblePlaces" und "FindAllPossiblePlaces"! - Und genau so oder zumindest sehr ähnlich habe ich es eingebaut - der Rest ist Oberfläche und Drumherum!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 16.06.10 22:17
Hallo!
Jetzt habe ich ein neues Problem: Wie verhindere ich, dass Steine "abgeschnitten" abgelegt werden können? Keiner meiner Ansätze waren wirklich erfolgreich, zB. klappt dieses nur sehr bedingt - das Programm hält sich nicht dran:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| function TForm1.CheckDomino(d: TDomino): Boolean; begin
if d.Dir = diVert then begin if d.X*iStoneWidth+iStoneHeight > Board.Width then exit; if d.Y*iStoneWidth+iStoneHeight+iStoneWidth > Board.Height then exit; end else begin if d.X*iStoneWidth+iStoneHeight+iStoneWidth > Board.Width then exit; if d.Y*iStoneWidth+iStoneHeight > Board.Height then exit; end;
SetLength(DominoList, Length(DominoList) + 1); DominoList[High(DominoList)] := d;
result := True; |
Das Bild im Anhang zeigt, was ich meine! Kann mir bei der Lösung dieses Problems jemand helfen?
Einloggen, um Attachments anzusehen!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Mi 16.06.10 22:23
Hey,
setz einfach deine Spielfeldgröße auf ein Vielfaches von 32 (bzw. auf ein Vielfaches der DominoBreite), das sollte das Problem lösen...
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mi 16.06.10 22:57
Bergmann89 hat folgendes geschrieben : | setz einfach deine Spielfeldgröße auf ein Vielfaches von 32 (bzw. auf ein Vielfaches der DominoBreite), das sollte das Problem lösen... |
Meinst du die Breite und Höhe des Spielfeld-Images? Das habe ich derzeit so: Board.SetBounds(0, 0, 600, 600); Genau, wie ich es brauche. Wenn ich nun statt 600 wesentlich höhere Werte nehme, wird das an sich transparente Image weiss (?), wenn das Programm seinen Stein berechnet!
Ausserdem brauche ich rechts neben dem Spielfeld einen freien Platz, weil ich dort noch ein paar Buttons unterbringen möchte.
//Edit: Verstehe - multiplizieren! Denke, jetzt hab ich's! Danke! 
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Do 17.06.10 21:36
galagher hat folgendes geschrieben : | //Edit: Verstehe - multiplizieren! Denke, jetzt hab ich's! Danke!  |
Das löst das Problem leider nicht oder ich habe die Lösung nicht verstanden. Ich dachte, wenn ich eine Spielfeldhöhe und -breite wähle, die zB. 15x die Breite der Steine hat, klappt es.
Jeder Stein hat 38 Pixel Breite, also mit zB. 15 multiplizieren, dann hat das Spielfeld 570x570 Pixel und die Steine passen so hinein, dass rechts und unten nichts abgeschnitten wird. Wenn das Programm aber nun einen Stein passend ablegt, dann manchmal auch so, dass entweder eine Hälfte sichtbar ist und die andere nicht mehr auf das Board gezeichnet wird, weil sie ausserhalb ist, oder der ganze Stein nicht im Board ist (im Array schon, nur eben grafisch nicht!).
Ich weiss nicht, wie ich das lösen kann. Die angehängte Grafik zeigt, was ich meine. Der rote Rahmen ist ein Shape.
Einloggen, um Attachments anzusehen!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Do 17.06.10 22:11
Hey,
guck dir ma die Prozedur an, die die möglichen Positionen durchzäht. Da hast du doch ne Abfrage drin, wann er nen "Zeilenumbruch" machen soll, und wann er letztendlich komplett aufhören soll. Oder du hast es mittlerweile über die for-Schleifen gemacht, weiß ich nich mehr. Und da änderst du die Werte einfach, das er nich mehr so weit nach außen und unten läuft...
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Fr 18.06.10 17:12
Hallo!
Die Prozedur FindAllPossiblePlaces durchläuft eine for-Schleife, und das hier sollte sein, was du meinst:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| if d.X >= Board.Width then begin d.X := 0; Inc(d.Y); end;
if d.Y >= Board.Height then break; | ...funktioniert aber nicht, und auch Konstrukte, die die Breite der Steine (38 Pixel) addieren, wie zB. if d.X+38 >= Board.Width then funktionieren nicht.
Hier die ganze Prozedur:
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:
| function TForm1.FindAllPossiblePlaces(d: TDomino): Integer; var x, y, n, h: Integer; begin d.X := 0; d.Y := 0; d.Rotate := 0; n := 0; h := 0; SetLength(DominoPossibleList, 0);
for x := 0 to Board.Width do for y := 0 to Board.Height do begin AddToPossiblePlaces(d);
RotateDomino(d);
Inc(h); d.Rotate := h;
Inc(n);
if n = 3 then begin Inc(d.X); n := 0; end;
if d.X >= Board.Width then begin d.X := 0; Inc(d.Y); end;
if d.Y >= Board.Height then break; end;
Result := High(DominoPossibleList); end; |
//Edit:
Schlimmer noch: Offenbar ist das Spielfeld rechts (und wahrscheinlich auch unten) unbegrenzt! Siehe Grafik!
Einloggen, um Attachments anzusehen!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Fr 18.06.10 19:16
Hey,
die Psoition des Dominos (d.X bzw. d.Y) ist in RasterKoordinaten, also in Abhängikeit der Breite ( 38 ). Um auf die FeldKoordinaten umzurechnen musst du mit 38 Multiplizieren, dann stimmt auich die IF-Abfrage. Das ganze kannst du die aber sparen, den du hast ja die Schleifen, die die Position weiter zählen, also einfach am Anfang der beiden Schleifen die Position des Dominos festlegen. Und danach dann eine Schlefe (0-3) die die Drehungen zählt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| for x := 0 to (Board.Width div 38)-1 do begin for y := 0 to (Board.Height div 38)-1 do begin d.X := 38 * x; d.Y := 38 * y; for n := 0 to 3 do begin d.Rotate := n; AddToPossiblePlaces(d); RotateDomino(d); end; end; end; |
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Sa 19.06.10 08:55
Hallo!
Vielen Dank, aber leider funktioniert das nicht. Es werden nun überhaupt keine Steine mehr abgelegt. Habe erst versucht, deinen Code in mein Programm einzubauen - klappt nicht. Dann ihn 1:1 zu übernehmen - klappt nicht.
//Edit:
Das scheint zu funktionieren, aber ehrlich gesagt, weiss ich nicht, warum! Ich habe es einfach ausprobiert:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| for x := 0 to Board.Width do for y := 0 to Board.Height do begin if (d.X*38 < Board.Width-38) and (d.Y*38 < Board.Height-38) then AddToPossiblePlaces(d);
if d.X >= Board.Width-1 then begin d.X := 0; Inc(d.Y); end;
if d.Y >= Board.Height-1 then break; |
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
galagher 
      
Beiträge: 2556
Erhaltene Danke: 45
Windows 10 Home
Delphi 10.1 Starter, Lazarus 2.0.6
|
Verfasst: Mo 21.06.10 20:05
Hallo!
Ok, nächstes Problem:
Zuerst: Es gibt einen gemeinsamen Talon, aus dem beide Spieler (Mensch und Programm) Steine entnehmen (Random).
Ich habe das Spiel jetzt auf 66 Steine erweitert; klappt soweit alles. Ich habe zur Gewinner-Ermittlung einfach für den Spieler und das Programm je einen Integer als Zähler, der pro abgelegtem Stein um 1 erhöht wird. Wer am Ende des Spiels (=wenn alle Steine abgelegt sind), die höhere Zahl hat, ist Sieger. So weit, so klar.
Nur - wie ermittle ich den Gewinner, wenn eine verbleibende Anzahl an Steinen nirgendwo mehr passt? Ich hatte bei 66 Steinen, 608x608 Pixel Spielfeldgrösse und 38x74 Pixle pro Stein schon mehr als 3 "Rest"steine, die nirgendwo mehr passten.
Das Programm ist dzt. so, dass es erkennt, wenn ein Stein nirgendwo passt, und entsprechende Meldungen ausgibt: "Ich kann nicht ablegen, Sie sind dran" bzw. "Sie können nicht ablegen, ich bin dran".
Wohin das am Spielende führt, ist absehbar: Zu einem endlosen Hin und Her:
Das Programm entnimmt einen der verbliebenen Steine aus dem Talon (hier ist bereits gewiss, dass keiner der verbliebenen Steine mehr passt, nur weiss das Programm das eben nicht!) und sagt: "Ich kann nicht - daher du" - dann nimmt der Spieler einen neuen Stein. Das Programm erkennt, dass der nirgends passt, und sagt: "Du kannst nicht, daher ich", nimmt seinerseits einen Stein, der nirgends passt, und sagt: "Ich kann nicht - daher du" -
"Du kannst nicht, daher ich" - "Ich kann nicht - daher du" - "Du kannst nicht, daher ich" - usw. Das würde ewig so weitergehen.
Kurz: An welcher Stelle prüfe ich - und wie prüfe ich - alle verbliebenen Steine auf "Passen"? So in der Art:
if KeinSteinPasstIrgendwo then ?
Den Rest habe ich: Der Gewinner steht dann anhand seines Zählers fest!
_________________ gedunstig war's - und fahle wornen zerschellten karsig im gestrock. oh graus, es gloomt der jabberwock - und die graisligen gulpen nurmen!
|
|
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Mo 21.06.10 23:16
Wie prüfst du denn jetzt, ob ein Spieler nicht mehr setzen kann? Das sollte sich doch problemlos auf "prüfen, ob kein Spieler mehr setzen kann" erweitern lassen.
|
|
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: Di 22.06.10 10:41
Hey,
Quelltext 1: 2: 3: 4: 5: 6: 7:
| für alle verbleibenden Steine, mache... wenn Stein abgelegt werden kann (CheckDomino, ohne ablegen!), dann... erhöhe Zähler um 1
wenn Zähler gleich null, dann... Textausgabe: "Kein Stein kann mehr abgelegt werden" Spielende |
Das solltest du mit den Funktionen die du bereits hast kein Problem sein
MfG Bergmannn
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
|