![]() |
Hallo Madeleine, jetzt kommts erstmal dick :mrgreen:
Ich hab dir jetzt mal drei Procedures geschrieben. Ich hatte ja nicht deinen Form Entwurf, dehalb hab ich ne Form gemacht mit folgendem drauf
Zunächst folgende globale Variablen
Delphi-Quellcode:
Die Kommentare dürften für sich sprechen.
var
Form1 : TForm1; w,h : Cardinal; //Höhe und Breite, //Cardinal weil keine negativen Werte erlaubt sind field : Array of Array of Integer; //Spielfeld, 0 = leeres Feld, 1 = blau, 2 = gelb game : boolean = false; //Wird gespielt? Player: integer = 1; //Spieler, 1 = blau, 2 = gelb Dann die Initialisierung im OnClick von ButtonStart:
Delphi-Quellcode:
Ich hab auch hier alles kommentiert, wenn du Fragen hast nur melden.
procedure TForm1.ButtonStartClick(Sender: TObject);
var i,j: integer; begin try begin w := StrToInt(EditW.Text); h := StrToInt(EditH.Text); //Höhe und Breite (w und h) auslesen DrawGrid.ColCount := w; DrawGrid.RowCount := h+1; //Höhe und Breite auf das Grid anwenden SetLength(field,w); //Array auf die richtige Größe bringen for i := 0 to High(field) do begin SetLength(field[i],h); for j := 0 to h-1 do field[i,j] := 0; //alle Felder auf 0, //nötig wenn mehrmals gespielt wird end; DrawGrid.Enabled := true; DrawGrid.Repaint; //neu zeichnen, //auch nötig wenn mehrmals gespielt wird game := true //jetzt wird gespielt end except //im Fehlerfall: zurück das Kommando begin ShowMessage('Fehlerhafte Eingabe'); EditW.SetFocus; exit end end end; Jetzt fehlen nur noch zwei Sachen: Was passiert beim Klick (OnMouseDown) und wie werden die Zellen gezeichnet?
Delphi-Quellcode:
Hier werden die Zellen "gemalt". Wenn es sich nicht um eine Zelle handelt, in der ein Kreis sein soll, wird nichts weiter gemacht.
procedure TForm1.DrawGridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState); begin if (not game) or (ARow = 0) then exit; //wenn kein Spiel am laufen ist, oder die Zeile nicht im Feld ist dann abbrechen //ab dem zweiten Spiel ist egal ob ein Spiel am laufen ist, vorher gibts aber nen Fehler //weil das Array field dann noch nicht initialisiert ist, deshalb die Abfrage case field[ACol,ARow-1] of 1: begin //wenn Spieler = 1 (blau) DrawGrid.Canvas.Brush.Color := clBlue; //Dann blaunen Kuller malen DrawGrid.Canvas.Ellipse(Rect); end; 2: begin //wenn Spieler = 2 (gelb) DrawGrid.Canvas.Brush.Color := clYellow; //Dann gelben Kuller malen DrawGrid.Canvas.Ellipse(Rect) end end end; Jetzt das setzen im OnMouseDown:
Delphi-Quellcode:
So, das wars auch schon (fast), zum schluß noch das Array freigeben:
procedure TForm1.DrawGridMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); var aCol,aRow,i : integer; begin DrawGrid.MouseToCell(X,Y,aCol,aRow); if (aRow <> 0) or (field[aCol,0]<>0) then exit; //Wenn nicht in die 1. Zeile geklickt wurde //oder die Spalte schon voll ist aufhören i := h-1; while field[aCol,i] <> 0 do dec(i); //bestimmen welche die erste freie Zelle ist field[aCol,i] := Player; //Zelle mit Spieler besetzen if Player = 2 then dec(Player) else inc(Player);//Spielerwechsel DrawGrid.Repaint //und neu zeichnen end;
Delphi-Quellcode:
Das Programm funktioniert jetzt soweit, dass man ein spiel starten kann indem man gewünschte Höhe und Breite angibt, und dann auf start klickt. Dann kann man (abwechselnd gelbe und blaue) Kullerdinger auf das Feld werfen. Es prüft jetzt noch nicht auf Sieg und es gibt auch keinen Computerspieler, das müsstest du noch einbauen, oder wir zusammen.
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var i: integer; begin for i := 0 to High(field) do //Array freigeben field[i] := nil; field := nil end; Zum checken auf Sieg hab ich schon was im Kopf, kann ja später mal nen Ansatz posten. Lies dir erstmal den Code durch und guck ob du ihn verstehst, sonnst immer fragen! Gruß, Sebastian |
Uih :shock:
:dancer: :dancer2: das ist ja super! :spin: Danke! Ich habs auch gleich ausprobiert, aber zeichnen macht es noch nicht,klappt das bei dir? Ich werd mich ma auf die Fehlersuche bei mir machen! Um zu prüfen, ob gewonnen oder nicht, kann man ja das field in nen String umwandeln und dann mit Hilfe von pos() Dinge ermitteln wie ('1111')--> gewonnen! |
Hallo Madeleine, bei mir klappts, erstell mal ein neues Project und setz die Komponenten die ich oben angegeben hab auf das Formular, und benenn sie so wies oben steht. Dann musst du noch den Code aus der folgenden Textdatei in die Unit kopieren (vorher alles löschen), und wichtig: Die Komponenten markieren und im Objektinspektor noch die jeweiligen Events zuordnen. (Also ButtonStart: OnClick = ButtonStartClick, etc)
Dann sollte es gehen. Gruß, Sebastian |
Ach ja, wegen dem "auf Sieg checken", das könnte man so machen, aber dann hat man keinen Sieg bei 4 diagonalen Steinen. Ich hab aber schon ne Idee wie man das machen kann, kommt heut noch :mrgreen:
Ich hoffe es klappt jetzt erstmal mit dem Code oben! :hi: Gruß, Sebastian |
Liste der Anhänge anzeigen (Anzahl: 1)
Jetzt hab ich doch tatsächlich die Anlage vergessen :oops:
Hier kommt sie! Ich denke immer mit dem "Durchsuchen" ist es getan. Gruß, Sebastian |
Liste der Anhänge anzeigen (Anzahl: 1)
So jetzt kommt gleich nochmal eine neue Version. Das Spiel ist jetzt beendet wenn einer der Spieler eine senkrechte oder waagerechte Viererreihe hat. Diagonal kommt noch! (Ohne wird es meistens damit enden dass keiner gewinnt).
Die Check-Procedure kann man vielleicht noch verkürzen, aber es funktioniert so. Beachte auch, dass es die Variable "game", mit der ich vorher geprüft hab ob ein Spiel läuft nicht mehr gibt, statt dessen überprüfe ich jetzt beim zeichnen ob das Array<>nil ist, der Vorteil ist der: Nach einem Spiel kann man zwar nichts mehr am Spielfeld verändern, es soll aber noch solange angezeigt werden bis ein neues Spiel gestartet wird. Wenn man in der OnCellDraw procedure aber (über die Variable game) prüft ob ein Spiel läuft, zeichnet sie nicht mehr wenn das Spiel vorbei ist. Gruß, Sebastian |
Zwischenstand
So, bei mir werden jetzt endlich auch blaue und gelbe Kreise gemahlt und warum das nicht geklappt hat, na das laß ich lieber unerwähnt :oops:
Habe erstmal so gemacht, das sich das DrawGrid den Feldern der Größe nach anpasst...sieht eben schöner aus :angle2: DrawGrid.Height:= (h+1)*36 +3; DrawGrid.Width:=w*36+3; ...dabei müssen die Felder aber 35 groß sein. Dann mach ich mich auch mal an die Prüfen ob gewonnen-Prozedur! |
Liste der Anhänge anzeigen (Anzahl: 1)
also ich hab dir mal meine prüfen-ob-gewonnen-Funktion angehängt, das klappt bei mir ganz gut, hast aber Recht, ich weiß noch nicht, wie ich das ganze diagonal noch hinkriege
deine Version hab ich noch nicht ausprobiert *fleißig weiter programmier* :coder: |
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Madeleine, meine Check Funktion sieht jetzt folgendermaßen aus:
Delphi-Quellcode:
So wie ich das sehe sind so alle Möglichkeiten abgedeckt. Gleichzeitig übernimmt sie noch die Textausgabe wenn jemand gewonnen hat. Dazu hab ich noch ein paar kleinere Änderungen an den vorherigen Procedures vorgenommen:
function CheckWinner(const Player,X,Y: integer): boolean;
var i,j,count,code: integer; begin result := true; code := 0; count := 0; //waagerecht for i := X-3 to X+3 do begin if i in [0..pred(w)] then if field[i,Y] = Player then inc(count) else count := 0; if count = 4 then begin code := 1; break end end; count := 0; //senkrecht if code=0 then for i := Y-3 to Y+3 do begin if i in [0..pred(h)] then if field[X,i] = Player then inc(count) else count := 0; if count = 4 then begin code := 2; break end end; count := 0; j := Y-3; if code = 0 then //diagonal for i := X-3 to X+3 do begin if (i in [0..pred(w)]) and (j in [0..pred(h)]) then if field[i,j] = Player then inc(count) else count := 0; if count = 4 then begin code := 3; break end; inc(j) end; count := 0; j := Y+3; if code = 0 then //diagonal for i := X-3 to X+3 do begin if (i in [0..pred(w)]) and (j in [0..pred(h)]) then if field[i,j] = Player then inc(count) else count := 0; if count = 4 then begin code := 4; break end; dec(j) end; case code of 1: begin Caption := 'Spieler '+IntToStr(Player)+' hat gewonnen (-)'; DrawGrid.Enabled := false end; 2: begin Caption := 'Spieler '+IntToStr(Player)+' hat gewonnen (|)'; DrawGrid.Enabled := false end; 3: begin Caption := 'Spieler '+IntToStr(Player)+' hat gewonnen (\)'; DrawGrid.Enabled := false end; 4: begin Caption := 'Spieler '+IntToStr(Player)+' hat gewonnen (/)'; DrawGrid.Enabled := false end; else result := false end end; 1. Die Initialisierungsprozedur prüft jetzt auch ob die Werte größer als 4 sind:
Delphi-Quellcode:
2. Es wird ausgegeben wer dran ist (Im OnMouseDown, da ist auch die Check Funktion untergebracht)
try
begin w := StrToInt(EditW.Text); h := StrToInt(EditH.Text); //Höhe und Breite (w und h) auslesen if (w<4) or (h<4) then raise Exception.Create('Zu kleine Werte'); DrawGrid.ColCount := w; DrawGrid.RowCount := h+1; //Höhe und Breite auf das Grid anwenden SetLength(field,w); //Array auf die richtige Größe bringen for i := 0 to High(field) do begin SetLength(field[i],h); for j := 0 to h-1 do field[i,j] := 0; //alle Felder auf 0, //nötig wenn mehrmals gespielt wird end; DrawGrid.Enabled := true; DrawGrid.Repaint; //neu zeichnen, //auch nötig wenn mehrmals gespielt wird Caption := 'Spieler 1: blau; Spieler 2 : gelb'; //Caption ändern Player := 1 //blau fängt an end except on E: Exception do //im Fehlerfall: zurück das Kommando begin ShowMessage(E.Message); EditW.SetFocus; exit end end;
Delphi-Quellcode:
Ich hoffe ich hab jetzt nichts vergessen, alles zusammen häng ich nochmal als Anlage dran. Nicht falsch verstehen, deine Funktion tuts natürlich auch, und durch selbst machen lernt man natürlich am besten, aber du kannst dir diese ja auch mal angucken und sehen ob du síe verstehst und möglicherweise Teile davon bei dir einbauen.
begin
... field[aCol,i] := Player; //Zelle mit Spieler besetzen DrawGrid.Repaint; //und neu zeichnen if CheckWinner(Player,aCol,i) then exit; if Player = 2 then begin dec(Player); Caption := 'Spieler 1 (blau) ist an der Reihe' end else begin inc(Player); Caption := 'Spieler 2 (gelb) ist an der Reihe' end end; Gruß, Sebastian |
nee, so wie du das gemacht hast, ist es schon viel ausgeklügelter, da kann ich sogar noch einiges für den Computergegner verwenden,danke!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz