Entwickler-Ecke

Sonstiges (Delphi) - [Tutorial] Game of Life


Nini - Mo 09.03.15 22:14
Titel: [Tutorial] Game of Life
Ich muss für die Schule das Game of life programmieren.
ich habe mir auch schon einen Handlungsplan überlegt und bin schon so weit gekommen, dass ich weiß, dass ich nen timer brauchen und nen stringgrid.

aber jetzt weiß ich nicht mehr weiter. Wie funktionieren die Befehle, die die Zellen die ich makiere (wie gehts das eigentlich) einlesen?

Danach will ich über ein Feld festlegen, dass die makierten schwarz werden und damit wahr sind und die weißen falsch also quasi ein array of boolean, kann das so funktionieren?

weiter weiß ich leider noch nicht :/

danke, wenn ihr mir helfen könntet

und ja, ich habe auch shcon die anderen themen durchgelesen aber ich verstehe das alles einfach überhaupt nicht ;/


Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 09.03.2015 um 21:54
Moderiert von user profile iconNarses: Titel geändert, war: "game of life stringgrid - probleme mit der delphi-sprache"
Moderiert von user profile iconNarses: Titel geändert, war: "[Hausaufgabe] Game of Life".


Narses - Mo 09.03.15 23:19

Moin und :welcome: in der EE!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Ich muss für die Schule das Game of life programmieren.
Ich möchte das gleich zu Anfang festhalten: wir machen hier keine Hausaufgaben. :| Aber wir helfen dir sicher gerne dabei, das gemeinsam hinzukriegen. Wenn du mitmachst und Einsatz zeigst, werden wir das auch schaffen. :zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich habe mir auch schon einen Handlungsplan überlegt und bin schon so weit gekommen, dass ich weiß, dass ich nen timer brauchen und nen stringgrid.
Klar, den Timer bauchst du später, um "Bewegung" in das Ganze zu kriegen, aber ich würde dir als Anfänger erstmal nicht zu einem StringGrid für die Ausgabe raten. :? Das ist etwas friemelig mit dieser Komponente...

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Wie funktionieren die Befehle, die die Zellen die ich makiere (wie gehts das eigentlich) einlesen?
Wie schon gesagt, ich würde das nicht mit einem StringGrid machen. :nixweiss: Statt dessen würde ich dir gerne einen anderen Ansatz für die GUI zeigen wollen: :idea: Starte das Projekt, dann kannst du mit der Maus die Farbe der Zellen durch Anklicken "umdrehen". :think:

Wenn du das soweit als Ausgangspunkt hast, können wir weiter machen. ;)

cu
Narses


Nini - Di 10.03.15 17:28

Danke sehr :)
aber mal eine dumme frage: was bedeutet GUI?

Als nächstes muss ich doch jetzt ja einlesen, welche felder gefärbt sind und welche nicht. dafür benötige ich ja eine neue prozedur, kommt die in einen "start"-button? und wie les ich das dann ein?


WasWeißDennIch - Di 10.03.15 17:35

GUI [http://de.wikipedia.org/wiki/Grafische_Benutzeroberfl%C3%A4che]
Du kannst auch wie von Dir selbst eingangs erwähnt mit einem Array of Boolean arbeiten und die Shapes lediglich zur Ausgabe des aktuellen Zustands verwenden.


Narses - Di 10.03.15 19:30

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber mal eine dumme frage: was bedeutet GUI?
Das hat dir user profile iconWasWeißDennIch ja schon erläutert. :beer:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Als nächstes muss ich doch jetzt ja einlesen, welche felder gefärbt sind und welche nicht. dafür benötige ich ja eine neue prozedur, kommt die in einen "start"-button? und wie les ich das dann ein?
Leider hab ich jetzt grade keine Zeit, hier weiter zu machen (ich hab noch einen Termin). :? Ich schreibe dir später noch was dazu. :zustimm:

cu
Narses


ub60 - Di 10.03.15 23:49

Die Idee mit dem StringGrid ist gar nicht mal so schlecht.

So, das wars schon. Und in Quelltext sind das unter 15 Zeilen.
Ich hoffe, es hilft etwas.

ub60


Narses - Mi 11.03.15 00:57

Moin!

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Ich schreibe dir später noch was dazu.
Soo, jetzt ist später. :D

user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Die Idee mit dem StringGrid ist gar nicht mal so schlecht.
Tja, das ist zugegeben Ansichtssache. :nixweiss: Womit ich sagen möchte, dass das, was ub60 da vorschlägt, durchaus OK ist (es wird zu einer Lösung führen). Ich würde es nur so nicht angehen wollen, da ich ein StringGrid für wenig didaktisch "hilfreich" halte. Aber das ist eben: Ansichtssache. :P

Leider haben wir nun ein Problem:
user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Als nächstes muss ich doch jetzt ja einlesen, welche felder gefärbt sind und welche nicht. dafür benötige ich ja eine neue prozedur, kommt die in einen "start"-button? und wie les ich das dann ein?
Da es jetzt zwei Vorschläge gibt, wie es weiter gehen soll, musst du dich nun entscheiden, welchen "Weg" du gehen möchtest::nixweiss: Ich gehe davon aus, dass beide Wege an dein Ziel führen werden, eine funktionierende Implementation von Game of Life zu erstellen. Allerdings bin ich jetzt verständlicherweise nur für meinen Vorschlag "zuständig". ;) Wenn du also mit dem StringGrid weiter machen möchtest (wie du es auch angesprochen hast), dann kann dir ub60 sicher damit weiterhelfen. :beer:

Wenn du mit meinem Ansatz weiter machen möchtest, dann antworte bitte entsprechend, damit wir dort weiter machen können. :) Falls dem so ist, sag doch auch nochmal bitte was zu deinem Kenntnisstand: kannst du mit arrays etwas anfangen? Mehrdimensionale Arrays? records? Funktionen und Prozeduren? Klassen? :les: :gruebel:

cu
Narses


Nini - Mi 11.03.15 16:22

Ich würde mich für den Weg mit den Shapes entscheiden, weil ich stringgrids auch im unterricht überhaupt nicht behersche.

mehrdimensionale arrays, records, funktionen und klassen sagen mir nichts. mit prozeduren arbeiten wir im unterricht immer aber ich nutze sie mehr als sie zu verstehen und arrays weiß ich nur, dass es da indixe gibt und dass die was mit vielen rechnungen wie sieb des erastotheles vereinfachen aber wie die genau zu benutzen sind weiß ich leider nicht, info ist leider nicht so mein bestes fach :/


WasWeißDennIch - Mi 11.03.15 16:37

Ganz ohne Grundlagen wird es aber wohl nichts werden. In Ergänzung zum Lehrstoff in der Schule kann ich empfehlen:
Delphi-Basics [http://delphibasics.co.uk/index.html] (Englisch)
Grundlagen-Tutorials vom Delphi-Treff [http://www.delphi-treff.de/tutorials/grundlagen-tutorials/]
Das E-Book vom Delphi-Treff [http://www.delphi-treff.de/downloads/e-book/] (kostenlos)

Es gibt noch einige weitere, aber das würde hier den Rahmen sprengen.


Narses - Mi 11.03.15 17:53

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Ich würde mich für den Weg mit den Shapes entscheiden
OK, dann machen wir da weiter. ;)

Ich hätte dann noch zwei Fragen:

a) Möchtest du ein statisches Feld (durch virtuelle "tote" Felder begrenzt) oder ein "unendliches" (=Torus) Feld umsetzen? Hier steht mehr dazu [http://de.wikipedia.org/wiki/Conways_Spiel_des_Lebens] :les: (wobei ich stark hoffe, dass du das meiste davon schon gelesen hast :?).

b)
user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
mehrdimensionale arrays, records, funktionen und klassen sagen mir nichts.
Verstehst du, was das hier für einen Zweck hat? Wenn ja, kannst du kurz beschreiben, welchen?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
const
  N = 4;

type
  TFeld = array[0..N-10..N-1of Boolean;

var
  Feld: TFeld;
Wenn du das nicht verstehst, ist das auch OK. Es hat nur dann Sinn, wenn ich auf deinem Verständnislevel schreibe, weil es sonst an dir "vorbei" geht... :zwinker: Es geht also nur darum herauszufinden, wie du mir am besten folgen kannst. :idea:

cu
Narses


Nini - Mi 11.03.15 18:08

also ich dachte eher an ein torusförmiges spielfeld außer das ist viel schwieriger als das andere?
das meiste hatte ich wirklich schon gelesen oder zumindest schonmal überflogen ;)

also ich verstehe das feld so, dass es bestimmt für x und y werte stehen und da jeweils von null bis n-1 als index gibt und die werte für das feld können jeweils nur wahr oder falsch sein wegen boolean


Narses - Mi 11.03.15 22:36

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also ich dachte eher an ein torusförmiges spielfeld außer das ist viel schwieriger als das andere?
Nein, das ist überhaupt gar kein Problem und auch kein anderer "Schwierigkeitsgrad". ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das meiste hatte ich wirklich schon gelesen oder zumindest schonmal überflogen ;)
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also ich verstehe das feld so, dass es bestimmt für x und y werte stehen und da jeweils von null bis n-1 als index gibt und die werte für das feld können jeweils nur wahr oder falsch sein wegen boolean
:zustimm:

Dann übernehmen wir mal diesen Teil in das Projekt und ich zeige dir, wie man die Farbe der Shapes in so ein Feld überträgt. Deine Aufgabe ist dann anschließend den Code zu schreiben, um die Werte aus dem internen Feld wieder in die Farbe eines Shapes zu übertragen.


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:
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls;

const
  N = 4// Seitenlänge des Feldes

type
  TFeld = array[0..N-10..N-1of Boolean; // Aufbau des Feldes festlegen (2-dimensionales array)

  TForm1 = class(TForm)
    Shape1: TShape;
    ...
    Shape16: TShape;
    btnLesen: TButton;
    btnSchreiben: TButton;
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure btnLesenClick(Sender: TObject);
    procedure btnSchreibenClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    Feld: TFeld; // das ist der interne Speicher für die Zellen (=Shapes in der GUI)
    // mit den Werten in diesem Array arbeiten wir später, die Shapes in der GUI
    // sind nur zum Anzeigen der unsichtbaren Werte in diesem Feld da
  end;

...

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
...
end;

procedure TForm1.btnLesenClick(Sender: TObject);
  var
    x, y, snr: Integer;
    Shape: TShape;
begin
  for y := 0 to N-1 do // von unten nach oben
    for x := 0 to N-1 do begin // von rechts nach links
      snr := x +y *N +1// Nr. des Shapes berechnen
      Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
      Feld[x, y] := (Shape.Brush.Color = clBlack); // Wert ermitteln
    end;
end;


procedure TForm1.btnSchreibenClick(Sender: TObject);
begin
  // hier muss dein Code zum Übertragen der Werte aus dem Feld in die Shapes hin
end;

Alles, was in dem Projekt neu ist, habe ich markiert. Das solltest du nun in dein Projekt übertragen. Hier noch ein paar Erläuterungen:Probier mal, ob du den Code vervollständigt kriegst. Wenn du noch Fragen hast, immmer her damit. Ansonsten frisch ans Werk :D und melde dich bitte mit dem Code von deinem Projekt in einem neuen Beitrag.

cu
Narses


Nini - Do 12.03.15 21:18

Ich versteh leider nicht, was da beim Werte ermitteln passiert :/ für mich liest sich das so, als ob ich da einfach alles schwarz machen würde


Delphi-Quelltext
1:
 Feld[x, y] := (Shape.Brush.Color = clBlack); // Wert ermitteln                    

Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt


Narses - Do 12.03.15 21:20

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Ich versteh leider nicht, was da beim Werte ermitteln passiert :/ für mich liest sich das so, als ob ich da einfach alles schwarz machen würde
OK, schreiben wir das mal anders (länger, ich hab´s zusammengefasst :?):


Delphi-Quelltext
1:
2:
3:
4:
if (Shape.Brush.Color = clBlack) then
  Feld[x, y] := True
else
  Feld[x, y] := False;

Verständlicher? ;)

cu
Narses


Nini - Do 12.03.15 21:35

ja, danke, gleich viel verständlicher :)

und in die zweite prozedur mach ich ja jetzt wieder so zwei for-schleifen in einander, aber was will ich eigentlich genau in dem shape anzeigen lassen? weil die sind ja schon weiß oder schwarz, soll ich da jetzt was reinschreiben ?


Jann1k - Do 12.03.15 21:52

Ja, du hast dann zwei Methoden eine liest die Farben aus den Shapes und schreibt sie als Boolean-Werte ins Array und die zweite liest die Werte aus dem Array und setzt die Farbe in den Shapes.

Im Moment klingt das ziemlich unsinnig, die Werte einfach hin und her zu schreiben, aber Narses wird dir auch noch eine dritte Prozedur an die Hand geben, in der sich die Werte im Array dann - gemäß den Spielregeln - ändern.


Nini - Do 12.03.15 22:20

so, das ist was ich machen würde, aber irgendwas stimmt daran noch überhaupt nicht.


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:
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:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;

const
  N = 4;
type
  TFeld = array[0..N-10..N-1of Boolean;

  { TForm1 }

  TForm1 = class(TForm)
    btnSchreiben: TButton;
    btnLesen: TButton;
    Shape1: TShape;
    Shape10: TShape;
    Shape11: TShape;
    Shape12: TShape;
    Shape13: TShape;
    Shape14: TShape;
    Shape15: TShape;
    Shape16: TShape;
    Shape2: TShape;
    Shape3: TShape;
    Shape4: TShape;
    Shape5: TShape;
    Shape6: TShape;
    Shape7: TShape;
    Shape8: TShape;
    Shape9: TShape;
    procedure btnLesenClick(Sender: TObject);
    procedure btnSchreibenClick(Sender: TObject);
    procedure Shape1ChangeBounds(Sender: TObject);
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { private declarations }
  public
    { public declarations }
    Feld: TFeld;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Shape1ChangeBounds(Sender: TObject);
begin

end;

procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           if (feld[x,y] = true) then begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
             shape.brush.color := clblack
           end;
           else shape.brush.color := clwhite;

       end;

end;

procedure TForm1.btnLesenClick(Sender: TObject);
var
    x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1// Nr. des Shapes berechnen
            Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False; // Wert ermitteln
        end;
end;

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var Thisshape : TShape;
begin
  ThisShape := (Sender as TShape);
  if (ThisShape.Brush.Color = clWhite) then
    ThisShape.Brush.Color := clBlack
  else
    ThisShape.Brush.Color := clWhite;
end;

end.


Moderiert von user profile iconMartok: Quote- durch Delphi-Tags ersetzt


Narses - Do 12.03.15 22:36

Moin!

Ja, schon gar nicht schlecht. :zustimm: Betrachten wir mal nur den hier relevanten Teil:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           if (feld[x,y] = truethen begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
             shape.brush.color := clblack
           end;
           else shape.brush.color := clwhite;

       end;
end;

Es ist leider zwar logisch korrekt auf = True zu vergleichen, aufgrund von technischen Details, die ich dir jetzt mal erspare, kann das zu Ergebnissen führen, die du so nicht erwarten und deshalb als "falsch" interpretieren würdest. Also: niemals auf = True testen, sondern einfach nur schreiben:

Delphi-Quelltext
1:
if (feld[x,y]) then begin // das ist funktional identisch zu "= True"                    


Nächstes Problem: du ermittelst nur im Fall einer schwarzen Zelle die Referenz auf das Shape neu (der entsprechende Code steht in dem Teil der Fallunterscheidung, die sich mit schwarzen Zellen beschäftigt). Wenn du also auf eine weiße Zelle triffst, dann färbst du das "falsche" Shape ein (weil du die Referenz nicht neu berechnest)... :hair: Lösungsidee: der Code, der die Referenz auf das Shape bestimmt, muss in jedem Fall (für schwarze und weiße Zellen) ausgeführt werden. :idea:

Kannst du das noch ändern? :zustimm:

Und als Funktions-Test: klicke mal irgendwelche Zellen schwarz, dann einmal auf den "Lesen"-Button (das ist dann so wie "speichern"), dann machst du irgendwelche anderen Zellen schwarz und klickst auf den "Schreiben"-Button (wirkt dann so wie "laden"). Jetzt sollten wieder die Zellen schwarz sein, die du beim Klick auf den "Lesen"-Button gefärbt hattest. :idea: Wenn das so abläuft, ist alles korrekt. :)

cu
Narses


Nini - Do 12.03.15 23:24

yeah, so klappt es :) danke sehr

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           if (feld[x,y]) then begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
             shape.brush.color := clblack
           end
           else begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
             shape.brush.color := clwhite;
           end;

       end;

end;


Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt


Narses - Do 12.03.15 23:27

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
yeah, so klappt es :) danke sehr
Super! :zustimm:

Aber :gruebel: schau doch nochmal genau hin, du hast da zwei komplett identische Zeilen stehen, muss das wirklich so sein? :lupe: Geht das nicht etwas ... kürzer? :zwinker:

cu
Narses


Nini - Do 12.03.15 23:34


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
 for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1// Nr. des Shapes berechnen
           Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;


so, da hätt ich auch selbst drauf kommen könne :P

Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt


Narses - Do 12.03.15 23:36

Moin!

Top, genau so! :zustimm:

Dann gehen wir mal an den Kern der Sache: das eigentliche Spiel. 8) Könntest du mal kurz die Regeln zusammenfassen, nach denen bestimmt wird, wie eine neue Generation berechnet wird (ruhig in Umgangssprache, das übersetzen wir dann nach und nach in Code)? :les:

cu
Narses


Nini - Do 12.03.15 23:40

conways regeln besagen glaub ich, dass eine schwarze zelle weiß wird , wenn sie 0,1,4,5,6,7,8 nachbarn hat, es passiert nihts mit einer zelle, wenn sie zwei nachbarn hat und eine weiße zelle wird schwarz, wenn sie 3 nachbarn hat


Narses - Do 12.03.15 23:43

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
conways regeln besagen glaub ich
Glaub ich oder weiß ich? :gruebel: :zwinker: Das dumme ist, Computer wollen immer alles ganz genau haben (so wie Lehrer :lol:), also kann ich dir das nicht ersparen:

Schreib mal bitte getrennt auf, welche Bedingungen zu einer neuen schwarzen, und welche zu einer neuen weißen Zelle führen (diesmal aber bitte mit dem Attribut "wissen", nicht glauben... 8)).

cu
Narses


Nini - Do 12.03.15 23:48

ich weiß, dass es folgendermaßen ist:
weiß --> schwarz bei 3 Nachbarn
schwarz --> weiß bei 0,1,4,5,6,7,8 Nachbarn
keine Änderung bei 2 Nachbarn


Narses - Do 12.03.15 23:50

Moin!

Und was ist mit 3 Nachbarn bei schwarzen Zellen? :lupe:

cu
Narses


Nini - Do 12.03.15 23:54

die bleibt doch schwarz oder nicht?


Narses - Do 12.03.15 23:58

Moin!

Ja, aber du hast es nicht in deiner Liste erwähnt. :nixweiss: (zur Erinnerung: Computer :arrow: ganz genau aufschreiben) ;)

OK, nächster Schritt: Verändere bitte die Aufzählung so, dass nur berücksichtigt wird, wie schwarze Zellen in der neuen Generation entstehen (also die Regeln formulieren, die schwarze Zellen zur Folge haben [egal ob neue oder "alte"]). Wenn etwas nicht erwähnt wird, wird die Zelle eben automatisch weiß. :idea:

cu
Narses


Nini - Fr 13.03.15 00:01

eine Zelle wird schwarz, wenn sie 2 nachbarn haben oder schwarz sind und drei nachbarn haben


Narses - Fr 13.03.15 00:04

Moin!

Hm, OK, hab die Frage doof formuliert, ich fasse es nochmal zusammen:

Quelltext
1:
2:
3:
4:
alt     | neu
---------------------------------------
weiß    | 3 Nachbarn? -> schwarz
schwarz | 2 oder 3 Nachbarn? -> schwarz

Kommt das hin oder nicht? :lupe:

cu
Narses


Nini - Fr 13.03.15 00:08

ja, das stimmt so


Narses - Fr 13.03.15 00:15

Moin!

Gut, weiter geht´s.

Wir brauchen eine Art "Schmierzettel" bei der Berechnung der neuen Generation, wir müssen uns ja die Farbe der neuen Zellen "woanders" merken, damit wir die Rechenergebnisse der umliegenden Zellen nicht verfälschen. :idea:

Dann formulieren wir mal in Pseudo-Code:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
für alle Zellen im Feld
  wenn die alte Zelle weiß ist
    wenn die Anzahl der schwarzen Nachbarn dieser Zelle = 3 ist
      neue Zelle schwarz machen
    sonst
      neue Zelle weiß machen
  sonst (die alte Zelle ist dann logischerweise schwarz)
    wenn die Anzahl der schwarzen Nachbarn dieser Zelle = 2 oder 3 ist
      neue Zelle schwarz machen
    sonst
      neue Zelle weiß machen

Kannst du mir folgen? Entspricht dieses Vorgehen den gerade in der Tabelle aufgestellten Regeln?

cu
Narses


Nini - Fr 13.03.15 00:17

ja, soweit versteh ich es noch und es stimmt mit der tabelle auch überein


Narses - Fr 13.03.15 00:24

Moin!

Gut, dann hast du sicher bemerkt, dass wir da eine Funktion verwenden, nämlich das "Anzahl der schwarzen Nachbarn"-Dings. ;) Das lassen wir auch mal so und kümmern uns später darum, dass diese Funktion das tut, was sie soll. Deshalb fügen wir in den Code nur eine leere Hülse ein (damit man es trotzdem schon kompilieren kann, obwohl es nicht tut, was es soll):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  TForm1 = class(TForm)
    Shape1: TShape;
    ...
  public
    Feld: TFeld; // das ist der interne Speicher für die Zellen (=Shapes in der GUI)
    function AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  end;
...

function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
begin
  Result := 0// das ist natürlich Blödsinn
end;


Jetzt fehlt dir noch der "Schmierzettel". ;) Dazu legen wir einen neuen Button "btnRechnen" auf das Formular. In dessen Ereignishandler schreiben wir:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.btnRechnenClick(Sender: TObject);
  var
    FeldNeu: TFeld; // der "Schmierzettel", wird genauso benutzt, wie das andere Feld
begin
  // hier kommt jetzt dein Versuch einer Übersetzung des Pseudo-Codes rein
end;

Auf geht´s! :zustimm:

cu
Narses


Nini - Sa 14.03.15 16:11


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
var x, y, snr: Integer;

    feldneu : tfeld;
    Shape: TShape;
begin
     for y := 0 to N-1 do
         for x := 0 to N-1 do begin
       snr := x +y *N +1// Nr. des Shapes berechnen
       Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
      if not (feldneu[x,y]) then begin
         if   wenn die Anzahl der schwarzen Nachbarn dieser Zelle = 3 ist
              then (Shape.Brush.Color = clBlack)
              else (Shape.Brush.Color = clWhite) end;
         else if  wenn die Anzahl der schwarzen Nachbarn dieser Zelle = 2 oder 3 ist
      neue Zelle schwarz machen
              then (Shape.Brush.Color = clblack)
              else (Shape.Brush.Color = clwhite);

  end;

end;


soweit habe ich es hinbekommen, aber jetzt weiß ich nicht mehr weiter

Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt


Narses - Sa 14.03.15 17:45

Moin!

Hast du die (Dummy-)Funktion AnzahlLebenderNachbarn() wie oben beschrieben in deinen Code übernommen?

Man ruft eine Funktion einfach über ihren Namen auf, also wird aus:

Delphi-Quelltext
1:
if   wenn die Anzahl der schwarzen Nachbarn dieser Zelle = 3 ist                    
dann

Delphi-Quelltext
1:
if (AnzahlLebenderNachbar(x, y) = 3then                    

Schau mal, ob du damit weiter kommst. :idea: Zumindest solltest du es dann kompilieren können.

Hinweis: Das ist natürlich noch nicht fertig, sondern nur ein Zwischenschritt, weil wir ja noch diese Funktion mit dem "echten Inhalt" füllen müssen, aber eins nach dem anderen. ;)

cu
Narses

PS: Und schau doch bitte mal, ob du die Einrückungen noch etwas schöner machen kannst. Das ist zwar nur "Schmuck am Christbaum" (also für die Funktionalität des Codes nicht wichtig, ja, ich weiß), aber trotzdem macht es den Code deutlich besser lesbar und damit verständlicher. :zustimm:


Nini - Sa 14.03.15 17:57


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
for y := 0 to N-1 do
         for x := 0 to N-1 do begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
              if not (feldneu[x,y]) then
                   if   (AnzahlLebenderNachbarn(x, y) = 3)
                   then (Shape.Brush.Color = clBlack)
                   else (Shape.Brush.Color = clWhite)
              else if  (AnzahlLebenderNachbarn(x, y) in [23])
                   then (Shape.Brush.Color = clblack)
                   else (Shape.Brush.Color = clwhite);
         end;


Ich hab das jetzt so verändert, ind den letzten 5 zeilen werden mir die fehlermeldung angezeigt: "Error: Illegal Expression"
die funktion hab ich ei gebaut und das was ich gemacht hatte mit einrückungen hat's einfach nicht übernommen beim kopieren .,.

Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt


Narses - Sa 14.03.15 18:29

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das was ich gemacht hatte mit einrückungen hat's einfach nicht übernommen beim kopieren
Wenn du den Code in Delphi-Tags einfasst, dann passt das auch mit den Einrückungen:

[delphi]begin
end;[/delphi]

wird dann zu

Delphi-Quelltext
1:
2:
begin
end;


user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
fehlermeldung angezeigt: "Error: Illegal Expression"
Eine Zuweisung wird in Delphi mit ":=" gemacht, was du das hast, ist ein Vergleich, deshalb die Meldung. :idea:

cu
Narses


Nini - Sa 14.03.15 18:34

ok, danke, jetzt funktioniert es soweit :)


Narses - Sa 14.03.15 18:46

Moin!

Fein. :)

Allerdings :? Hast du noch zwei logische Fehler drin:

1. Du fragst Felder aus dem "Schmierzettel" ab (FeldNeu), statt aus dem internen Feld. Du musst natürlich Felder aus dem internen Feld abfragen und dir das Ergebnis im Schmierzettel merken.

2. steckt schon im Verbesserungsvorschlag von oben drin: du färbst direkt die Shapes in der GUI, statt in den Schmierzettel zu schreiben.

Das meinte ich vorhin mit dem Zwischenschritt: man wird noch keine direkte Auswirkungen sehen, wenn man auf den Button btnRechnen klickt.

cu
Narses

PS: Wenn du nicht weißt, worauf ich hinaus will, sag's ruhig, dann müssen wir noch mehr auf das Konzept eingehen. Zeig auch ruhig nochmal den aktuellen Code.


Nini - Sa 14.03.15 18:57


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.btnRechnenclick(Sender: TObject);
 var x, y, snr: Integer;
    Shape: TShape;

begin
     for y := 0 to N-1 do
         for x := 0 to N-1 do begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
              if not (feld[x,y]) then
                   if   (AnzahlLebenderNachbarn(x, y) = 3)
                   then (Shape.Brush.Color := clBlack)
                   else (Shape.Brush.Color := clWhite)
              else if  (AnzahlLebenderNachbarn(x, y) in [23])
                   then (Shape.Brush.Color := clblack)
                   else (Shape.Brush.Color := clwhite);
         end;

end;


ich hab das feldneu jetzt zu feld wieder geändert, aber was ich noch ändern muss um es im "Schmierzettel" zu merken, statt direkt zu malen, weiß ich nicht. bedeutet das, dass ich die true/false werte ändern muss?


Narses - Sa 14.03.15 19:11

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich hab das feldneu jetzt zu feld wieder geändert
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
was ich noch ändern muss um es im "Schmierzettel" zu merken, statt direkt zu malen, weiß ich nicht. bedeutet das, dass ich die true/false werte ändern muss?
Ja, genau. ;) Ich wollte die Lösung nach dem EVA-Prinzip (Eingabe-Verarbeitung-Ausgabe) abwickeln. Also etwa so:

btnLesen anklicken (Werte aus der GUI in das interne Feld lesen)
btnRechnen anklicken (nächste Generation berechnen / unsichtbar!)
btnSchreiben anklicken (Werte aus dem internen Feld wieder in die GUI schreiben)

Dehalb arbeiten wir mit den Werten True / False in internen Arrays, statt direkt die Farben zuzuweisen (so trennt man die Logik von der Darstellung). Statt also Farbwerte zu setzen, weist du den bool´schen Wert ab das FeldNeu zu. :idea:

cu
Narses


Nini - Sa 14.03.15 19:20

also muss mein quelltext folgendermaßen aussehen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  for y := 0 to N-1 do
         for x := 0 to N-1 do begin
             snr := x +y *N +1// Nr. des Shapes berechnen
             Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
              if not (feld[x,y]) then
                   if   (AnzahlLebenderNachbarn(x, y) = 3)
                   then feldneu[x,y] := true
                   else feldneu[x,y] := false
              else if  (AnzahlLebenderNachbarn(x, y) in [23])
                  then feldneu[x,y] := true
                  else feldneu[x,y] := false;
         end;


Narses - Sa 14.03.15 20:10

Moin!

Jawoll, so hab ich mir das vorgestellt. :zustimm: Aber: wir brauchen in der Prozedur doch gar keine Shapes mehr, also kann der betreffende Code wieder raus. :idea:

Und zum Abschluss müssen wir noch den Schmierzettel wieder "abschreiben" (weil die btnSchreiben-Prozedur ja von da die Werte holt). Hast du eine Idee, wie man das machen könnte?

cu
Narses


Nini - Sa 14.03.15 20:24

ein. also ehrlich gesagt, fällt mir dazu gar nichts ein :(


Narses - Sa 14.03.15 20:26

Moin!

Nun, Feld ist eine Variable und FeldNeu auch. Wie weist man denn einer Variablen den Wert einer anderen zu? 8)

cu
Narses


Nini - Sa 14.03.15 20:31

vlt mit feld := feldneu ?

Moderiert von user profile iconNarses: Beiträge zusammengefasst

vlt mit feld[x,y] := feldneu[x,y] ?


Narses - Sa 14.03.15 20:39

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
vlt mit feld := feldneu ?
Jap! Genau so, ganz einfach. ;) (der Vollständigkeit halber: dein anderer Vorschlag ist auch nicht falsch, aber dann brauchst du auch noch die doppelten Schleifen drum rum, und das ist ja nicht nötig)

Wenn du diese letzte Zeile noch ergänzt hast, dann zeig doch bitte nochmal den Code.

Du kannst jetzt auch schon testen: ein paar Felder schwarz machen, btnLesen anklicken, btnRechnen anklicken, btnSchreiben anklicken und dann - sind alle Felder weiß! :shock: (was korrekt ist) Aber warum? :gruebel: ;)

cu
Narses


Nini - Sa 14.03.15 20:45


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:
76:
77:
function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
begin
  Result := 0// das ist natürlich Blödsinn
end;

procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1// Nr. des Shapes berechnen
           Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;


       end;

end;

procedure TForm1.EndeClick(Sender: TObject);
begin
  close;
end;


  procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  var
    ThisShape: TShape;
begin
  ThisShape := (Sender as TShape);
  if (ThisShape.Brush.Color = clWhite) then
    ThisShape.Brush.Color := clBlack
  else
    ThisShape.Brush.Color := clWhite;
end;




procedure TForm1.btnLesenClick(Sender: TObject);
var
    x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1// Nr. des Shapes berechnen
            Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False; // Wert ermitteln
        end;
    feld := feldneu
end;

procedure TForm1.btnRechnenclick(Sender: TObject);
 var x, y: Integer;

begin
     for y := 0 to N-1 do
         for x := 0 to N-1 do begin
              if not (feld[x,y]) then
                   if   (AnzahlLebenderNachbarn(x, y) = 3)
                   then feldneu[x,y] := true
                   else feldneu[x,y] := false
              else if  (AnzahlLebenderNachbarn(x, y) in [23])
                  then feldneu[x,y] := true
                  else feldneu[x,y] := false;
         end;

end;
end.


es wird alles weiß, weil in der funktion result := 0 steht, also sind alle nachbarn "tot" und deshalb sterben die zellen


Narses - Sa 14.03.15 20:56

Moin!

Wir waren doch bei der btnRechnen-Prozedur, warum schreibst du den Kopiercode in die btnLesen-Prozedur? :nixweiss: Und wo hast du FeldNeu deklariert? :lupe:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
es wird alles weiß, weil in der funktion result := 0 steht, also sind alle nachbarn "tot" und deshalb sterben die zellen
Top! :zustimm:

Was passiert denn, wenn du statt 0 eine 3 zurück lieferst? (Nur mal so als test)

cu
Narses


Nini - Sa 14.03.15 21:02

feldneu hab ich wie feld unter public declariert

den kopiercode hab ich jetzt auch zur btnrechnen gewechselt

mit result := 3 werden alle felder schwarz


Narses - Sa 14.03.15 21:14

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
feldneu hab ich wie feld unter public declariert
Brauchen wir denn FeldNeu "überall" in der Formularklasse? :gruebel: Ich denke nicht. :nixweiss: Also kann FeldNeu doch ruhig zu den anderen lokalen Variablen in btnRechnen, oder? ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
den kopiercode hab ich jetzt auch zur btnrechnen gewechselt
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
mit result := 3 werden alle felder schwarz
Das war zu erwarten. Warum? :lupe:

Was passiert, wenn du 2 zurücklieferst? Und speziell: was passiert, wenn du als Ausgangsgeneration die 4 Felder in der Mitte schwarz machst und einen weißen Rand aussen drum rum lässt?

cu
Narses


Nini - Sa 14.03.15 21:18

ja, stimmt, ich hab das jetzt umgeschreiben, also nur lokal deklariert

weil ja bei drei lebenden zellen eine neue zelle geboren wirde/die zelle schwarz wird, werden alle schwarz

bei zwei bleibt alles wie es ist


Narses - Sa 14.03.15 21:22

Moin!

Fein, dann haben wir die Regeln für das Game of Life schon fertig umgesetzt (ja, von "automatisch ablaufen" sind wir noch etwas entfernt, aber das kommt auch noch). :zustimm:

Jetzt zu dem Detail-Problem: wie kriegen wir die Anzahl der lebenden Nachbarn einer beliebigen Zelle raus (und damit den Code in die Funktion rein)? :gruebel: Mach doch mal einen Vorschlag, ruhig erstmal wieder in Umgangssprache oder, wenn du magst, auch gleich in Pseudo-Code. :les:

cu
Narses


Nini - Sa 14.03.15 21:29

vielleicht geht ja sowas dass man von den den nachbarn x-1 bis x+1 und y-1 bis y+1 die wahrheitswerte prüft und dann zählt oder so


Narses - Sa 14.03.15 21:33

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
vielleicht geht ja sowas dass man von den den nachbarn x-1 bis x+1 und y-1 bis y+1 die wahrheitswerte prüft und dann zählt oder so
Top! :zustimm: Genau so hab ich das in meinem Test-Programm hierfür auch gemacht. ;)

Versuch doch mal diese Ablaufbeschreibung, die ja nun sehr kurz/grob ist, zu verfeinern, also z.B. in eine von mir aus umgangssprachlich formulierte Arbeitsanweisung zu übersetzen. Du kannst dich ja daran orientieren, wie wir über alle Felder mit den beiden Schleifen laufen, vielleicht kann man das ja so ähnlich machen? :idea:

cu
Narses


Nini - Sa 14.03.15 21:39


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
 

begin
 result := 0;
 for x = 0 to N-1 do
             for y = 0 to N-1 do begin
                 if feld[x-1,y-1] = true then result:=result+1;
                 if feld[x-1,y] = true then result:=result+1;
                 if feld[x-1,y+1] = true then result:=result+1;
                 if feld[x,y-1] = true then result:=result+1;
                 if feld[x,y+1] = true then result:=result+1;
                 if feld[x+1,y-1] = true then result:=result+1;
                 if feld[x+1,y] = true then result:=result+1;
                 if feld[x+1,y+1] = true then result:=result+1;
            end;
end;


kann das so funktionieren?


Narses - Sa 14.03.15 21:46

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
kann das so funktionieren?
Ist nicht komplett verkehrt, aber an unserem Ansatz vorbei. :nixweiss:

Nochmal zur Erinnerung:

Delphi-Quelltext
1:
2:
3:
4:
function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
begin
  Result := 0// das ist natürlich Blödsinn
end;

Wir haben diese Funktion deklariert. Die soll als Ergebnis (was der Wert von Result ist) die Anzahl der lebenden Zellen um die Zelle[x,y] liefern (das ist der Sinn der beiden Parameter dieser Funktion: um welche Zelle geht´s denn). :idea:

Wenn du allerdings 8 einzelne Abfragen verwenden möchtest (was nicht falsch ist, nur umständlich), dann kannst du die Schleifen weglassen. :nixweiss:

Dann versuch nochmal die Funktion zu vervollständigen und zeig deinen Code (nur die Funktion, wie oben, nur mit deinem "Inhalt").

cu
Narses

PS: Ich bin jetzt gleich bis ca. 22 Uhr (oder etwas später) offline.

PPS: Wie war das noch mit "= True"? :zwinker:


Nini - Sa 14.03.15 21:54

meine neue funktion:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;

begin
 result := 0;

 if (feld[x-1,y-1]) then result:=result+1;
 if (feld[x-1,y]) then result:=result+1;
 if (feld[x-1,y+1]) then result:=result+1;
 if (feld[x,y-1]) then result:=result+1;
 if (feld[x,y+1]) then result:=result+1;
 if (feld[x+1,y-1]) then result:=result+1;
 if (feld[x+1,y]) then result:=result+1;
 if (feld[x+1,y+1]) then result:=result+1;


end;


aber so ganz stimmt die noch nucht :(


Boldar - Sa 14.03.15 22:34

Das sieht doch schon ganz gut aus. Ich will mich hier jetzt nicht allzusehr einmischen, und Narses wird das dir dann schon erläutern, aber du kannst ja jetzt schonmal drüber nachdenken, in welchen Fällen (also welche Werte für x/y) die Funktion nicht funktionieren kann und wie man das abfangen könnte (Stichwort Modulo, sagt dir das etwas aus der Mathematik?).


Narses - Sa 14.03.15 23:18

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
meine neue funktion:
Das ist doch schon ganz OK. ;) Allerdings ziemlich umständlich. :? Möchtest du das ändern? Also weniger umständlich machen? :nixweiss: Dann zeige ich dir noch einen kleinen Trick... 8)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber so ganz stimmt die noch nucht :(
Warum, gibt´s Fehlermeldungen? :lupe:

Boldar hat schon drauf hingewiesen (:beer:), da ist noch ein generelles, logisches Problem drin. Bist du schon drauf gekommen?

cu
Narses


Nini - Sa 14.03.15 23:23

also nicht funktionieren kann es meiner meinung nach nicht für die randfelder

und mod sind die Restklassen bei der division mit einer bestimmten zahl
aber was genau falsch ist, weiß ich nicht :/

ja, einfacher wäre es mir schon lieber :P

nein, fehlermeldungen treten nicht auf, aber die felder die es anmalt sind noch ziemlich wahllos irgendwie ._.


Narses - Sa 14.03.15 23:31

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ja, einfacher wäre es mir schon lieber :P
OK, dann machen wir das. :zustimm: Man kann die umgebenden Felder auch mit zwei Schleifen "ablaufen", und zwar so:

Delphi-Quelltext
1:
2:
3:
4:
for dx := -1 to 1 do
  for dy := -1 to 1 do
    if (Feld[x +dx, y +dy]) then
      Result := Result +1;

Das hat nur einen winzig kleinen "Haken", erkennst du ihn? :lupe:


user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also nicht funktionieren kann es meiner meinung nach nicht für die randfelder
Jap, genau da ist das Problem. Da gehen wir gleich noch genauer drauf ein. :zustimm:

cu
Narses


Nini - Sa 14.03.15 23:34

nein, also so direkt fällt mir kein haken auf


Narses - Sa 14.03.15 23:45

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
nein, also so direkt fällt mir kein haken auf
OK, dann müssen wir einen kleinen Exkurs einlegen, kein Problem. :)

Zunächst mal führen wir noch eine Funktion ein, die müssen wir wieder oben in der Klasse "anmelden":

Delphi-Quelltext
1:
2:
3:
4:
  public
    Feld: TFeld; // das ist der interne Speicher für die Zellen (=Shapes in der GUI)
    function AnzahlLebenderNachbarn(const x, y: Integer): Integer;
    function LebtNachbar(x, y: Integer): Boolean;

Der Sinn soll also sein, die Prüfung, ob eine bestimmte Zelle "lebendig" ist, auszulagern. Sonst wird der Code schnell unübersichtlich. :idea: Aber, wir machen da noch nicht den endgültigen Code rein, sondern erstmal was zum testen:

Delphi-Quelltext
1:
2:
3:
4:
5:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y];
end;

Wenn du das übernommen hast, dann müssen wir noch die Zähler-Funktion anpassen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  var
    dx, dy: Integer;
begin
  Result := 0;
  for dy := -1 to 1 do
    for dx := -1 to 1 do
      if LebtNachbar(x +dx, y +dy) then
        Inc(Result); // das ist das Gleiche wie "Result := Result +1", nur kürzer ;)
end;

ACHTUNG: Mit diesem Code nicht auf den btnRechnen klicken, sonst musst du zig-tausend Messageboxen wegklicken! :shock:

Statt dessen machst du noch einen neuen Button auf das Formular: btnTest, und da schreibst du rein:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.btnTestClick(Sender: TObject);
begin
  AnzahlLebenderNachbarn(11); // Test-Aufruf nur für die Zelle[1,1]
end;

Jetzt das Projekt starten und einmal auf den neuen Test-Button klicken: Wieviele Messageboxen kommen und was steht drin?

cu
Narses


Nini - So 15.03.15 00:02

es kommt eine message boxx und darin steht "x=0,y=0"


Narses - So 15.03.15 00:03

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
es kommt eine message boxx und darin steht "x=0,y=0"
Es wird nur genau eine MessageBox angezeigt?! :lupe: Da sollten ein paar mehr kommen... :gruebel: Zeig mal bitte deinen gesamten Code... :les:

cu
Narses


Nini - So 15.03.15 00:04

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
es kommt eine message boxx und darin steht "x=0,y=0"

oh, danack kommen ja noch welche :P
und danach x=1, y=0
x=2, y=0
x=0, y=1
x=1, y=1
x=2 y=1
x=0 y=2
x=1 y=2
x=2 y=2

und dann schließen sich die boxen


Narses - So 15.03.15 00:06

Moin!

Ah, schon besser. :P Und, wieviele sind es denn nun gewesen? :lupe:

cu
Narses


Nini - So 15.03.15 00:11

es waren 9


Narses - So 15.03.15 00:12

Moin!

OK, kannst du dann bitte mal die Nachbarn der Zelle[1,1] aufzählen? (oder als Abkürzung sagen, wieviele Nachbarn diese Zelle hat?)

cu
Narses


Nini - So 15.03.15 00:15

0,0
0,1
0,2
1,0
1,2
2,0
2,1
2,2


Narses - So 15.03.15 00:16

Moin!

Was fällt dir im Gegensatz zu den MessageBoxen auf? ;)

cu
Narses


Nini - So 15.03.15 00:20

eeehhhm, keine ahnung, vlt, dass ich die andersrum sotiert habe? und das halt die 1,1 nicht dazu gehört, weil die die zelle selbst ist


Narses - So 15.03.15 00:21

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und das halt die 1,1 nicht dazu gehört, weil die die zelle selbst ist
Hast ja doch Ahnung, genau das ist es! :zustimm: Und jetzt die Preisfrage: warum taucht denn bei der Lösung mit den beiden Schleifen die Zelle selbst auf (die ist ja kein Nachbar)?! :gruebel:

cu
Narses


Nini - So 15.03.15 00:31

weil nicht ausgeschlossen ist, dass dx und dy gleichzeitig 0 sein können


Narses - So 15.03.15 00:32

Moin!

Perfekt! :zustimm: Dann ändere das doch mal eben (und zeig dann den Code der Funktion bitte)! ;)

cu
Narses


Nini - So 15.03.15 00:40

so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  var
    dx, dy: Integer;
begin
  Result := 0;
  for dy := -1 to 1 do
    for dx := -1 to 1 do
      if not ((x=0and (y=0)) then
      if LebtNachbar(x +dx, y +dy) then
        Inc(Result); // das ist das Gleiche wie "Result := Result +1", nur kürzer ;)
end;


Narses - So 15.03.15 00:43

Moin!

Grandios! :zustimm: Genau so.

Dann ändere doch mal bitte den Testaufruf:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.btnTestClick(Sender: TObject);
begin
  AnzahlLebenderNachbarn(00); // Test-Aufruf nur für linke obere Ecke (Zelle[0,0])
end;

Welche Werte werden dir nun nach einem Klick auf btnTest in den MessageBoxen angezeigt? Und gibt es da vielleicht schon ... Auffälligkeiten? :lupe: ;)

cu
Narses


Nini - So 15.03.15 00:47

bei mir passiert gar nichts mehr, wenn ich auf btntest gehe


Narses - So 15.03.15 00:48

Moin!

Aha :gruebel: zeig mal den ganzen Code... :les: Irgendwo nochwas geändert? :lupe:

cu
Narses


Nini - So 15.03.15 00:53

also bewusst habe ich nichts verändert :/

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:
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:
  public
    Feld: TFeld; // das ist der interne Speicher für die Zellen (=Shapes in der GUI)
    function LebtNachbar(x, y: Integer): Boolean;
    function AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y];
end;

function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  var
    dx, dy: Integer;
begin
  Result := 0;
  for dy := -1 to 1 do
    for dx := -1 to 1 do
      if not ((x=0and (y=0)) then
      if LebtNachbar(x +dx, y +dy) then
        Inc(Result); // das ist das Gleiche wie "Result := Result +1", nur kürzer ;)
end;

procedure TForm1.btnTestClick(Sender: TObject);
begin
  AnzahlLebenderNachbarn(00); // Test-Aufruf nur für linke obere Ecke (Zelle[0,0])
end;

procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1// Nr. des Shapes berechnen
           Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;
       end;

end;

procedure TForm1.EndeClick(Sender: TObject);
begin
  close;
end;


  procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  var
    ThisShape: TShape;
begin
  ThisShape := (Sender as TShape);
  if (ThisShape.Brush.Color = clWhite) then
    ThisShape.Brush.Color := clBlack
  else
    ThisShape.Brush.Color := clWhite;
end;




procedure TForm1.btnLesenClick(Sender: TObject);
var
    x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1// Nr. des Shapes berechnen
            Shape := TShape(FindComponent('Shape' +IntToStr(snr))); // Komponente suchen
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False; // Wert ermitteln
        end;

end;

procedure TForm1.btnRechnenclick(Sender: TObject);
 var x, y: Integer;
     Feldneu : TFeld;
begin
     for y := 0 to N-1 do
         for x := 0 to N-1 do begin
              if not (feld[x,y]) then
                   if   (AnzahlLebenderNachbarn(x, y) = 3)
                   then feldneu[x,y] := true
                   else feldneu[x,y] := false
              else if  (AnzahlLebenderNachbarn(x, y) in [23])
                  then feldneu[x,y] := true
                  else feldneu[x,y] := false;
         end;
     feld := feldneu
end;
end.


Narses - So 15.03.15 00:56

Moin!

Hm, sieht eigentlich gut aus. Dann kommentier mal diese Zeile testweise aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  //Result := Feld[x, y];  <-- testweise deaktivieren
end;

Mein Delphi hat da keine Probleme mit (was genau, sehen wir dann gleich schon), vielleicht hat Lazarus da aber schon eins... :? :nixweiss:

Geht´s dann wieder (kommen MessageBoxen)?

cu
Narses


Nini - So 15.03.15 01:00

nein, die messageboxen bleiben verschwunden :/


Narses - So 15.03.15 01:01

Moin!

OK, dann Projekt abspeichern, Lazarus beenden, wieder öffnen und das Projekt laden. Geht´s jetzt?

cu
Narses


Nini - So 15.03.15 01:04

das bringt auch nichts :/ das geht nur wenn ich die eine zeile auskommentier:
if not ((x=0) and (y=0)) then


Narses - So 15.03.15 01:07

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das bringt auch nichts :/ das geht nur wenn ich die eine zeile auskommentier:
Stimmt. :autsch: Da ist nämlich noch ein Fehler drin:

Delphi-Quelltext
1:
if not ((dx = 0and (dy = 0)) then                    

Mach dir nix draus, ich hab´s auch die ganze Zeit übersehen... :lol:

Jetzt sollte das aber wieder laufen. ;)

cu
Narses

PS: Da hast du´s sogar selbst geschrieben: ;)
user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
weil nicht ausgeschlossen ist, dass dx und dy gleichzeitig 0 sein können


Nini - So 15.03.15 01:11

ok jetzt kommt:
-1.-1
0,-1
1,-1
-1,0
1,0
-1,1
0,1
1,1


Narses - So 15.03.15 01:12

Moin!

Jap, das passt wieder. ;) Also weiter mit dem eigentlichen Problem: was davon ist ... problematisch? :lupe:

cu
Narses


Nini - So 15.03.15 01:13

die -1, die müsste ja eigentlich der höchste wert auf der anderen seite vom feld sein


Narses - So 15.03.15 01:15

Moin!

Richtig, also wenn die Werte < 0 sind, dann müssen wir... ja, was dann. Vorschläge? ;)

cu
Narses


Nini - So 15.03.15 01:16

vielleicht stattdessen N oder N-1 nehmen?


Narses - So 15.03.15 01:18

Moin!

Gegenangebot: N addieren? ;)

Verstanden? -> Codevorschlag zeigen.
Nicht verstanden? -> Wo hapert´s?

cu
Narses


Nini - So 15.03.15 10:12

vielleicht einfach mit zwei weiteren if schleifen if y+dy=-1 then y+dy:=y+dy+N


Narses - So 15.03.15 12:33

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
vielleicht einfach mit zwei weiteren if schleifen
Zunächst mal zur Begrifflichkeit:

if: Fallunterscheidung (wenn-dann) :idea:
forwhilerepeat: Schleifen (wiederhole irgendwas) :think:

Bitte nicht "if-schleifen" in Gegenwart von Informatikern sagen, die kriegen dann so ein schmerzhaftes Ziehen in der linken Gehirnhälfte und anschließend Ausschlag am ganzen Körper... :lol:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
if y+dy=-1 then y+dy:=y+dy+N
Hm, damit kann ich jetzt wenig anfangen... :gruebel:

Vielleicht zeigst du erstmal die Stelle im Code, an der wir ansetzen müssen, um das Problem zu lösen. ;)

cu
Narses


Nini - So 15.03.15 12:52

ohh, ok, werde ich mir merken ;)

ich würde das vielleicht so machen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  var
    dx, dy: Integer;
begin
  Result := 0;
  for dy := -1 to 1 do
    for dx := -1 to 1 do
     if not ((dx=0and (dy=0)) then begin
        if (dx=-1then  begin
          dx:=dx+N;
           if (dy=-1then  begin
           dy:=dy+N;
         if LebtNachbar(x +dx, y +dy) then
        Inc(Result); // das ist das Gleiche wie "Result := Result +1", nur kürzer ;)
     end;
           end;
        end;
        end;


Narses - So 15.03.15 13:19

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ohh, ok, werde ich mir merken ;)
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich würde das vielleicht so machen:
Hm, zum einen macht das den Code recht unübersichtlich. Also alleine unter diesem Gesichtspunkte finde ich das keine gute Stelle. :nixweiss: Mit den beiden Schleifen (dx und dy) gehen wir alle Nachbar durch. Wenn du nun da eingreifst, hätte das ja zur Folge, dass nicht alle oder andere Nachbarn berücksichtigt würden. :gruebel: Also auch vom logischen Gesichtspunkt vielleicht keine glückliche Stelle. :? (zur Klarstellung: grundsätzlich geht das auch hier, empfehle ich dir aber nicht)

Wo könnte man es denn evtl. besser unterbringen? :lupe:

cu
Narses


Nini - So 15.03.15 13:28

mir fällt leider keine andere stelle ein :(


Narses - So 15.03.15 13:29

Moin!

Wir haben doch noch eine weitere Funktion eingeführt:

Delphi-Quelltext
1:
2:
3:
4:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  Result := Feld[x, y];
end;

Was meinst du, nur für diese eine Zeile? :zwinker:

cu
Narses


Nini - So 15.03.15 13:48

stimmt das dann so?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  if x = -1 then x := x+N;
  if y = -1 then y := y+N;
  ShowMessageFmt('x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y];
end;


Narses - So 15.03.15 14:13

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
stimmt das dann so?
Ja, das ist nicht falsch. :zustimm: Aber auch noch nicht alles... :? Immer mit der Ruhe. ;)

Ich würde das etwas allgemeiner formulieren:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('vorher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  if (x < 0then
    x := x +N;
  if (y < 0then
    y := y +N;
  ShowMessageFmt('nachher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y];
end;

Probier´s mal mit dem Test-Button aus. :les:

cu
Narses


Nini - So 15.03.15 14:16

das ist gut :) das klappt


Narses - So 15.03.15 14:19

Moin!

OK, nächster Schritt: ändere mal in dem btnTest-Handler die Aufrufparameter ab, so dass die rechte untere Zelle abgefragt wird. Dann auf den Test-Button klicken. Gibt´s da evtl. noch Probleme? :lupe:

cu
Narses


Nini - So 15.03.15 14:33

da gibt es jetzt zellen mit [4,4] und so und die gibt es nicht, die müssen wieder auf die andere seite

das hab ich jetzt so abgeändert:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('vorher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  if (x < 0then
    x := x +N;
  if (y < 0then
    y := y +N;
   if (x > (N-1)) then
    x := x -N;
  if (y > (N-1)) then
    y := y -N;
  ShowMessageFmt('nachher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y];
end;


Narses - So 15.03.15 14:37

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
da gibt es jetzt zellen mit [4,4] und so und die gibt es nicht, die müssen wieder auf die andere seite
Jap. :)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das hab ich jetzt so abgeändert:
Funktionsfähig, zwar etwas umständlich, aber OK! :zustimm:

Dann nimm mal die Testausgaben raus, damit du dich gleich nicht "totklickst". ;) Wir sind soweit, einen echten Lauf zu probieren. :hair: Also klick dir mal drei schwarze Zellen horizontal oder vertikal zusammen (einen "Strich"), dann auf den btnLesen, dann btnRechnen, dann btnSchreiben und ab da:
btnRechnen -> btnSchreiben -> btnRechnen -> btnSchreiben usw.

Was passiert? :lupe:

cu
Narses


Nini - So 15.03.15 14:40

erst sind die zellen oxo dann ooo
oxo xxx
oxo ooo

und das wechselt sich immer ab


Narses - So 15.03.15 14:46

Moin!

Passt, der Strich wechselt also immer von liegend auf stehend und zurück. ;)

Dann mach mal die mittleren 4 Zellen schwarz und lass den Rand weiß. Wieder so vorgehen wie gerade, Lesen, Rechnen, Schreiben, Rechnen, Schreiben, etc.

Was passiert?

cu
Narses


Nini - So 15.03.15 14:47

die vier in der mitte bleiben schwarz, der rest bleibt weiß


Narses - So 15.03.15 14:52

Moin!

Und, ist das OK so oder nicht? :gruebel:

cu
Narses


Nini - So 15.03.15 14:56

das stimmt so


Narses - So 15.03.15 14:58

Moin!

Fein. :zustimm:

Dann erweitern wir erstmal das Feld auf 5x5 Shapes. Kannst du das mal kurz machen? Was muss man da alles tun (Stichpunkte reichen)?

Wenn das läuft, machen wir noch die Automatik dazu und dann ist gut. :)

cu
Narses


Nini - So 15.03.15 15:00

- die shapes hinzufügen
- die shapes auch mit in die procedure TForm1.Shape1MouseDown einbinden
- N von 4 auf 5 ändern


Narses - So 15.03.15 15:01

Moin!

GO! :zustimm:

cu
Narses


Nini - So 15.03.15 15:06

schon erledigt ;)


Narses - So 15.03.15 15:22

Moin!

Top! :D

Jetzt noch eine kleine Optimierung: wir haben immer nach einem Klick auf den btnRechnen auch auf den btnSchreiben gemacht (sonst sieht man ja nicht, was da berechnet wurde). Das machen wir jetzt per Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TForm1.btnRechnenClick(Sender: TObject);
  var
    x, y: Integer;
    FeldNeu: TFeld;
begin
  for y := 0 to N-1 do
    for x := 0 to N-1 do
      if Feld[x, y] then // lebende Zelle
        FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in [2..3]) // Überleben
      else // tote Zelle
        FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) = 3); // Geburt
  Feld := FeldNeu;
  btnSchreibenClick(Self); // virtuell auf den Button klicken
end;


Dann löschst du alle Buttons aus dem Formular (dabei sollte der Code für die Button-Handler stehen bleiben - bis auf den Test-Button, den kannst du ganz rausnehmen, mit Code).

Jetzt geht´s an die Automatik: leg einen Timer auf das Formular, den Namen änderst du auf "Timer" (die "1" kann weg, wir brauchen nur einen) und die Eigenschaft .Enabled auf "False" (der soll nicht von selbst loslaufen, wenn das Programm startet). Anschließend legst du noch eine Checkbox neu auf das Formular, die nennst du mal "ckAutomatik" und bei Caption kannst du reinschreiben, was du möchtest, die Eigenschaft .Checked bleibt auf "False" stehen.

Jetzt machst du einen Doppelklick auf der Checkbox, es wird ein Handler erstellt, da schreibst du rein:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm1.ckAutomatikClick(Sender: TObject);
begin
  if ckAutomatik.Checked then begin // Haken reingeklickt
    btnLesenClick(Self); // Feld einlesen
    Timer.Enabled := True; // Timer einschalten
  end
  else // Haken rausgeklickt
    Timer.Enabled := False; // Timer ausschalten
end;

cu
Narses


Nini - So 15.03.15 15:31

ok, ich habe alles so gemacht


Narses - So 15.03.15 15:32

Moin!

Gut, was passiert, wenn du den Haken setzt?

cu
Narses


Nini - So 15.03.15 15:37

gar nichts :(


Narses - So 15.03.15 15:39

Moin!

Warum? :lupe: Und was tun wir dagegen? :gruebel:

cu
Narses


Nini - So 15.03.15 15:42

weil in der lesenprozedur nicht gesagt wird, dass die rechenprozedur aufgerufen wird, also muss ich dort jetzt das so machen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.btnLesenClick(Sender: TObject);
var x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1;
            Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False;
        end;
      btnRechnenClick(Self);
end;


Narses - So 15.03.15 15:46

Moin!

Und, klappt´s jetzt (ich sag mal: nein :zwinker:)?

cu
Narses


Nini - So 15.03.15 15:55

hast recht, es geht nicht

es verändert sich eine generation lang und dann bleibt's stehn


Narses - So 15.03.15 15:56

Moin!

Jo, so ist es. :nixweiss: Also: kannst den Button-Aufruf da wieder raus nehmen.

Wie funktioniert denn ein Timer? Haben wir irgendwo gesagt, was der machen soll? :lupe: 8)

cu
Narses


Nini - So 15.03.15 15:59

nein, also so wirklich hab ich keine ahnung wie timer funktionieren :/


Narses - So 15.03.15 16:00

Moin!

Dann mach doch mal einen Doppelklick auf der Timer-Komponenten im Formular... :zwinker:

cu
Narses


Nini - So 15.03.15 16:01

damit hab ich eine weitere prozedur geöffnet.
muss ich da jetzt reinschreiben, dass er den rechnenbutton ausführen soll?


Narses - So 15.03.15 16:07

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
muss ich da jetzt reinschreiben, dass er den rechnenbutton ausführen soll?
Jup. ;)

cu
Narses


Nini - So 15.03.15 16:09

es funktioniert *_*


Narses - So 15.03.15 16:35

Moin!

:party: :dance2: :beer: :dance:


Wie sieht´s aus, rein von der Aufgabe her bist du fertig: Game of Life läuft. :zustimm:

Willst du noch ein bisschen optimieren? ;) Evtl. könnte man ja die Feldgröße unabhängig von manuell angelegten Shapes machen? (man kann die Shapes auch per Programmcode anlegen und muss dann nur noch N ändern, wenn man das Feld größer machen möchte :idea:)

cu
Narses


Nini - So 15.03.15 16:47

joar, das hört sich gut an :)

kann man eigentlich das programm auch so ändern, dass der nutzer die regeln für geburt/tod ändern können?


Narses - So 15.03.15 17:06

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
joar, das hört sich gut an :)
Gut, dann schauen wir mal, was noch geht. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
kann man eigentlich das programm auch so ändern, dass der nutzer die regeln für geburt/tod ändern können?
Mann kann schon, die Frage ist eher: kann Frau auch? :zwinker: (soll heißen: ja, klar kann man, aber wenn du keine Idee hast wie, könnte es noch etwas schwer sein für dich, oder?)

Dann zeig doch bitte erstmal deinen kompletten Code, damit ich den aktuellen Status kenne. :zustimm:

cu
Narses


Nini - So 15.03.15 17:21


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:
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:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;

const
  N = 5;
type
  TFeld = array[0..N-10..N-1of Boolean;

  { TForm1 }

  TForm1 = class(TForm)
    ckAutomatik: TCheckBox;
    Ende: TButton;
    Shape1: TShape;
    Shape10: TShape;
    Shape11: TShape;
    Shape12: TShape;
    Shape13: TShape;
    Shape14: TShape;
    Shape15: TShape;
    Shape16: TShape;
    Shape17: TShape;
    Shape18: TShape;
    Shape19: TShape;
    Shape2: TShape;
    Shape20: TShape;
    Shape21: TShape;
    Shape22: TShape;
    Shape23: TShape;
    Shape24: TShape;
    Shape25: TShape;

    Timer: TTimer;
    procedure btnLesenClick(Sender: TObject);
    procedure btnRechnenClick(Sender: TObject);
    procedure btnSchreibenClick(Sender: TObject);
    procedure ckAutomatikChange(Sender: TObject);
    procedure EndeClick(Sender: TObject);
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure TimerTimer(Sender: TObject);

  private

  public
    Feld: TFeld; // das ist der interne Speicher für die Zellen (=Shapes in der GUI)
    function LebtNachbar(x, y: Integer): Boolean;
    function AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  if (x < 0then
    x := x +N;
  if (y < 0then
    y := y +N;
   if (x > (N-1)) then
    x := x -N;
  if (y > (N-1)) then
    y := y -N;
  Result := Feld[x, y];
end;

function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  var
    dx, dy: Integer;
begin
  Result := 0;
  for dy := -1 to 1 do
    for dx := -1 to 1 do begin
     if not ((dx=0and (dy=0)) then
         if LebtNachbar(x +dx, y +dy) then
        Inc(Result);
    end;
end;


procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1;
           Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;
       end;

end;

procedure TForm1.ckAutomatikChange(Sender: TObject);
begin
    if ckAutomatik.Checked then begin // Haken reingeklickt
    btnLesenClick(Self); // Feld einlesen
    Timer.Enabled := True; // Timer einschalten
  end
  else // Haken rausgeklickt
    Timer.Enabled := False; // Timer ausschalten
end;

procedure TForm1.EndeClick(Sender: TObject);
begin
  close;
end;


procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var  ThisShape: TShape;
begin
  ThisShape := (Sender as TShape);
  if (ThisShape.Brush.Color = clWhite) then
     ThisShape.Brush.Color := clBlack
  else
     ThisShape.Brush.Color := clWhite;
end;

procedure TForm1.TimerTimer(Sender: TObject);
begin
  btnrechnenClick(Self);
end;

procedure TForm1.btnLesenClick(Sender: TObject);
var x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1;
            Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False;
        end;

end;

procedure TForm1.btnRechnenClick(Sender: TObject);
  var
    x, y: Integer;
    FeldNeu: TFeld;
begin
  for y := 0 to N-1 do
    for x := 0 to N-1 do
      if Feld[x, y] then // lebende Zelle
        FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in [2..3]) // Überleben
      else // tote Zelle
        FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) = 3); // Geburt
  Feld := FeldNeu;
  btnSchreibenClick(Self); // virtuell auf den Button klicken

end;
end.


das könnte gut sein :P


Narses - So 15.03.15 17:32

Moin!

Soo, dann gehen wir erstmal hier noch dran:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  if (x < 0then
    x := x +N;
  if (y < 0then
    y := y +N;
   if (x > (N-1)) then
    x := x -N;
  if (y > (N-1)) then
    y := y -N;
  Result := Feld[x, y];
end;

Der markierte Teil "gefällt" mir noch nicht. :? (ist nicht falsch, nur ... unschön)

user profile iconBoldar hat schonmal drauf hingewiesen, es gibt die Modulo-Rechnung. Was war das nochmal? :les:

cu
Narses


Nini - So 15.03.15 18:35

bei x mod y wird nur der rest bei der division von x durch y angegeben

irgendwie hab ich das gefühl, dass das programm bei 5 feldern macht was es will, eigentlich muss ja so ein balken aus drei feldern sich immer drehn aber der verschwindet einfach -.-


Narses - So 15.03.15 18:50

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
bei x mod y wird nur der rest bei der division von x durch y angegeben
Richtig. Wir haben da also ein x, und das soll nur Werte zwischen 0..(N-1) annehmen können. Wie müsste man das dann mit mod schreiben?

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
irgendwie hab ich das gefühl, dass das programm bei 5 feldern macht was es will, eigentlich muss ja so ein balken aus drei feldern sich immer drehn aber der verschwindet einfach -.-
Kontrollier mal die Reihenfolge der Shapes (also der Reihe nach eins im Formular anklicken und dann schauen, welche Nummer das hat - da könnte was schief gelaufen sein). :idea:

cu
Narses


Nini - So 15.03.15 19:00

ok, danke :) daran hat es wohl gelegen ..

ich vermute, dass das x MOD (N-1) sein müsste


Narses - So 15.03.15 19:11

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ok, danke :) daran hat es wohl gelegen ..
;)


user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich vermute, dass das x MOD (N-1) sein müsste
Hm, Vermutungen... :gruebel:

Dann mal ein konkretes Beispiel: sagen wir mal, N = 5, dann haben wir für

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
x  | x mod N
------------
0  |
1  |
2  |
3  |
4  |
5  |
6  |
17 |

Mal bitte die Tabelle ausfüllen... :les:

cu
Narses


Nini - So 15.03.15 19:16


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
x  | x mod N
------------
0  |0
1  |1
2  |2
3  |3
4  |4
5  |5
6  |1
17 |2


Narses - So 15.03.15 19:21

Moin!

Danke, ist aber leider (nicht ganz, aber genug) falsch. :?

Kommen wir also wieder zu unserem Test-Button (das kennst du ja schon, Button auf´s Formular klatschen, doppelklicken, loslegen):

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.btnTestClick(Sender: TObject);
begin
  ShowMessageFmt('x=%d, N=%d, x mod N=%d', [050 mod 5]); // das ist praktisch die erste Zeile aus der Tabelle
end;

Damit mal bitte testen gehen... :lupe:

cu
Narses


Nini - So 15.03.15 19:27

da kommt dann: x=0, N=5, x MOD N=0


Narses - So 15.03.15 19:29

Moin!

Sehr schön, damit überprüfst du jetzt mal die Tabelle da oben. :idea: :lupe:

(und wenn du ganz pfiffig bist, dann automatisierst du dir das sogar... 8) wenn nicht, auch nicht schlimm, dann halt immer wieder die Zeile anpassen, Programm starten, Button anklicken, etc.)

cu
Narses


Nini - So 15.03.15 19:33


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
x  | x mod N
------------
0  |0
1  |1
2  |2
3  |3
4  |4
5  |0
6  |1
17 |2


Narses - So 15.03.15 19:34

Moin!

Sehr gut, wo war der Fehler? :lupe:

Erweiterung: was ist mit -1 mod 5?

cu
Narses


Nini - So 15.03.15 19:36

das bei 5 mod 5 natürlich kein rest bleiben kann ... :P

da kommt -1 als ergebnis raus


Narses - So 15.03.15 19:43

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das bei 5 mod 5 natürlich kein rest bleiben kann ... :P
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
da kommt -1 als ergebnis raus
Ja, doof, nicht wahr? :? Sehen wir gleich noch...

Bei der Modulorechnung ist also festzuhalten: x mod N ist immer kleiner als N :idea:

Was ist denn mit diesen Termen: x = (x mod N) = ((x +N) mod N) = ((x +2N) mod N)

Für welche x ergibt sich hier eine wahre Aussage?

cu
Narses


Nini - So 15.03.15 20:01

für alle x = N


Narses - So 15.03.15 20:08

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
für alle x = N
Nö, für die genau nicht mehr. :lupe: sondern :arrow: für x = 0 .. N-1 :think:

Und jetzt drehen wir mal die Denkrichtung um (und lesen die Terme umgekehrt): Es ist also völlig egal, wieviele N wir auf x addieren, solange wir am Ende ein mod N machen, ist das immer gleich!

Nächster Schritt, hier:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('vorher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  if (x < 0then
    x := x +N;
  if (y < 0then
    y := y +N;
   if (x > (N-1)) then
    x := x -N;
  if (y > (N-1)) then
    y := y -N;
  ShowMessageFmt('nachher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y];
end;
haben wir uns doch ziemlich einen abgebrochen, um am Ende (Markierung) in den Bereich 0..N-1 zu kommen. Wir hatten erst mit x = -1 zu kämpfen, dann mit x = N, was wieder "zuviel" war. :nixweiss:

Wenn wir also am Ende schreiben:

Delphi-Quelltext
1:
Result := Feld[x mod N, y mod N];                    
dann können wir von den if-Anweisungen was einsparen. Aber welche? :gruebel: Mach mal einen Vorschlag.

cu
Narses


Nini - So 15.03.15 20:15

die beiden wo wir +N rechnen, also die beiden für x<0 brauchen wir nicht mehr


Narses - So 15.03.15 20:20

Moin!

Meinst du das so?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  ShowMessageFmt('vorher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
//  if (x < 0) then
//    x := x +N;
//  if (y < 0) then
//    y := y +N;
   if (x > (N-1)) then
    x := x -N;
  if (y > (N-1)) then
    y := y -N;
  x := x mod N; // das mod N schon hier rechnen,
  y := y mod N; // damit man das gleich ausgeben kann
  ShowMessageFmt('nachher: x=%d, y=%d', [x, y]); // das hier ist nur zum Testen
  Result := Feld[x, y]; // hier wieder rausgenommen und nach oben verschoben
end;


Dann mach mal in den Test-Button wieder einen Aufruf wie neulich rein:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.btnTestClick(Sender: TObject);
begin
  AnzahlLebenderNachbarn(00); // Test-Aufruf
end;

Und, was passiert?

cu
Narses


Nini - So 15.03.15 20:30

ok, das war keine gute idee, die vorher- und nacherwerte sind identisch :/

ich kann genau das andere rausnehmen,also für x >(N-1), das klapppt dann wieder wie es soll


Narses - So 15.03.15 22:26

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ok, das war keine gute idee, die vorher- und nacherwerte sind identisch :/
;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich kann genau das andere rausnehmen,also für x >(N-1), das klapppt dann wieder wie es soll
Genau so ist es, du hast ja für N <= x < 2N genau den Effekt, den mod N bewirkt, wenn du x -N rechnest. :idea: Deshalb ist es die zweite if-Gruppe, die rausfällt.

Wie werden wir denn nun die erste if-Gruppe auch noch los? :gruebel: Hier wirkt ja leider mod N nicht, weil wir bereits festgestellt haben, dass -1 mod N auch = -1 bleibt (das war das mit dem "doof" :zwinker:)...

Ideen? :D

cu
Narses


Nini - So 15.03.15 22:30

nein, also um ehrlich zu sein, fällt mir nichts ein, wie die If-anweisung weg könnte :(


Narses - Mo 16.03.15 00:05

Moin!

OK, dann fassen wir nochmal zusammen:

a) wir können "mod N" nutzen, um Werte größer N "abzufangen"
b) man kann beliebig oft N addieren, solange man irgendwann "mod N" rechnet, ist das egal (also zumindest in unserem Rahmen hier)

Das waren die beiden Erkenntnisse, die wir aus dem Mathe-Vortrag vorhin gewonnen haben (oder haben sollten :angel:). a) haben wird schon "untergebracht", was bleibt noch? :zwinker:

cu
Narses


Nini - Mo 16.03.15 17:26

bei mir hängt es anscheinend, ich sehe einfach keine möglichkeit das noch weoiter zu vereinfachen ;/


Narses - Mo 16.03.15 17:29

Moin!

Wir haben in der ersten if-Gruppe N addiert, wenn x < 0 ist. Könnte man nicht "gefahrlos" immer x addieren? (weil wir doch mod N nutzen) :idea:

cu
Narses


Nini - Mo 16.03.15 17:35

aber wenn x = -1 dann ist doch wenn ich x addiere das neue x=-2 oder hab ich nen denkfehler?


Narses - Mo 16.03.15 17:37

Moin!

x addieren... :autsch: :oops: :lol:

N addieren natürlich! :P

cu
Narses


Nini - Mo 16.03.15 17:44

also N addieren geht problemlos


Narses - Mo 16.03.15 17:47

Moin!

Ja dann, her mit dem Codevorschlag. ;)

cu
Narses


Nini - Mo 16.03.15 17:52

also ich würd es ja einfahc so lassen, weiß nicht, was ich so genau ändern soll


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
  
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  if (x < 0then
    x := x +N;
  if (y < 0then
    y := y +N;
  
  Result := Feld[x mod N, y mod N];
end;


Narses - Mo 16.03.15 17:55

Moin!

Wir haben doch festgestellt, dass man immer N addieren kann, nicht nur dann, wenn x < 0 ist. Also können auf jeden Fall die beiden if-Zeilen raus. Und dann schau mal, ob man da noch was zusammenfassen kann. :lupe:

cu
Narses


Nini - Mo 16.03.15 18:24

vielleicht so:

Delphi-Quelltext
1:
2:
3:
4:
function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  Result := Feld[(x+N) mod N, (y+N) mod N];
end;


Narses - Mo 16.03.15 18:32

Moin!

Perfekt! :zustimm:

Dann würde ich hier gerne noch das "not" entfernen (zugegeben, mehr aus didaktischen Gründen, als dass es großen Nutzen hätte). ;)

Delphi-Quelltext
1:
if not ((dx = 0and (dy = 0)) then                    

Was tut "not"? Es negiert die Bedingung. Wenn wir also das not entfernen wollen, müssen wir alle Terme in der Klammer negieren (also das Gegenteil abfragen).

Probier mal. :)

cu
Narses


Nini - Mo 16.03.15 18:36

vielleicht funktioniert das ja so

Delphi-Quelltext
1:
   if  ((dx<>0and (dy<>0)) then                    


Narses - Mo 16.03.15 18:38

Moin!

Probiers doch einfach mal im Programm aus. :zwinker: (ist schon gar nicht so schlecht :zustimm:)

cu
Narses


Nini - Mo 16.03.15 18:47

das programm läuft, aber nicht ganz richtig


Narses - Mo 16.03.15 19:01

Moin!

Genau, so ist es. Aber was heißt denn, nicht ganz richtig? (naja, ich weiß es natürlich, deshalb schlage ich vor, wir untersuchen besser nicht, was da im Game of Life schief läuft, das könnte nämlich haarig werden, sondern betrachten das separat)


Quelltext
1:
2:
3:
4:
5:
6:
a | b | not (a and b) | (not a) and (not b)
-------------------------------------------
0 | 0 |       ?       |          ?
0 | 1 |       ?       |          ?
1 | 0 |       ?       |          ?
1 | 1 |       ?       |          ?

Bitte mal ausfüllen. :les:

cu
Narses


Nini - Mo 16.03.15 19:47

ich hab keine ahnung, was ich rechnen muss :/


Narses - Mo 16.03.15 20:24

Moin!

OK, das nennt man Wahrheitstabelle [http://de.wikipedia.org/wiki/Wahrheitstabelle]. :idea: Hier mal ein paar einfache Beispiele:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
a | b | a and b
---------------
0 | 0 |    0
0 | 1 |    0
1 | 0 |    0
1 | 1 |    1

a | b | a or b
---------------
0 | 0 |    0
0 | 1 |    1
1 | 0 |    1
1 | 1 |    1

a | not a
---------
0 |   1
1 |   0

Dabei steht 0 für False und 1 für True. Jetzt klarer? ;)

cu
Narses


Nini - Mo 16.03.15 20:33

dann wäre die erste spalte, wenn ich es richtig verstanden habe


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
a | b | not (a and b) | (not a) and (not b)
-------------------------------------------
0 | 0 |       1       |          ?
0 | 1 |       1       |          ?
1 | 0 |       1       |          ?
1 | 1 |       0       |          ?


Narses - Mo 16.03.15 20:45

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
dann wäre die erste spalte, wenn ich es richtig verstanden habe
Jap, hast du. :zustimm:

Und wenn unsere umgewandelte Formel in der letzten Spalte korrekt ist, sollte da genau das Gleiche rauskommen (wir haben ja nur das not in die Klammer gezogen). :les:

cu
Narses


Nini - Mo 16.03.15 20:51

aaaaaaachso :P sowas wie assoziativgesetz also


Narses - Mo 16.03.15 21:05

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aaaaaaachso :P sowas wie assoziativgesetz also
:shock: Wow, ja, genau sowas. (Aber eben nicht ganz 8))

cu
Narses


Nini - Mo 16.03.15 21:06

ie krieg ich das jetzt so umgewandelt, dass das programm wieder richtig läuft?


Narses - Mo 16.03.15 21:10

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ie krieg ich das jetzt so umgewandelt, dass das programm wieder richtig läuft?
Indem du das Gehirn einschaltest, die Tabelle ausfüllst, feststellst, dass die Formel nicht korrekt ist, diese korrigierst, die Tabelle auch und dann die Erkenntnis auf die Delphi-Zeile anwendest. :zwinker:

cu
Narses


Nini - Mo 16.03.15 21:26

ich bin überfordert :(


Narses - Mo 16.03.15 21:31

Moin!

Ach, das wird schon, nicht aufgeben. :zustimm:

Dann machen wir die erste Zeile mal zusammen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
a | b | not (a and b) | (not a) and (not b)
-------------------------------------------
0 | 0 |       1       | (not 0and (not 0) = 1 and 1 = 1
0 | 1 |       1       |          ?
1 | 0 |       1       |          ?
1 | 1 |       0       |          ?

Jetzt klarer? Einfach die Werte einsetzen und ausrechnen. :idea:

cu
Narses


Nini - Mo 16.03.15 21:34


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
a | b | not (a and b) | (not a) and (not b)
-------------------------------------------
0 | 0 |       1       | (not 0and (not 0) = 1 and 1 = 1
0 | 1 |       1       | (not 0and (not 1) = 1 and 0 = 0        
1 | 0 |       1       | (not 1and (not 0) = 0 and 1 = 0 
1 | 1 |       0       | (not 1and (not 1) = 0 and 0 = 0


Narses - Mo 16.03.15 21:39

Moin!

Passt. :) Na, war doch gar nicht schwer, oder? ;)

Leider passt aber unsere Formeltransformation offensichtlich nicht, denn da kommt was anderes als in der Spalte davor... :? Vorschlag für eine Korrektur?

cu
Narses


Nini - Mo 16.03.15 21:47

nein, so logische verknüpfungen find ich total kompliziert :(


Narses - Mo 16.03.15 21:51

Moin!

Nur auf den ersten Blick, eigentlich ist das fast immer das Gleiche und total regelmäßig. ;)

Dann schau mal hier rein, das ist die Lösung: http://de.m.wikipedia.org/wiki/De_Morgansche_Gesetze

Einfach mal versuchen, ist nicht schwer. :zustimm:

cu
Narses


Nini - Mo 16.03.15 22:11

das heißt jetzt, dass not (a and b) = (not a) or (not b)


Narses - Mo 16.03.15 22:15

Moin!

Top! :zustimm: Erkenntnis: wenn man bool'sche Terme negiert, müssen auch die Operatoren angepasst werden. Aus und wird oder und umgekehrt. :idea: Spannend, oder? :D

Und jetzt solltest du auch die Delphi-Zeile wieder reparieren können. ;)

cu
Narses


Nini - Mo 16.03.15 22:21

so?


Delphi-Quelltext
1:
if  ((not a) or (not b))<>0)  then                    


Narses - Mo 16.03.15 22:24

Moin!

Ne ;) "a" steht doch für "dx = 0", ein a kam vorher ja auch nicht vor... :lupe:

cu
Narses

PS: Öhm, vor deinem Edit war's richtiger... :?


Nini - Mo 16.03.15 22:27

dann vielleicht so:

Delphi-Quelltext
1:
if  ((dx<>0or (dy<>0)) then                    


Narses - Mo 16.03.15 22:31

Moin!

Genau so, optimal! :zustimm: Schon ausprobiert? ;)

Dann können wir uns langsam wieder den Shapes zuwenden. :les:

cu
Narses

PS: Ich bin gleich mal ne Stunde oder so offline.


Nini - Mo 16.03.15 22:43

jaaa, es funktioniert :)


Narses - Mo 16.03.15 23:38

Moin!

Soo, dann gehen wir mal an die dynamischen Shapes. ;)

Leg ein neues Projekt (zum Testen) an und lege einfach irgendwo (in die Mitte z.B.) einen Button ab. In dessen Handler schreibst du:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.btnTestClick(Sender: TObject);
  var
    Shape: TShape;
begin
  Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
  Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
  Shape.Name := 'Shape1'// Name der Komponente
  Shape.Left := 8// 8 Pixel vom linken Rand
  Shape.Top := 8// 8 Pixel vom oberen Rand
  Shape.Width := 25// 25 Pixel breit
  Shape.Height := 25// 25 Pixel hoch
// Shape.OnMouseDown := Shape1MouseDown; // haben wir hier nicht, aber so weist man eine Methode zu
end;

Damit machen wir per Programmcode genau das, was die IDE automatisch macht, wenn du ein Shape aus der Komponentenpalette auf das Formular klickst. Aber eben nicht zur Entwurfszeit, sondern (erst) zur Laufzeit des Programms! :idea:

Noch etwas zu dem "Self"-Parameter beim Create: normalerweise muss man Objekte, die man zur Laufzeit erstellt, auch selbst wieder freigeben (weil dafür Speicher reserviert wird, der sonst nicht wieder freigegeben wird - das berühmte "memory leak"). Bei visuellen Komponenten gibt es aber einen praktischen Mechanismus, man kann nämlich beim Erzeugen einen "Eigentümer" angeben - und der ist dann dafür verantwortlich, dass die Komponente (und der zugehörige Speicher) beim Beenden des Programmes auch wieder freigegeben wird.

Probier mal aus, was da passiert. Wenn du das Programm startest und auf den Button klickst, sollte ein Shape links oben in der Ecke erscheinen. ;)

cu
Narses


Narses - Mi 18.03.15 20:58

Moin!

Und, schon ausprobiert? ;)

cu
Narses


Nini - Mi 18.03.15 21:12

ja,gere eben ausprobiert, wollte auch gleich noch antworten :P

es kommen voll viele fehlermeldungen :/


Narses - Mi 18.03.15 21:14

Moin!

Du hast auch ein komplett neues Projekt zum Testen genommen? (wenn beim 2. Klick auf den Button Fehlermeldungen kommen, ist das normal)

Welche Fehler kommen? Kannste die mal hier reinkopieren? :lupe: :les:

cu
Narses


Nini - Mi 18.03.15 22:25

die fehlermeldugnen auf dem bild zeigts mir alle an

ja, ich hab nen gesamtneues dings genommen


Narses - Mi 18.03.15 22:45

Moin!

Ach so, der Compiler sagt doch nur, dass er TShape nicht kennt... :P Füg mal oben in der uses-Klausel ein:

Delphi-Quelltext
1:
2:
uses
  ..., ExtCtrls;

Das sollte dann klappen. ;)

cu
Narses


Nini - Mo 23.03.15 16:23

so, jetzt hab ich mal wieder Zeit zum programmieren :)

irgendwas klappt dann immer noch nicht, ich bekomme 49 Fehlermeldungen o.O


Narses - Mo 23.03.15 21:32

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
so, jetzt hab ich mal wieder Zeit zum programmieren :)
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
irgendwas klappt dann immer noch nicht
:gruebel: Sehr komische Meldungen. Ich bin zugegeben nicht so firm mit Lazarus (muss mir doch mal bei Gelegenheit eine Test-Installation anlegen; welches Lazarus verwendest du? :lupe:)...

OK, gehen wir anders ran: Pack mal ein Shape auf das Formular, irgendeins, irgendwo. Das nennst du dann "TestShape" oder so (ist egal, nur nicht "Shape1"). Jetzt sollte sich automatisch die uses-Klausel oben im Projekt verändert haben, richtig? :les: Und jetzt sollte auch der Button-Code laufen bzw. sich das Ding überhaupt kompilieren lassen? :suspect:

cu
Narses


Nini - Mo 23.03.15 22:00

ich verwende Lazarus IDE v1.2.6

wenn ich das Shape reinmache, dann kommt zu uses noch ExtCtrls dazu aber dann bleiben die 49 fehlermeldungen, wenn ich das aber rauslösche und das shape drinnen lasse sind es immerhin nur noch 3 Fehlermeldungen:
Identifier not found "TShape"
Error in type definition
Symbol can't be published, can be only a class


Narses - Mo 23.03.15 22:04

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich verwende Lazarus IDE v1.2.6
OK, danke.

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
wenn ich das Shape reinmache, dann kommt zu uses noch ExtCtrls dazu
Wie jetzt "kommt dazu", das hatte ich doch ein paar Posts weiter oben schon erwähnt, hattest du das noch nicht mit drin? :gruebel:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber dann bleiben die 49 fehlermeldungen, wenn ich das aber rauslösche und das shape drinnen lasse sind es immerhin nur noch 3 Fehlermeldungen:
Zeig mal eben den kompletten Projekt-Quelltext. :les:

cu
Narses


Nini - Mo 23.03.15 22:07

ich bin überfordert :P


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:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls;

type

  { TForm1 }

    TForm1 = class(TForm)
    btnTest: TButton;
    testShape: TShape;
    procedure btnTestClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

  procedure TForm1.btnTestClick(Sender: TObject);
  var
    Shape: TShape;
begin
  Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
  Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
  Shape.Name := 'Shape1'// Name der Komponente
  Shape.Left := 8// 8 Pixel vom linken Rand
  Shape.Top := 8// 8 Pixel vom oberen Rand
  Shape.Width := 25// 25 Pixel breit
  Shape.Height := 25// 25 Pixel hoch
// Shape.OnMouseDown := Shape1MouseDown; // haben wir hier nicht, aber so weist man eine Methode zu
end;
end.


Narses - Mo 23.03.15 23:25

Moin!

Ich krieg jetzt auf die Schnelle keine Lazarus-Install gemacht... :? Aber an deinem Code ist auch nix komisches, wenn ich das mit dem hier [http://wiki.freepascal.org/Formular-Komponenten_in_Lazarus_dynamisch_erzeugen] vergleiche, dann geht das in Lazarus genau so wie in Delphi. :lupe: :nixweiss: Das muss also irgendwas anderes sein... :gruebel:

Gut, fangen wir nochmal langsam an:
Bei welchem Schritt fangen die Probleme an? :suspect:

cu
Narses


Nini - Mo 23.03.15 23:52

Ich kann es mir zwar nicht erklären, aber dieses Mal hat es ohne Fehlermeldung funktioniert und dann auch das Programm korrekt ausgeführt ?!


Narses - Di 24.03.15 00:00

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Ich kann es mir zwar nicht erklären, aber dieses Mal hat es ohne Fehlermeldung funktioniert
:zustimm: Tja, war wohl Schluckauf... :lol:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und dann auch das Programm korrekt ausgeführt ?!
Soll heißen, wenn du auf den Button klickst, wird ein neues Shape erstellt? ;)

cu
Narses


Nini - Di 24.03.15 00:02

genau, da kommt nen neues shape oben links :)


Narses - Di 24.03.15 00:07

Moin!

Perfekt! :zustimm:

Nächster Schritt: wieder zum Game of Life Projekt wechseln und alle Shapes vom Formular löschen. :hair: Keine Panik, die legen wir gleich alle wieder beim Programmstart automatisch an. ;)

Dazu machst du einen Doppelklick auf dem Formularhintergrund, es sollte ein neuer Handler angelegt werden, und zwar für das Ereignis FormCreate. :idea: Da müssen wir nun den Code reinschreiben, der die Shapes erzeugt. Wie man ein Shape erzeugt hast du nun gesehen und getestet. Dann mach doch mal einen (Code-)Vorschlag, wie man das auf die Menge Shapes "aufbohrt", die wir brauchen. :lupe: (ich würde als Tipp mal so sagen, du brauchst da ne Schleife, so ähnlich wie beim btnLesenClick :think:)

cu
Narses


Nini - Di 24.03.15 00:15

mein vorschlag wäre das:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.FormCreate(Sender: TObject);
var i,j,x : integer;
    shape : TShape;
begin
  x := strtoint(edit1.text);
  for j := 1 to x do
   for i := 1 to x do begin
    Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    Shape.Name := 'Shape'+i; // Name der Komponente
    Shape.Left := 8+i*25// 8 Pixel vom linken Rand
    Shape.Top := 8+i*25// 8 Pixel vom oberen Rand
    Shape.Width := 25// 25 Pixel breit
    Shape.Height := 25// 25 Pixel hoch
  end;
end;


Narses - Di 24.03.15 00:22

Moin!

Gar nicht übel! :zustimm:

Allerdings muss ich dir leider den Zahn mit dem Edit-Feld und der Eingabe der Feldgröße zur Laufzeit wieder ziehen :? das geht leider nicht ganz so einfach (also es geht schon, aber eben etwas anders). :nixweiss:

Du musst in diesem Ansatz einfach N für die Kantenlänge verwenden, also die Konstante, die du im Programm ganz oben deklariert hast. :idea: Und dann noch beim Namen des Shapes beachten, dass dieser sowohl eindeutig, als auch der Konvention ("Reihenfolge") entspricht, wie bei den manuell angelegten Shapes (im Moment erzeugst du Shapes, die mehrfach den gleichen Namen haben :shock:).

Also, nächster Versuch. ;)

cu
Narses


Nini - Di 24.03.15 00:27

meine nächste Variante:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm1.FormCreate(Sender: TObject);
var i,j,snr : integer;
    shape : TShape;
begin
  for j := 0 to N-1 do
   for i := 0 to N-1 do begin
    Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
    //Shape.Name := 'Shape'+inttostr(i); // Name der Komponente
    Shape.Left := 8+i*25// 8 Pixel vom linken Rand
    Shape.Top := 8+i*25// 8 Pixel vom oberen Rand
    Shape.Width := 25// 25 Pixel breit
    Shape.Height := 25// 25 Pixel hoch
  end;
end;


Narses - Di 24.03.15 00:32

Moin!

Schon besser. ;)

Aaaaber... :P


Delphi-Quelltext
1:
snr := x +y *N +1;                    
Damit berechnest du (völlig korrekt!) die Shape-Nr. :zustimm:


Delphi-Quelltext
1:
Shape := TShape(FindComponent('Shape' +IntToStr(snr)));                    
Statt diese zu verwenden, versuchst du ein bereits vorhandenes Shape zu finden :lupe: :?!?: (was es logischerweise nicht gibt!)


Delphi-Quelltext
1:
//Shape.Name := 'Shape'+inttostr(i); // Name der Komponente                    
...und kommentierst den (fast korrekten) Code, der das was du brauchst, tut, aus. :eyes:

Also: noch ein Versuch! :D

cu
Narses


Nini - Di 24.03.15 00:34


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.FormCreate(Sender: TObject);
var i,j,snr : integer;
    shape : TShape;
begin
  for j := 0 to N-1 do
   for i := 0 to N-1 do begin
    Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 8+i*25// 8 Pixel vom linken Rand
    Shape.Top := 8+i*25// 8 Pixel vom oberen Rand
    Shape.Width := 25// 25 Pixel breit
    Shape.Height := 25// 25 Pixel hoch
  end;
end;


so das dürfte jetzt stimmen


Narses - Di 24.03.15 00:39

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
so das dürfte jetzt stimmen
Jap, sieht gut aus! :zustimm: Schon ausprobiert? ;) Was fehlt noch (funktional)? :P

cu
Narses

PS: Ah, kleiner Bug ist noch drin... :zwinker:


Nini - Di 24.03.15 00:43

musste noch x und y als integer deklarieren aber was ich gegen die debuggernachricht machen soll weiß ich gar nicht ... :(


Narses - Di 24.03.15 00:53

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
musste noch x und y als integer deklarieren
Jap, genau da ist noch was im Argen... ;) Tipp: Entweder du verwendest x und y oder du verwendet i und j, beides "mischen" ist nicht so schlau. :zwinker:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber was ich gegen die debuggernachricht machen soll weiß ich gar nicht ... :(
Dazu müsstest du diese mal zeigen. :lupe: :les:

Aber korrigier erstmal noch das Index-Problem in den Schleifen/Deklaration, vielleicht ist der andere Fehler dann schon weg. :idea:

cu
Narses


Nini - Di 24.03.15 00:56

ja es funktioniert *_* das war wohl noch mein fehler :)
hab jetzt beim programm start ein 5x5-Raster


Narses - Di 24.03.15 00:58

Moin!

Dann zeig nochmal kurz den Code (FormCreate reicht). :les:

Und, was "fehlt" jetzt noch (funktional)? :D

cu
Narses


Nini - Di 24.03.15 01:02


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 8+x*25// 8 Pixel vom linken Rand
    Shape.Top := 8+y*25// 8 Pixel vom oberen Rand
    Shape.Width := 25// 25 Pixel breit
    Shape.Height := 25// 25 Pixel hoch
  end;
end;


irgendwas, dass ich die felder wieder färben kann fehlt noch und dass ich N irgendwie ändern kann im programm


Narses - Di 24.03.15 01:10

Moin!

Ja, der Code sieht jetzt gut aus. :zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
irgendwas, dass ich die felder wieder färben kann fehlt noch
Genau! :D Da war doch noch so eine auskommentierte Zeile in der Demo... :lupe: wozu mag die wohl gut gewesen sein... :gruebel:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und dass ich N irgendwie ändern kann im programm
Tja, grundsätzlich geht sowas zwar, aber nicht mit diesem Ansatz. :nixweiss: Dazu müsste man das Programm etwas anders aufziehen. In dieser Version musst du N im Quelltext ändern und dann neu kompilieren. :(

Auf der anderen Seite: das ist natürlich so gesehen eine (die nächste?) Herausforderung? :zwinker: Wenn du möchtest, können wir uns dieses Problems später nochmal annehmen. ;)

Jetzt kriegen wir das aber erstmal überhaupt wieder ans Laufen. :P

cu
Narses


Nini - Di 24.03.15 01:27

Shape.OnMouseDown := Shape1MouseDown; weist ja die Methode zu, also für das shape dann das was in prozedur TForm1.Shape1MouseDown steht oder?

kann ich das dann einfach unten noch ranschreiben?


Narses - Di 24.03.15 16:39

Moin!

Jap, genau so. :zustimm: Klappt? ;)

cu
Narses


Nini - Di 24.03.15 17:05

ne, ich bekomm da ne fehlermeldung:
wrong number of parametersspecified for call to "Shape1MouseDown"


Narses - Di 24.03.15 17:20

Moin!

OK, laut dem Beitrag hier [http://www.lazarusforum.de/viewtopic.php?f=55&t=3558] muss man bei Lazarus noch ein "@" vor den Methodennamen setzen (sehr merkwürdig :?), also:

Delphi-Quelltext
1:
Shape.OnMouseDown := @Shape1MouseDown;                    

Geht das?

cu
Narses


Nini - Di 24.03.15 17:39

ja, so läuft das programm wieder :)


Narses - Di 24.03.15 17:46

Moin!

OK, dann setz N doch mal testweise auf 10 und starte das Programm. Was fällt auf? ;)

cu
Narses


Nini - Di 24.03.15 17:50

mit N=10 ist das Raster 10x10 groß


Narses - Di 24.03.15 18:10

Moin!

Ja, klar. :lol: Aber das Fenster dürfte doch in der Größe nicht passen und kommt man noch an den Automatik-Button dran? ;)

cu
Narses


Nini - Di 24.03.15 18:22

ne, das fenster musste ich größer machen und das dinf zum simulation starten musste ich auch verschieben :P


Narses - Di 24.03.15 18:27

Moin!

OK, dann schlage ich vor:cu
Narses


Nini - Di 24.03.15 20:18

jaaa, so klappts :) jetzt passt das fenster


Narses - Di 24.03.15 21:09

Moin!

Dann zeig doch bitte nochmal den aktuellen Stand der FormCreate-Methode. :les: ;)

Was soll´s denn als nächstes sein? :D Möchtest du die Regeln für Geburt/Tod anpassbar machen? Oder willst du lieber erst die Feldgröße vom Benutzer wählen lassen? :nixweiss:

Bedenke: was auch immer du wählst, du musst dazu auch irgend eine Idee haben, wie man das denn umsetzen könnte... 8) (klar, das muss kein fertiger Code sein, eine umgangssprachliche Beschreibung, wie vorzugehen ist oder welcher besondere "Trick"/Gedanke weiterhilft, um an´s Ziel zu kommen, reicht auch schon) :idea:

cu
Narses


Nini - Di 24.03.15 21:21

also die aktuelle formcreate-methode

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 8+x*25// 8 Pixel vom linken Rand
    Shape.Top := 48+y*25// 8 Pixel vom oberen Rand
    Shape.Width := 25// 25 Pixel breit
    Shape.Height := 25// 25 Pixel hoch
    Shape.OnMouseDown := @Shape1MouseDown; // haben wir hier nicht, aber so weist man eine Methode zu
    ClientHeight := N*25+100;
    ClientWidth := N*25+80;
   end;
end;




ich würde die Regeländerun bevorzugen.
Mein ganz grober plan: Ich muss eingeben können,was passiert bei wie viel NAchbarn, dafür würde ich checkboxen nehmen, also 8 für geburt und 8 für tod, wenn nichts gewählt wird für ne bestimmte nachbar-anzahl, dann passiert nichts mit der Zelle.
Und dann muss das Ergebnis, ob die Zelle geboren wird in die Rechnen-prozedur einlesen können, damit die das dann anwenden kann


Narses - Mi 25.03.15 00:07

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also die aktuelle formcreate-methode
Warum setzt du denn N^2 mal die Formulargröße? :shock: Einmal reicht doch... :angel: Aber sonst OK. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich würde die Regeländerun bevorzugen.
OK, dann machen wir die Regeln anpassbar. :zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
dafür würde ich checkboxen nehmen, also 8 für geburt und 8 für tod, wenn nichts gewählt wird für ne bestimmte nachbar-anzahl, dann passiert nichts mit der Zelle.
Dann füg doch bitte mal der Anwendung ein weiteres Formular hinzu. Das gestaltest du so, wie du dir die Oberfläche für die Regeldefinition vorstellst und dann stellst du einen Screenshot hier rein. :lupe:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Und dann muss das Ergebnis, ob die Zelle geboren wird in die Rechnen-prozedur einlesen können, damit die das dann anwenden kann
Klar, das schauen wir uns dann an. ;)

cu
Narses


Nini - Mi 25.03.15 12:36

ich würd das so machen:
Regeländerung


Narses - Mi 25.03.15 18:13

Moin!

OK, wie müssten denn die Haken gesetzt werden, um die aktuellen Regeln abzubilden? :lupe:

cu
Narses

PS: Hast du den Fehler mit der Fenstergröße noch behoben? ;)


Nini - Mi 25.03.15 18:52

ne, weiß nicht was ich da ändern muss :P funktioniert ja so

so mit jetzigen regeln wär's das
Regeländerung


Narses - Mi 25.03.15 23:53

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
:P funktioniert ja so
Hmhm. :| Wenn du also bei N=10 insgesamt 100 mal die Fenstergröße setzt, dann ist das OK? :suspect: :schmoll:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ne, weiß nicht was ich da ändern muss
Wozu sind hier die beiden markierten Worte da? :lupe:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    ...
    Shape.OnMouseDown := @Shape1MouseDown; // haben wir hier nicht, aber so weist man eine Methode zu
    ClientHeight := N*25+100;
    ClientWidth := N*25+80;
   end;
end;


user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
so mit jetzigen regeln wär's das
OK, allerdings würde ich bevorzugen in beiden Spalten das Entstehen einer schwarzen Zelle als Ergebnis zu definieren, also müssten wir von "Tod" auf "Überleben" umstellen. Wie machen wir das? :idea:

Dann hast du mal folgenden Code vorgeschlagen (ganz alleine, das war nicht von mir!):

Delphi-Quelltext
1:
if (AnzahlLebenderNachbarn(x, y) in [23]then                    

Was bewirkt der markierte Teil? Nutzt uns das was für unser aktuelles Problem? ;)

cu
Narses


Nini - Sa 28.03.15 00:59

die grenzen die sachen ein die in der schleife passieren, also muss ich das client... aus den schleifen rausnehmen damits nur einmal so groß ist

mit überleben wär's dann wie auf dem bild
Regeländerung2

das macht dass das geschaut wird ob die zelle zwei oder drei lebende zellen hat und man müsste jetzt nur das in der eckigen klammer ändern können, dass da die wahren werte von der überlebenden Zelle reinkommen damit sich die zelle schwarz färbt


Happy_Penguin - Sa 28.03.15 14:22

Ein kleiner Tipp von mir...
Wie wäre es denn, wenn du nun zwei Arrays für das Regelwerk anlegst?
Einen Array, wann eine Zelle neu entsteht und dann einen, wann sie überlebt.


Delphi-Quelltext
1:
2:
3:
var
  ueberleben:   Array[0..8of Boolean;
  neuEntstehen: Array[0..8of Boolean;


Durch die Checkboxen kannst du ja dann prima darauf zugreifen.


Narses - Sa 28.03.15 16:58

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
die grenzen die sachen ein die in der schleife passieren, also muss ich das client... aus den schleifen rausnehmen damits nur einmal so groß ist
:zustimm: Geht doch.

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
mit überleben wär's dann wie auf dem bild
Jawoll, einfach invertieren. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das macht dass das geschaut wird ob die zelle zwei oder drei lebende zellen hat
Jup.

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und man müsste jetzt nur das in der eckigen klammer ändern können, dass da die wahren werte von der überlebenden Zelle reinkommen damit sich die zelle schwarz färbt
Genau, und das werden wir als nächstes tun. :)

Diese Aufzählungen in eckigen Klammern nennt man eine Menge, und statt das als Konstante zu verwenden, wie in der if-Anweisung kann man das auch als Variable verwenden. :idea: Da wir von verschiedenen Stellen im Code darauf zugreifen können wollen, müssen wir die Variable in der Klasse deklarieren:

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:
const
  N = 10// Seitenlänge des Feldes

type
  TNachbarn = 1..8; // es gibt 8 Nachbarn einer Zelle

  TRegel = set of TNachbarn; // Auswahl von Nachbaranzahlen

  TFeld = array[0..N-10..N-1of Boolean; // Aufbau des Feldes festlegen (2-dimensionales array)

  TForm1 = class(TForm)
    ...
  public
    Feld: TFeld; // das ist der interne Speicher für die Zellen (=Shapes in der GUI)
    Ueberleben: TRegel;
    Geburt: TRegel;
    function LebtNachbar(x, y: Integer): Boolean;

...

procedure TForm1.FormCreate(Sender: TObject);
  var
    x, y, snr: Integer;
    Shape: TShape;
begin
  Ueberleben := [23]; // Standard-Regeln definieren
  Geburt := [3];
  ClientWidth := 17 +24 *N;
  ...

Das ist die Vorarbeit, um mit den Regel-Mengen arbeiten zu können. Dein Part ist nun den Code in der Rechnen-Methode so anzupassen, dass mit den neuen Regel-Mengen gearbeitet wird. Vorschlag? :les:

@user profile iconHappy_Penguin: Das kann man sicher auch so machen, ich würde aber den Ansatz mit den Mengen empfehlen. ;)

cu
Narses


Happy_Penguin - Sa 28.03.15 17:09

Okay das geht natürlich auch :-)

Ich möchte nur noch anmerken, dass auch 0 Nachbarn möglich sind und auch das vom Nutzer einstellbar sein sollte...
Also am Besten TNachbarn entsprechend anpassen

Delphi-Quelltext
1:
TNachbarn = 0..8;                    


Narses - Sa 28.03.15 17:21

Moin!

user profile iconHappy_Penguin hat folgendes geschrieben Zum zitierten Posting springen:
Ich möchte nur noch anmerken, dass auch 0 Nachbarn möglich sind und auch das vom Nutzer einstellbar sein sollte...
Und richtig klasse wäre es, wenn Nini das selbst merkt... :zwinker: :roll:

cu
Narses


Nini - Sa 28.03.15 17:34


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
   for y := 0 to N-1 do
    for x := 0 to N-1 do
      if Feld[x, y] then
         for i := 1 to 8 do
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) = ueberleben)
      else
        FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) = geburt);
  Feld := FeldNeu;


Ich hätte das ja gern einfach so gemacht, aber das geht nicht, weil irgendwie die typen inkompatibel sind :(


Narses - Sa 28.03.15 18:06

Moin!

Du hast doch auch in dem von mir zitierten Stück Code nicht "=" genommen, warum sollte das jetzt anders sein? :gruebel: :zwinker:

cu
Narses


Nini - Sa 28.03.15 18:13

ok, dann also so:

Delphi-Quelltext
1:
2:
3:
4:
if Feld[x, y] then
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in ueberleben)
      else
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in geburt);


Narses - Sa 28.03.15 18:34

Moin!

Jup. :) Und, funktioniert´s? ;)

Der nächste Schritt wird natürlich sein, diese Regel-Mengen mit dem Zustand der Checkboxen zu "befüllen". Ich gehe doch mal stark davon aus, dass Lazarus eine Online-Hilfe hat. :lupe: Da schaust du mal bitte rein und liest dir durch, was es zu Mengen und Mengenoperatoren (also z.B. "in") zu wissen gibt. :les: Dann kannst du dich mal an einem Codevorschlag zum Auslesen der Checkboxen versuchen. :idea:

cu
Narses


Martok - Sa 28.03.15 19:49

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Ich gehe doch mal stark davon aus, dass Lazarus eine Online-Hilfe hat.
Schon, aber die ist fast durchgehend API/Klassen-Dokumentation, die Sprache muss man so können.

Du kannst aber die Delphi-Hilfe nehmen: Mengentypen [http://docwiki.embarcadero.com/RADStudio/XE7/de/Strukturierte_Typen#Mengentypen], Mengenoperatoren [http://docwiki.embarcadero.com/RADStudio/XE7/de/Ausdr%C3%BCcke_%28Delphi%29#Mengenoperatoren].


Happy_Penguin - Mo 30.03.15 19:59

user profile iconHappy_Penguin hat folgendes geschrieben Zum zitierten Posting springen:
Okay das geht natürlich auch :-)

Ich möchte nur noch anmerken, dass auch 0 Nachbarn möglich sind und auch das vom Nutzer einstellbar sein sollte...
Also am Besten TNachbarn entsprechend anpassen

Delphi-Quelltext
1:
TNachbarn := 0..8;                    


Moderiert von user profile iconNarses: Beiträge zusammengefasst

Hallo,

also am Besten wäre es vielleicht wirklich, dass mit dem Boolean-Arrays zu lösen, da kommt man nämlich mit dem Schulwissen aus :-;


Nini - Mo 30.03.15 20:40

ich hab mir die beiden artikel komplett durchgelesen und auch eeeewig drüber nachgedacht, aber irgendwie hab ich gar keine ahnung wie ich das anstellen muss :( :cry:


Narses - Mo 30.03.15 20:44

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich hab mir die beiden artikel komplett durchgelesen und auch eeeewig drüber nachgedacht,
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber irgendwie hab ich gar keine ahnung wie ich das anstellen muss :( :cry:
Na, dann wollen wir das mal ändern. ;)

Was wäre denn konzeptionell zu tun (also jetzt mal unabhängig von irgendwelchem Code)? Beschreib´s mit Worten. :idea:

cu
Narses


Nini - Mo 30.03.15 21:04

Also als erstes muss ich die ckeckboxen auslesen ob soe angeklickt sind oder nicht, dann würde ich wenn angekliclt den wert wahr zuweisen und dann muss wenn wahr das iwie in die menge gespeichert werden


Narses - Mo 30.03.15 21:11

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
als erstes muss ich die ckeckboxen auslesen ob soe angeklickt sind oder nicht,
Jup. Bei den Shapes haben wir das doch auch irgendwie gemacht, wie ging das denn da? :lupe: :les:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
dann würde ich wenn angekliclt den wert wahr zuweisen
Hm :? also das würde ich jetzt mal weglassen, da mir nicht ganz klar ist, was das bewirken soll :gruebel: (und wenn ich raten sollte 8) dir auch nicht :lol: oder? :zwinker:)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und dann muss wenn wahr das iwie in die menge gespeichert werden
Genau, dann muss was in die Menge rein. Das schauen wir uns dann an, wenn es soweit ist. Vielleicht noch ein Gedanke: bevor wir anfangen irgendwas in eine Menge zu tun, was ist denn, wenn da schon was drin steht? :suspect: :nixweiss:

cu
Narses


Nini - Mo 30.03.15 21:21

Geht das auslesen nicht mit ck0geburt.checked oder so?

Dann muss ich die menge also vorher erst noch löschen damit die leer ist


Narses - Mo 30.03.15 22:00

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Geht das auslesen nicht mit ck0geburt.checked oder so?
Jup, so geht´s auch. ;) Dann brauchst du zwar für jede Checkbox eine if-Abfrage, aber funktionieren tu´s schon. :nixweiss:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Dann muss ich die menge also vorher erst noch löschen damit die leer ist
Genau! :idea: "Löschen" kann man eine Menge durch Zuweisung der leeren Menge:

Delphi-Quelltext
1:
MengenVariable := []; // [] ist die leere Menge                    

cu
Narses


Nini - Mo 30.03.15 22:10


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
geburt := [];
    ueberleben := [];
    ckgeburt0.Checked;
    ckgeburt1.Checked;
    ckgeburt2.Checked;
    ckgeburt3.Checked;
    ckgeburt4.Checked;
    ckgeburt5.Checked;
    ckgeburt6.Checked;
    ckgeburt7.Checked;
    ckgeburt8.Checked;

dann hab ich das jetzt so weit und dann halt nochmal für die andern checkboxen, aber weiter weiß ich nicht mehr


Narses - Mo 30.03.15 22:17

Moin!

Wo sind denn die if-Abfragen? :lupe: ;)

cu
Narses


Nini - Mo 30.03.15 22:31

ok, die muss ich also noch drumrum bauen, hab ich vergessen


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
 
    if ckgeburt0.Checked then
        else;
    if ckgeburt1.Checked then
       else;
    if ckgeburt2.Checked then
       else;


und so weiter


Narses - Mo 30.03.15 22:40

Moin!

Gut, da du bereits eine Checkbox für 0 Nachbarn vorgesehen hast: hast du dann auch die Deklaration von TNachbarn entsprechend angepasst? :lupe:

Und hier noch die Syntax, um ein Element einer Menge hinzuzufügen:

Delphi-Quelltext
1:
MengenVariable := MengenVariable +[3]; // fügt das Element 3 der Menge hinzu                    

Dann solltest du jetzt den Code vervollständigen können (zumindest den Block, der sich um das Abfragen kümmert; wir müssen uns ja noch was für die Fenster-Verwaltung einfallen lassen).

cu
Narses


Nini - Mo 30.03.15 22:48

ja, das hab ich schon gemacht


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
    if ckgeburt0.Checked then geburt := geburt + [0]
       else;
    if ckgeburt1.Checked then geburt := geburt + [1]
       else;                               
    if ckgeburt2.Checked then geburt := geburt + [2]
       else;
    if ckgeburt3.Checked then geburt := geburt + [3]
       else;


das sollte ja so jetzt glaube ich stimmen


Narses - Mo 30.03.15 22:58

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ja, das hab ich schon gemacht
:zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das sollte ja so jetzt glaube ich stimmen
Was möchtest du denn mit dem "else;" bewirken? :gruebel: Im else-Fall machst du doch nix (";" = leere Anweisung). :nixweiss: Kannst du also weglassen (oder hinter das else einen Befehl schreiben :?).

Gut, kommen wir zur Einbindung in das Projekt. Du brauchst einen neuen Button auf dem Hauptformular (kannst du ja hinter der Automatik-Checkbox anlegen). Den könnte man "btnRegeln" oder so nennen. ;) Doppelklick drauf machen und dann in den Handler schreiben:

Delphi-Quelltext
1:
Form2.ShowModal; // unterstellt, dass das zweite Formular so heißt                    

Wenn du das versuchst zu kompilieren, wird es vermutlich eine Fehlermeldung geben. :shock: Warum? :lupe: Weil du dem Compiler noch nicht gesagt hast, dass du von Form1 aus auf Form2 zugreifen möchtest. :think: Also musst du noch die Verwendung in Form1 anmelden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
...
implementation

uses
  Unit2;

...

Jetzt sollte sich das kompilieren lassen. ;)

cu
Narses


Dundi - Di 31.03.15 04:33

Hallo Narses,
ein Lob an dich ,ich finde es Klasse wie du Nini bei ihrer Hausaufgabe förderst, Hut ab.

Mfg
Dundi


Nini - Di 31.03.15 15:47

user profile iconDundi hat folgendes geschrieben Zum zitierten Posting springen:
Hallo Narses,
ein Lob an dich ,ich finde es Klasse wie du Nini bei ihrer Hausaufgabe förderst, Hut ab.

ja das find ich auch voll nett :) danke sehr c:

ja, ich hab jetzt alles so gemacht und es lässt sich kompilieren das programm und mit dem btnRegeln öffne ich dann auch das zweite fenster wenns programm läuft :)


Narses - Di 31.03.15 16:22

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ja das find ich auch voll nett :) danke sehr c:
:beer:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
mit dem btnRegeln öffne ich dann auch das zweite fenster wenns programm läuft :)
Fein. ;) Dann müssen wir noch einen Button auf dem Regel-Formular anlegen, mit dem man diesen Dialog wieder schließen kann (das solltest du mittlerweile alleine hinkriegen, oder? :zustimm:)

Wenn der Dialog geschlossen wurde, müssen wir jetzt die Regel-Mengen aktualisieren. Also kommt der Code hinter das Form2.ShowModal;. :idea: Mach mal einen Vorschlag, wie´s da weiter geht. :les:

cu
Narses


Nini - Di 31.03.15 20:01

wie das jetzt so richtig weiter geht kann ich mir noch nicht so ganz vorstellen, aber ich muss als erstes jetzt irgendwie die mengen geburt und ueberleben aus der unit2 in die unit1 bekommen glaub ich.

ja, also ich hab das einfach so gemacht:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm2.btnEndeClick(Sender: TObject);
begin
  close;
end;


Narses - Di 31.03.15 20:51

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ja, also ich hab das einfach so gemacht:
Top. :zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich muss als erstes jetzt irgendwie die mengen geburt und ueberleben aus der unit2 in die unit1 bekommen glaub ich.
Die Mengen-Variablen sollten ja eigentlich bereits in der Form1-Klasse deklariert sein, so gesehen sind die schon da, wo sie hingehören. :lupe: Was du jetzt brauchst, ist der Zugriff auf Komponenten in Form2 von einer Methode in Form1. :idea: Und das geht so:

Delphi-Quelltext
1:
if Form2.ckgeburt0.Checked then geburt := geburt + [0];                    

Das muss jetzt ausgeführt werden, nachdem Form2 geschlossen wurde (also hinter das Form2.ShowModal; diese Methode "wartet" quasi darauf, dass das Formular wieder geschlossen wird :idea:).

cu
Narses


Nini - Di 31.03.15 21:36

jaa, da funktioniert das programm wieder komplett :)


Narses - Di 31.03.15 22:39

Moin!

Fein, dann zeig doch mal die komplette btnRegelnClick-Methode. :les: ;)

cu
Narses


Nini - Mi 01.04.15 17:37


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:
procedure TForm1.btnRegelnClick(Sender: TObject);
begin
  form2.ShowModal;
  geburt := [];
  ueberleben := [];  
  if Form2.ckgeburt0.Checked then geburt := geburt + [0];
  if Form2.ckgeburt1.Checked then geburt := geburt + [1];
  if Form2.ckgeburt2.Checked then geburt := geburt + [2];
  if Form2.ckgeburt3.Checked then geburt := geburt + [3];
  if Form2.ckgeburt4.Checked then geburt := geburt + [4];
  if Form2.ckgeburt5.Checked then geburt := geburt + [5];
  if Form2.ckgeburt6.Checked then geburt := geburt + [6];
  if Form2.ckgeburt7.Checked then geburt := geburt + [7];
  if Form2.ckgeburt8.Checked then geburt := geburt + [8];

  if Form2.ckueberleben0.checked then ueberleben := ueberleben + [0];
  if Form2.ckueberleben1.checked then ueberleben := ueberleben + [1];
  if Form2.ckueberleben2.checked then ueberleben := ueberleben + [2];
  if Form2.ckueberleben3.checked then ueberleben := ueberleben + [3];
  if Form2.ckueberleben4.checked then ueberleben := ueberleben + [4];
  if Form2.ckueberleben5.checked then ueberleben := ueberleben + [5];
  if Form2.ckueberleben6.checked then ueberleben := ueberleben + [6];
  if Form2.ckueberleben7.checked then ueberleben := ueberleben + [7];
  if Form2.ckueberleben8.checked then ueberleben := ueberleben + [8];
end;


Narses - Mi 01.04.15 18:47

Moin!

OK. ;) Allerdings :? ziemlich viel gleiche Sachen, oder? :lupe: Ideen, wie man das "einfacher" machen kann? :zwinker: :idea:

cu
Narses


Nini - Mi 01.04.15 20:03

das geht bestimmt so ähnlich wie bei den shapes
vielleicht so ungefähr? :

Delphi-Quelltext
1:
2:
3:
4:
           for i:= 0 to 8 do begin
            ckgeburt:= Tcheckbox(FindComponent('ckgeburt' +IntToStr(i)));
            if form2.ckgeburt.checked then  geburt := geburt + [i];
           end;


Narses - Mi 01.04.15 21:45

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das geht bestimmt so ähnlich wie bei den shapes
8)
user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
vielleicht so ungefähr? :
:zustimm:

Allerdings: die Checkboxen sind ja auf Form2, also musst du das FindComponent von Form2 aufrufen:

Delphi-Quelltext
1:
2:
3:
4:
5:
for i := 0 to 8 do begin
  ckgeburt := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
  if ckgeburt.checked then
    geburt := geburt + [i];
end;

Da kannst du sogar noch gleich die andere Spalte Checkboxen mit rein nehmen. :idea:

cu
Narses


Nini - Mi 01.04.15 22:02


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.btnRegelnClick(Sender: TObject);
var ckgeburt, ckueberleben : TCheckBox;
     i : integer;
begin
  form2.ShowModal;
  geburt := [];
  ueberleben := [];

  for i := 0 to 8 do begin
    ckgeburt := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if ckgeburt.checked then
      geburt := geburt + [i];
  end;

  for i := 0 to 8 do begin
    ckueberleben := TCheckBox(Form2.FindComponent('ckueberleben' +IntToStr(i)));
    if ckueberleben.checked then
      ueberleben := ueberleben + [i];
  end
end;


Narses - Mi 01.04.15 22:19

Moin!

:les: :idea: :nixweiss:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure TForm1.btnRegelnClick(Sender: TObject);
  var
    ckgeburt, ckueberleben: TCheckBox;
    i: Integer;
begin
  Form2.ShowModal;
  geburt := [];
  ueberleben := [];
  for i := 0 to 8 do begin
    ckgeburt := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if ckgeburt.checked then
      geburt := geburt + [i];
    ckueberleben := TCheckBox(Form2.FindComponent('ckueberleben' +IntToStr(i)));
    if ckueberleben.checked then
      ueberleben := ueberleben + [i];
  end;
end;


Ich möchte dir aber noch einen anderen Ansatz zeigen, wie man das Problem auch lösen könnte: mit einer lokalen Funktion: :think:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegeln;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    ... // hier musst du jetzt ran ;)
  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
end;

Probier mal. :D

cu
Narses


Nini - Mo 13.04.15 16:01

so jetzt sind die ferien wieder vorbei und internet wieder da :P ich hab auch die letzten zwei wochen drüber nachgedacht wie das gehen könnte, aber ehrlich gesagt finde ich die funktionen noch etwas unverständlich :(


Narses - Mo 13.04.15 16:38

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
so jetzt sind die ferien wieder vorbei und internet wieder da :P
Ah, du bist ja doch noch dabei! :D Ich hatte schon befürchtet, die "Hausaufgabe" ist erledigt, die Note gerettet, und auf wiedersehen Programmiererei... :P Schön, dass du (immer) noch Interesse hast. :zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich hab auch die letzten zwei wochen drüber nachgedacht wie das gehen könnte, aber ehrlich gesagt finde ich die funktionen noch etwas unverständlich :(
OK, dann nehmen wir doch einfach mal das entsprechende (Teil-)Stück Code von oben (deine Version):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  geburt := [];
  for i := 0 to 8 do begin
    ckgeburt := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if ckgeburt.checked then
      geburt := geburt + [i];
  end;

Im Prinzip muss díeser Teil jetzt - etwas allgemeiner formuliert, die Ansätze siehst du ja schon in meinem Code - da irgendwie "rein". Probier einfach mal, ist nicht schlimm, wenn´s nicht sofort passt. ;)

cu
Narses


Nini - Mo 13.04.15 17:30

ist das dann vielleicht in etwa so?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegeln;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
    checkbox := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if checkbox.checked then
      result := result + [i];
      end;...
  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
end;


Narses - Mo 13.04.15 20:57

Moin!

Ja, das ist schon ganz gut. Allerdings beachtest du noch nicht den übergebenen Namen in der Funktion. :idea: Und dann noch die 3 Punkte entfernen, und schon sollte sich das kompilieren lassen. ;)

cu
Narses


Nini - Mo 13.04.15 21:11

ich habe keine ahnung was ich ändern muss :(


Narses - Mo 13.04.15 22:05

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich habe keine ahnung was ich ändern muss :(
OK, dann gaaanz langsam. ;)

Das ist der Aufruf der Funktion:

Delphi-Quelltext
1:
ueberleben := GetRuleSet('ckueberleben');                    

In der Funktion ist dann die Textkonstante als Parameter vorhanden:

Delphi-Quelltext
1:
function GetRuleSet(const ANameString): TRegeln;                    

Mach mal folgenden Test:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegeln;
  begin
    ShowMessage(AName); // Test-Ausgabe, was passiert?
  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
end;

Probier das mal aus. :lupe: :think:

cu
Narses


Nini - Di 14.04.15 19:47

so also wenn ich btnRegeln öffne und dann schließe kriege ich ein Nachrichtenfeld in dem ckGeburt steht und wenn ich das geschlossen habe darunter ein Feld auf dem ckueberleben steht.


Narses - Di 14.04.15 23:16

Moin!

OK, dann ändere das mal so ab:

Delphi-Quelltext
1:
2:
ueberleben := GetRuleSet('hallo');
geburt := GetRuleSet('holla');

Und, was passiert? ;)

cu
Narses


Nini - Mi 15.04.15 17:58

da kommt dann als text holla bzw. hallo


Narses - Mi 15.04.15 22:40

Moin!

Und, kapiert was da mit dem Parameter AName passiert? :zwinker:

Dann jetzt nochmal der Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegeln;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
      checkbox := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
      if checkbox.checked then
        result := result + [i];
    end;
  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
end;

Was passt hier also noch nicht?

cu
Narses


Nini - Do 16.04.15 18:24

muss ich vielleicht das ueberleben/geburt noch dem aName zuweisen?


Narses - Do 16.04.15 20:59

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
muss ich vielleicht das ueberleben/geburt noch dem aName zuweisen?
Das passiert hier bereits: (beim Aufruf)

Delphi-Quelltext
1:
2:
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');

Aber du beachtest es in der Funktion nicht. :idea: :zwinker:

cu
Narses


Nini - Fr 17.04.15 22:23

und wie bekomm ich den denn da rein? O.o


Narses - Sa 18.04.15 01:05

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und wie bekomm ich den denn da rein? O.o
Ganz einfach, über AName drauf zugreifen, wie hier auch im Test:

Delphi-Quelltext
1:
2:
3:
4:
  function GetRuleSet(const AName: String): TRegeln;
  begin
    ShowMessage(AName); // Test-Ausgabe, was passiert?
  end;

cu
Narses


Nini - Sa 18.04.15 14:27

vlt so in der art?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegel;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result(AName) := [];
    for i := 0 to 8 do begin
    checkbox:= TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if checkbox.checked then
      result(AName)  := result(AName)  + [i];
      end;
  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ueberleben');
  geburt := GetRuleSet('geburt');
end;


Narses - Sa 18.04.15 16:04

Moin!

OK, zwei Sachen:

Delphi-Quelltext
1:
checkbox:= TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));                    
Was bewirkt diese Zeile?


Delphi-Quelltext
1:
2:
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
Vor deinem letzten Vorschlag stand das da so. :idea:

cu
Narses


Nini - Sa 18.04.15 16:22

oh, das hab ich jetzt wieder so geändert :)

die Zeile macht dass die checkbox die mit dem namen ckgeburt i gefunden wurde zur klasse tCheckbox gehört, glaube ich


Narses - Sa 18.04.15 21:36

Moin!

OK, ich denke, du hast noch nicht verstanden, wohin die "Reise" gehen soll, also kannst du den Weg auch nicht finden... :? :nixweiss: Dann müssen wir das erstmal ändern. ;)

Diese Funktion:

Delphi-Quelltext
1:
function GetRuleSet(const AName: String): TRegel;                    
soll eine Gruppe von Checkboxen bearbeiten und das Ergebnis dieser "Bearbeitung" in einer Menge (vom Typ TRegel) abliefern. :idea:

Deshalb rufen wir die Funktion zwei mal auf:

Delphi-Quelltext
1:
2:
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');

Sinn: beim Aufruf geben wir der Funktion mit (der Parameter in Klammern), welche Checkbox-Gruppe bearbeitet werden soll. Und die Zuweisung des Funktionsergebnisses an die entsprechende Variable (ueberleben := bzw. geburt :=) stellt den Zusammenhang von Checkbox-Namen zu Funktion im Programm her. :think:

Du musst also in der Funktion den Namen der Checkbox-Gruppe verwenden (wir als AName bereitgestellt), statt eines konstanten Namens. :les: Jetzt klarer?

cu
Narses


Nini - Sa 18.04.15 21:43

ja also ich glaube, ich hab es jetzt besser verstanden

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegel;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
    checkbox:= TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if checkbox.checked then
      result := result + [i];
      end;
  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('aName');
  geburt := GetRuleSet('aName');
end;


Narses - Sa 18.04.15 22:32

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ja also ich glaube, ich hab es jetzt besser verstanden
Öhm, noch nicht ganz. :P Es ist genau anders rum! :think:

Das hier war so korrekt:

Delphi-Quelltext
1:
2:
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
Das muss natürlich genau so bleiben, da hier die Verbindung zwischen den (Checkbox-)Namen und den (Regel-)Variablen im Programm hergestellt wird. :idea: (Diese Info kann der Comupter ja alleine nicht erkennen, für den ist ein Name wie "ckgeburt" völlig bedeutungslos :nixweiss:)

Machen wir es mal der Ausführungsreihenfolge nach, nicht der (eigentlich korrekten) Deklarationsreihenfolge nach:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
// Funktionsaufruf
geburt := GetRuleSet('ckueberleben'); // könnte man sich auch so vorstellen: geburt := GetRuleSet(AName := 'ckueberleben');

...

// Funktionsausführung
  function GetRuleSet(const AName: String): TRegel; // hier ist jetzt AName gleichbedeutend zu 'ckueberleben'
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
      checkbox:= TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i))); // genau hier ignorierst du aber, was du eigentlich bearbeiten solltest ;)
      if checkbox.checked then
        result := result + [i];
    end;
  end;

Jetzt klarer? :zwinker:

cu
Narses


Nini - So 19.04.15 18:31

das ganz schön kompliziert o.O

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
 function GetRuleSet(const AName: String): TRegel;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
    checkbox:= TCheckBox(Form2.FindComponent(aName +IntToStr(i)));
    if checkbox.checked then
      result := result + [i];

    end;

  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ueberleben');
  geburt := GetRuleSet('geburt');
end;

so dann in etwa vielleicht?


Narses - So 19.04.15 18:53

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das ganz schön kompliziert o.O
8)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
so dann in etwa vielleicht?
Jup, das ist es! :zustimm: Allerdings wird das so trotzdem nicht laufen, es sei denn, du hast die Checkboxen umbenannt... :zwinker: Oder? :P

cu
Narses


Nini - So 19.04.15 18:58

achso :autsch: :D danke sehr die heißen ja immernock ckgeburt und ckueberleben :P aber jetzt läuft mein programm wieder :)


Narses - So 19.04.15 19:01

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber jetzt läuft mein programm wieder :)
Top! :zustimm:

Dann hast du jetzt auch schon wieder etwas mehr verstanden, was eine Funktion tut. :les: :think:

Und, schon überlegt, wo es weiter geht? ;)

cu
Narses


Nini - So 19.04.15 19:05

ja ich glaub auch, dass ich das jetzt ein bisschen besser verstehe :)

ich würd gern noch N ändern können auf der spieloberfläche, also dass das keine festgelegte konstante mehr ist ...


Narses - So 19.04.15 19:08

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich würd gern noch N ändern können auf der spieloberfläche, also dass das keine festgelegte konstante mehr ist ...
OK. 8) Und schon Ideen, wie das gehen soll? :nixweiss:

cu
Narses


Nini - So 19.04.15 19:50

also ich brauch irgendwas zum eingeben für N, nen editfeld oder sowas wie nen schieberegler oder sowas und dann muss ich das als wert für N einlesen


Narses - So 19.04.15 20:11

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
nen schieberegler oder sowas und dann muss ich das als wert für N einlesen
Jo, klar, irgendwo muss der Benutzer ja kund tun, was er will. ;) Ein Schieberegler finde ich persönlich optimal, da kann man die Eingaben besser begrenzen. :idea:

Aber ich meinte eher: wie soll das "unter der Haube" ablaufen? Wenn wir das Programm gestartet haben, dann sind da ja z.B. schon Shapes erzeugt worden. Was machen wir mit denen? :gruebel:

cu
Narses


Nini - So 19.04.15 20:20

gute frage ... vielleicht einfach wieder löschen? ich weiß es nicht :/


Narses - So 19.04.15 22:01

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
vielleicht einfach wieder löschen?
Simpel aber einfach, ja, das kann man machen. ;)

Allerdings... :? da werden uns jetzt gleich ein paar Probleme über den Weg laufen... :hair:

Zunächst mal haben wir das "Eigentümer-Problem". Hier mal ein Stück aus dem Code zum Erzeugen der Shapes:

Delphi-Quelltext
1:
  Shape := TShape.Create(Self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben                    
Du siehst es schon am Kommentar: wir übergeben das neue Shape dem Formular (also nicht nur zur Anzeige, sondern als Eigentümer des Speicherplatzes). Folglich dürfen wir das nicht einfach wieder selbst freigeben, weil uns die Komponenten gar nicht mehr "gehören" (wird mit Exceptions bestraft)! :shock:

Wir müssen also statt "Self" ein "nil" übergeben, dann "gehört" die Komponente uns. Allerdings müssen wir dann auch irgendwo eine Referenz darauf "aufheben", weil - ganz simpel, grade geplant - wir sie auch später nicht mehr freigeben können, wenn wir sie nicht "wiederfinden". :lupe:

Vorschläge, wie man das in den Griff kriegt? :les:

cu
Narses


Nini - Di 21.04.15 17:33

ne dazu hab ich echt gar keine idee o.O


Narses - Di 21.04.15 17:58

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ne dazu hab ich echt gar keine idee o.O
Hm, das ist aber potenziell ganz schlecht, weil 8) wer soll das dann machen... ? :lupe: :P

So schwer ist das gar nicht, nur etwas viel. :? Du kennst doch arrays, haben wir doch schon benutzt. Hilft uns sowas vielleicht weiter? :les:

cu
Narses


Nini - Di 21.04.15 18:19

vielleicht kann man die shapes als feld übergeben? also wieder zweidimensional oder so? :/


Narses - Di 21.04.15 18:38

Moin!

Ja, das ist eine Möglichkeit. Einfach noch ein Feld (2-dimensionales Array) für die Shapes anlegen, so wie bei den Booleans für die Berechnung. :idea: Dann mach mal einen Vorschlag, wie das aussehen könnte (ist egal wenn das falsch ist, Rom wurde auch nicht an einem Tag erbaut :P). :les:

cu
Narses


Nini - Mi 22.04.15 17:14

ich bin mir noch ganz unsicher, wie ich was da machen muss ...
als erstes glaub ich muss ich das feld deklarieren, bestimmt am besten unter public, dass es global ist aber welcher klasse soll ich das neue feld zuweisen?
geht das so?

Delphi-Quelltext
1:
2:
3:
4:
5:
type
TFeldShape = array[0..N-10..N-1of TShape; 
[...]
 public
    FeldShape : TFeldShape;


Narses - Mi 22.04.15 21:10

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich bin mir noch ganz unsicher, wie ich was da machen muss ...
Das wird schon. :zustimm:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
als erstes glaub ich muss ich das feld deklarieren,
Jup.

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
bestimmt am besten unter public, dass es global ist
Ist OK.

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber welcher klasse soll ich das neue feld zuweisen?
Hä? :gruebel: Meinst du den Elementtyp, da ist doch TShape genau richtig. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
geht das so?

Delphi-Quelltext
1:
2:
3:
4:
5:
type
TFeldShape = array[0..N-10..N-1of TShape; 
[...]
 public
    FeldShape : TFeldShape;
Grundsätzlich nicht schlecht, aber N soll doch variabel werden. :zwinker: Wie könnte man denn dieses Problem lösen? :les:

cu
Narses


Nini - Mi 22.04.15 21:26

dann mein ich bestimmt elementtyp, ich komm mit den ganzen begriffen nicht so ganz klar :P



Delphi-Quelltext
1:
2:
3:
4:
5:
type
    TFeldShape = array[0..300..30of TShape; 
[...]
 public
    FeldShape : TFeldShape;


ich kann ja so einfach einen höchstwert für die Feldgröße festlegen


Narses - Mi 22.04.15 21:58

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
dann mein ich bestimmt elementtyp, ich komm mit den ganzen begriffen nicht so ganz klar :P
Alles OK. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
ich kann ja so einfach einen höchstwert für die Feldgröße festlegen
Perfekt! :zustimm: Genau so, einfach einen Maximalwert festlegen. Aaaaber... dann bitte auch als Konstante wie N deklarieren (z.B. als "Nmax"). :idea: Wie würde das dann aussehen? :les:

cu
Narses


Nini - Mi 22.04.15 22:47


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
const
  Nmax = 35
[...]
type
    TFeldShape = array[0..NMax-10..NMAX-1of TShape; 
[...]
 public
    FeldShape : TFeldShape;

wäre das dann so?


Narses - Mi 22.04.15 23:20

Moin!

Top! :zustimm:

Dann müssen wir jetzt als nächstes die Shape-Erzeugung angehen: die müssen jetzt mit "nil" als Parameter erzeugt werden und dann als Referenz im neuen Feld abgelegt werden. :les:

cu
Narses


Nini - Do 23.04.15 18:26


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Nil); 
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown; // so weist man eine Methode zu
    FeldShape[x,y] := Shape;
   end;
  ClientHeight := N*25+100;
  ClientWidth := N*25+20;
end;


Ist das dann irgendwie so in der Art?


Narses - Do 23.04.15 18:36

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Ist das dann irgendwie so in der Art?
Sollte passen. ;)

Dann brauchen wir noch einen Schieberegler oben im Formular, welcher zwischen 3 und Nmax einstellbare Werte erlaubt (weniger als 3 macht keinen Sinn und mehr als Nmax erlauben wir nicht). :les:

cu
Narses


Nini - Do 23.04.15 18:54

hab ich eingebaut :)


Narses - Fr 24.04.15 12:34

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
hab ich eingebaut :)
Fein. :) Hast du das denn auch so gemacht, dass man nur die Konstante Nmax ändern muss, wenn man diesen Wert verändern möchte? :zwinker:

Als nächstes müssen wir uns darum kümmern, dass die erstellen Shapes, die ja nun uns gehören, auch beim Programmende wieder freigegeben werden. :idea: Sonst haben wir ein Speicher-Leck (wir fordern Speicher für die Shapes an, aber geben ihn nicht wieder frei :shock:)! Dazu eine Idee? :les:

cu
Narses


Nini - Fr 24.04.15 19:36

Ne der wollte NMax als maximumwert nicht akzeptieren :/

Nee da hab ich leider keine idee :(


Narses - Fr 24.04.15 20:28

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Ne der wollte NMax als maximumwert nicht akzeptieren :/
Ja, das hab ich mir schon gedacht. :D Lösung: In der FormCreate-Methode musst du den Maximalwert per Code setzen. :idea:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Nee da hab ich leider keine idee :(
Was sich auf das Freigeben bezieht, nehme ich an. Ansatz: Du läufst mit einer Schleife über alle Felder in FeldShape und wenn da nicht Nil drin steht, dann gibst du das Element mit .Free; frei und setzt dann das Element auf Nil. Das Ganze könnte z.B. im FormDestroy passieren... :angel:

cu
Narses


Nini - Fr 24.04.15 21:57

was ist denn formdestroy? o.O


Narses - Fr 24.04.15 22:01

Moin!

Das ist die Methode, die aufgerufen wird, wenn das Formular gelöscht werden soll. :idea: Zumindest bei Delphi kommt man da so dran: das Formular markieren, dann im Objekt-Inspektor auf die Ereignisse-Seite wechseln, in der Liste dann einen Doppelklick auf OnDestroy machen, dann wird der Handler erzeugt. :lupe:

cu
Narses


Nini - Fr 24.04.15 23:07

danke, hab es jetzt gefunden ;)

aber ich glaube ich hab das was ich machen soll nicht ganz verstanden, ich wür es so machen aber dass sieht falsch aus

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.FormDestroy(Sender: TObject);
var y,x : integer;

begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    if not FeldShape(nilthen FeldShape.free;
    FeldShape.free := FeldShape.nil;
   end;
end;


Narses - Fr 24.04.15 23:39

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber ich glaube ich hab das was ich machen soll nicht ganz verstanden
Ja, das könnte sein. ;) Ist aber nicht schlimm, das kriegen wir hin. :zustimm:

Dann fangen wir mal an:Damit solltest du erstmal weiter kommen. :les:

cu
Narses


Nini - Sa 25.04.15 00:07


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.FormDestroy(Sender: TObject);
var y,x : integer;

begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    if not (FeldShape[x,y]=nilthen
      FeldShape.free;
    FeldShape[x,y] := nil;
   end;
end;


ist das dann so?


Boldar - Sa 25.04.15 00:12

Das sieht doch erstmal ganz gut aus.
Hast du denn das hier schon gemacht:
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Ja, das hab ich mir schon gedacht. :D Lösung: In der FormCreate-Methode musst du den Maximalwert per Code setzen. :idea:

??


Nini - Sa 25.04.15 00:18


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
    Schieberegler : TScrollBar;
begin
[...]
  NMax := 24;
  Schieberegler.Max := NMax;
end;


ich hab mir das so gedacht aber si ganz stimmt das glaub ich noch nicht


Narses - Sa 25.04.15 00:33

Moin!

Zeig mal den ganzen Code, wir müssen mal wieder einen Basisabgleich machen. ;)

cu
Narses


Nini - Sa 25.04.15 09:00


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:
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:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls;

const
  Nmax = 35;

type
    TNachbarn = 0..8// es gibt 8 Nachbarn einer Zelle

    TRegel = set of TNachbarn; // Auswahl von Nachbaranzahlen

    TFeld = array[0..N-10..N-1of Boolean; // Aufbau des Feldes festlegen (2-dimensionales array)

    TFeldShape = array[0..Nmax-10..NMax-1of TShape;
  { TForm1 }

  TForm1 = class(TForm)
    btnRegeln: TButton;
    btnLeeren: TButton;
    ckAutomatik: TCheckBox;
    Ende: TButton;
    ScrollBar1: TScrollBar;

    Timer: TTimer;
    procedure btnLeerenClick(Sender: TObject);
    procedure btnLesenClick(Sender: TObject);
    procedure btnRechnenClick(Sender: TObject);
    procedure btnRegelnClick(Sender: TObject);
    procedure btnSchreibenClick(Sender: TObject);
    procedure ckAutomatikChange(Sender: TObject);
    procedure EndeClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure TimerTimer(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private

  public
    FeldShape: TFeldShape;
    Feld: TFeld;
    Ueberleben: TRegel;
    Geburt: TRegel;
    function LebtNachbar(x, y: Integer): Boolean;
    function AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  end;

var
  Form1: TForm1;

implementation

uses Unit2;
{$R *.lfm}

{ TForm1 }

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var  ThisShape: TShape;
begin
  ThisShape := (Sender as TShape);
  if (ThisShape.Brush.Color = clWhite) then
     ThisShape.Brush.Color := clBlack
  else
     ThisShape.Brush.Color := clWhite;
end;

procedure TForm1.ckAutomatikChange(Sender: TObject);
begin
    if ckAutomatik.Checked then begin // Haken reingeklickt
    btnLesenClick(Self); // Feld einlesen
    Timer.Enabled := True; // Timer einschalten
  end
  else // Haken rausgeklickt
    Timer.Enabled := False; // Timer ausschalten
end;

procedure TForm1.btnLesenClick(Sender: TObject);
var x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1;
            Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False;
        end;
end;

procedure TForm1.btnLeerenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do
           if  (feld[x,y]) then
             feld[x,y] := false;

   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1;
           Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;
       end;
end;

procedure TForm1.TimerTimer(Sender: TObject);
begin
  btnrechnenClick(Self);
end;

 procedure TForm1.btnRechnenClick(Sender: TObject);
  var
    x, y: Integer;
    FeldNeu: TFeld;
begin
  for y := 0 to N-1 do
    for x := 0 to N-1 do
      if Feld[x, y] then
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in ueberleben)
      else
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in  geburt);
  Feld := FeldNeu;
  btnSchreibenClick(Self);
end;

procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegel;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
    checkbox:= TCheckBox(Form2.FindComponent(aName +IntToStr(i)));
    if checkbox.checked then
      result := result + [i];

    end;

  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
end;

 function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
   var
     dx, dy: Integer;
 begin
   Result := 0;
   for dy := -1 to 1 do
     for dx := -1 to 1 do begin
      if  ((dx<>0or (dy<>0)) then
          if LebtNachbar(x +dx, y +dy) then
         Inc(Result);
     end;
 end;

function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  Result := Feld[(x+N) mod N, (y+N) mod N];
end;

procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1;
           Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;
       end;

end;

procedure TForm1.EndeClick(Sender: TObject);
begin
  close;
end;

procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
    Schieberegler : TScrollBar;
begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Nil); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown; // so weist man eine Methode zu
    FeldShape[x,y] := Shape;
   end;
  ClientHeight := N*25+100;
  ClientWidth := N*25+20;
  NMax := 24;
  Schieberegler.Max := NMax;
end;

procedure TForm1.FormDestroy(Sender: TObject);
var y,x : integer;

begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    if not (FeldShape[x,y]=nilthen
      FeldShape.free;
    FeldShape[x,y] := nil;
   end;
end;


end.
das wäre dann so und halt die unit2 noch


Narses - So 26.04.15 12:51

Moin!

Ah, danke. Da ist doch noch was zu tun:cu
Narses


Nini - So 26.04.15 14:03

aber das spielfeld leeren funktioniert ja trotzdem :p

hab das jetzt geändert und n in nmax umgeschrieben :)


Narses - So 26.04.15 17:57

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber das spielfeld leeren funktioniert ja trotzdem :p
Ich hab ja auch nicht behauptet, dass es nicht funktionieren würde - aber das ändert immer noch nix daran, dass der Code dafür überflüssig kompliziert ist. 8) Egal, das schauen wir uns später noch an.

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
hab das jetzt geändert und n in nmax umgeschrieben :)
Sehr schön. Allerdings sollte das hier

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
    Schieberegler : TScrollBar;
begin
  for y := 0 to N-1 do
  //...
  ClientWidth := N*25+20;
  NMax := 24;
  Schieberegler.Max := NMax;
end;
eigentlich mindestens eine Warnung im Compiler produzieren, dass du da den Wert einer Konstanten verändert möchtest. :shock: Das geht natürlich nicht, da du ja hier (oben):

Delphi-Quelltext
1:
2:
const
  Nmax = 35;
den Wert für Nmax als Konstante (also unveränderlich) festlegst.

Dann würde ich noch vorschlagen, statt einer ScrollBox eine TrackBar zu verwenden (ist bei Delphi im Register Win32). Probier mal lieber diese Komponente aus. ;)

Und dann noch das hier:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure TForm1.FormDestroy(Sender: TObject);
  var
    y, x: Integer;
begin
  for y := 0 to Nmax-1 do
    for x := 0 to Nmax-1 do begin
      if Assigned(FeldShape[x,y]) then begin // mit Assigned() kann man prüfen, ob einer (Zeiger-)Variablen ein Wert zugewiesen ist
        FeldShape.Free; // Komponente freigeben
        FeldShape[x,y] := nil// Referenz entfernen
      end;
   end;
end;

Bau das mal ein/um und dann zeig nochmal den kompletten Code. :les:

cu
Narses


Nini - So 26.04.15 18:57

so das wär dann glaub ich das:

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:
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:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
 unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, ComCtrls;

const
  Nmax = 35;

type
    TNachbarn = 0..8// es gibt 8 Nachbarn einer Zelle

    TRegel = set of TNachbarn; // Auswahl von Nachbaranzahlen

    TFeld = array[0..Nmax-10..Nmax-1of Boolean; // Aufbau des Feldes festlegen (2-dimensionales array)

    TFeldShape = array[0..Nmax-10..NMax-1of TShape;
  { TForm1 }

  TForm1 = class(TForm)
    btnRegeln: TButton;
    btnLeeren: TButton;
    ckAutomatik: TCheckBox;
    Ende: TButton;

    Timer: TTimer;
    TrackBar1: TTrackBar;
    procedure btnLeerenClick(Sender: TObject);
    procedure btnLesenClick(Sender: TObject);
    procedure btnRechnenClick(Sender: TObject);
    procedure btnRegelnClick(Sender: TObject);
    procedure btnSchreibenClick(Sender: TObject);
    procedure ckAutomatikChange(Sender: TObject);
    procedure EndeClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure TimerTimer(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private

  public
    FeldShape: TFeldShape;
    Feld: TFeld;
    Ueberleben: TRegel;
    Geburt: TRegel;
    N: Integer;
    function LebtNachbar(x, y: Integer): Boolean;
    function AnzahlLebenderNachbarn(const x, y: Integer): Integer;
  end;

var
  Form1: TForm1;

implementation

uses Unit2;
{$R *.lfm}

{ TForm1 }

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var  ThisShape: TShape;
begin
  ThisShape := (Sender as TShape);
  if (ThisShape.Brush.Color = clWhite) then
     ThisShape.Brush.Color := clBlack
  else
     ThisShape.Brush.Color := clWhite;
end;

procedure TForm1.ckAutomatikChange(Sender: TObject);
begin
    if ckAutomatik.Checked then begin // Haken reingeklickt
    btnLesenClick(Self); // Feld einlesen
    Timer.Enabled := True; // Timer einschalten
  end
  else // Haken rausgeklickt
    Timer.Enabled := False; // Timer ausschalten
end;

procedure TForm1.btnLesenClick(Sender: TObject);
var x, y, snr: Integer;
    Shape: TShape;
begin
    for y := 0 to N-1 do // von unten nach oben
        for x := 0 to N-1 do begin // von rechts nach links
            snr := x +y *N +1;
            Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
            if (Shape.Brush.Color = clBlack) then
               Feld[x, y] := True
            else
               Feld[x, y] := False;
        end;
end;

procedure TForm1.btnLeerenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           if  (feld[x,y]) then
             feld[x,y] := false;
           snr := x +y *N +1;
           Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
           if not (feld[x,y]) then
             shape.brush.color := clwhite;
       end;
end;

procedure TForm1.TimerTimer(Sender: TObject);
begin
  btnrechnenClick(Self);
end;

 procedure TForm1.btnRechnenClick(Sender: TObject);
  var
    x, y: Integer;
    FeldNeu: TFeld;
begin
  for y := 0 to N-1 do
    for x := 0 to N-1 do
      if Feld[x, y] then
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in ueberleben)
      else
         FeldNeu[x, y] := (AnzahlLebenderNachbarn(x, y) in  geburt);
  Feld := FeldNeu;
  btnSchreibenClick(Self);
end;

var ckgeburt, ckueberleben : TCheckBox;
     i : integer;
begin
  form2.ShowModal;
  geburt := [];
  ueberleben := [];

  for i := 0 to 8 do begin
    ckgeburt := TCheckBox(Form2.FindComponent('ckgeburt' +IntToStr(i)));
    if ckgeburt.checked then
      geburt := geburt + [i];
  end;

  for i := 0 to 8 do begin
    ckueberleben := TCheckBox(Form2.FindComponent('ckueberleben' +IntToStr(i)));
    if ckueberleben.checked then
      ueberleben := ueberleben + [i];
  end;
end;}
procedure TForm1.btnRegelnClick(Sender: TObject);

  function GetRuleSet(const AName: String): TRegel;
    var
      CheckBox: TCheckBox;
      i: Integer;
  begin
    Result := [];
    for i := 0 to 8 do begin
    checkbox:= TCheckBox(Form2.FindComponent(aName +IntToStr(i)));
    if checkbox.checked then
      result := result + [i];

    end;

  end;

begin
  Form2.ShowModal;
  ueberleben := GetRuleSet('ckueberleben');
  geburt := GetRuleSet('ckgeburt');
end;

 function TForm1.AnzahlLebenderNachbarn(const x, y: Integer): Integer;
   var
     dx, dy: Integer;
 begin
   Result := 0;
   for dy := -1 to 1 do
     for dx := -1 to 1 do begin
      if  ((dx<>0or (dy<>0)) then
          if LebtNachbar(x +dx, y +dy) then
         Inc(Result);
     end;
 end;

function TForm1.LebtNachbar(x, y: Integer): Boolean;
begin
  Result := Feld[(x+N) mod N, (y+N) mod N];
end;

procedure TForm1.btnSchreibenClick(Sender: TObject);
var  x, y, snr: Integer;
    Shape: TShape;
begin
   for y := 0 to N-1 do
       for x := 0 to N-1 do begin
           snr := x +y *N +1;
           Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
           if (feld[x,y]) then
              shape.brush.color := clblack
           else
             shape.brush.color := clwhite;
       end;

end;

procedure TForm1.EndeClick(Sender: TObject);
begin
  close;
end;

procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
    trackbar : TTrackbar;
begin
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Nil); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown; // so weist man eine Methode zu
    FeldShape[x,y] := Shape;
   end;
  ClientHeight := N*25+100;
  ClientWidth := N*25+20;
  trackbar.Max := NMax;
end;

procedure TForm1.FormDestroy(Sender: TObject);
  var
    y, x: Integer;
begin
  for y := 0 to Nmax-1 do
    for x := 0 to Nmax-1 do begin
      if Assigned(FeldShape[x,y]) then begin // mit Assigned() kann man prüfen, ob einer (Zeiger-)Variablen ein Wert zugewiesen ist
        FeldShape.Free; // Komponente freigeben
        FeldShape[x,y] := nil// Referenz entfernen
      end;
   end;
end;


end.


Narses - So 26.04.15 19:22

Moin!

Zwei Kleinigkeiten haben wir aber noch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.FormDestroy(Sender: TObject);
//...
      if Assigned(FeldShape[x,y]) then begin // mit Assigned() kann man prüfen, ob einer (Zeiger-)Variablen ein Wert zugewiesen ist
        FeldShape[x,y].Free; // Komponente freigeben
        FeldShape[x,y] := nil// Referenz entfernen
//...
end;
Hier haben wir "vergessen" zu sagen, welches Shape da freigegeben werden soll. :oops: (das hätte eigentlich als Fehler im Kompiler auftauchen müssen :?)

Und hier:

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:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
    trackbar : TTrackbar;
begin
  trackbar.Max := NMax; // nach oben verschoben
  N := TrackBar.Position; // N vorbelegen (wird ja gleich benutzt)
  ClientHeight := N*25+100// nach oben verschoben
  ClientWidth := N*25+20;
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Nil); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown; // so weist man eine Methode zu
    FeldShape[x,y] := Shape;
   end;
end;
haben wir noch nicht dafür gesorgt, dass beim Programmstart N auch einen "vernünftigen" Wert erhält. Weiterhin habe ich das mal etwas umsortiert, so dass es mehr "Sinn" macht.

Damit sollte sich das wieder kompilieren lassen und auch korrekt laufen. OK? :les:

cu
Narses


Nini - So 26.04.15 19:35

ich krieg da grad so ne komische fehlermeldung o.O
fehlermeldung
ne das war die falsche merk ich grad ich such mal die richtige :D

so das müsste die richtige sein

fehlermeldung2

Moderiert von user profile iconNarses: Beiträge zusammengefasst.


Narses - So 26.04.15 19:44

Moin!

Ähm, ich seh da grad was: :?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
    trackbar : TTrackbar;
begin
  trackbar.Max := NMax; // nach oben verschoben
  N := TrackBar.Position; // N vorbelegen (wird ja gleich benutzt)
//...
Das ist natürlich Blödsinn, da einfach eine Trackbar als lokale Variable anzulegen. Du musst natürlich die entsprechende Komponente auf das Formular legen (und dann sollte da ein "TrackBar1" automatisch erstellt werden). :idea:

cu
Narses


Nini - So 26.04.15 19:49

also dann so

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
 procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  trackbar1.Max := NMax; // nach oben verschoben
  N := TrackBar1.Position; // N vorbelegen (wird ja gleich benutzt)
  ClientHeight := N*25+100// nach oben verschoben
  ClientWidth := N*25+20;


das öffnet sich jetzt wieder und hat dann nen 3x3 feld aber mehr will das nicht machen


Narses - So 26.04.15 19:54

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also dann so
Jup. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
das öffnet sich jetzt wieder und hat dann nen 3x3 feld aber mehr will das nicht machen
Dann stell mal TrackBar1.Position im Objekt-Inspektor auf 10, dann sollte der wieder mit 10 Feldern Kantenlänge starten.

Dass da nicht mehr passiert, ist erstmal normal. Genau da müssen wir ja noch ran. :zwinker:

cu
Narses


Nini - So 26.04.15 19:57

ja,jetzt sind es 10x10 felder :)


Narses - So 26.04.15 20:00

Moin!

Vorschläge, wie´s jetzt weiter geht? :lupe: :D

cu
Narses


Nini - So 26.04.15 20:03

irgendwie muss ich jetzt während das programm läuft N wieder einlesen aber wie weiß ich leider gar nicht :(


Narses - So 26.04.15 20:08

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
irgendwie muss ich jetzt während das programm läuft N wieder einlesen aber wie weiß ich leider gar nicht :(
Naja, das ist ja nicht besonders schwer, das hast du sogar schon gemacht:

Delphi-Quelltext
1:
N := TrackBar1.Position;                    

Allerdings... :? das reicht nicht. :nixweiss: Was muss denn noch alles geändert werden? :lupe: :gruebel:

cu
Narses


Nini - So 26.04.15 20:11

die shapes müssen noch dementsprechen erstellt werden


Narses - So 26.04.15 20:16

Moin!

Jap, und was heißt das im Detail? (beschreib mal so genau wie möglich - also was da ablaufen muss, den Code machen wir dann schon) :les:

cu
Narses


Nini - So 26.04.15 20:19

also erst muss ich formdestroy aufrufen, dass die gelöscht werden (oder sind die das dann schon? o.O) und dann muss ich ja eigentlich meiner meinung nach nur wieder mit der schleife von 0 bis N-1 die SHapes erzeugen wie am anfang davor auch also so oder so

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
  Shape := TShape.Create(self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown; // so weist man eine Methode zu
    FeldShape[x,y] := Shape;


Narses - So 26.04.15 20:31

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also erst muss ich formdestroy aufrufen, dass die gelöscht werden
FormDestroy aufrufen ist nicht so schlau - jedenfalls dann nicht, wenn du das Formular noch weiter nutzen möchtest. :P

Aber du kannst einen Button "btnShapesLoeschen" anlegen und das darüber abwickeln (also dann im FormDestory den Buttonhandler aufrufen, so wie wir das bei Lesen/Schreiben auch gemacht haben; das kannst du dann auch für die neue Idee nutzen). :nixweiss: Dann kann man zwischendurch auch mal (zum Entwickeln! später muss der Button natürlich wieder aus der Formular raus!) so anklicken zum Testen. ;)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
(oder sind die das dann schon? o.O) und dann muss ich ja eigentlich meiner meinung nach nur wieder mit der schleife von 0 bis N-1 die SHapes erzeugen wie am anfang davor auch
Jup. Auch hier: wie wäre es mit einem Button "btnShapesAnlegen"? :zwinker:

Wir haben aber noch ein ganz anderes, richtig krasses Problem... :? schon gefunden? :lupe:

cu
Narses


Nini - So 26.04.15 20:39

also das shapeanlegen funktioniert schon mal :)

in den andern prozeduren wussten die ja nicht was N jetzt ist, also hab ich überall N := TrackBar1.Position; eingefügt

und bei dem löschbutton überlege ich grad noch

Moderiert von user profile iconNarses: Beiträge zusammengefasst

al ich hab das jetzt so gemacht

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:
 procedure TForm1.btnShapesanlegenClick(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  btnShapesLoeschenClick(self);
  N := TrackBar1.Position; // N vorbelegen (wird ja gleich benutzt)
  ClientHeight := N*25+100// nach oben verschoben
  ClientWidth := N*25+20;
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(self); // Shape-Objekt erzeugen, als Eigentümer das Formular (=Self) angeben
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr); // Name der Komponente
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown; // so weist man eine Methode zu
    FeldShape[x,y] := Shape;
   end;

end;

procedure TForm1.btnShapesLoeschenClick(Sender: TObject);
var y, x: Integer;
begin
    for y := 0 to Nmax-1 do
    for x := 0 to Nmax-1 do begin
      if Assigned(FeldShape[x,y]) then begin // mit Assigned() kann man prüfen, ob einer (Zeiger-)Variablen ein Wert zugewiesen ist
        FeldShape[x,y].Free; // Komponente freigeben
        FeldShape[x,y] := nil// Referenz entfernen
      end;
   end;
end;


Narses - Mo 27.04.15 11:16

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also das shapeanlegen funktioniert schon mal :)
Naja, wenn du die Shapes selbst freigeben willst (was wir ja nun für das Ändern der Größe tun müssen), dann darfst du hier nicht "Self" übergeben, sondern "nil": :!:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.btnShapesanlegenClick(Sender: TObject);
//...
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(self); // das hier geht nicht, wenn man die Shapes selbst freigeben will!
    Shape.Parent := Self; // das neue Shape soll auf dem Formular (=Self) angezeigt werden

Wenn du Komponenten dem Formular übergibst (=wenn du "Self" in die Klammern schreibst), dann kann das üble Folgen haben, wenn du das Programm beendest (Exceptions etc.) und vorher diese Komponenten selbst freigegeben hast! :idea:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
in den andern prozeduren wussten die ja nicht was N jetzt ist, also hab ich überall N := TrackBar1.Position; eingefügt
Eigentlich muss das nur an zwei Stellen hin: im FormCreate (zum Vorbelegen beim Programmstart) und dann beim Erzeugen der neuen Shapes. :gruebel: Was genau meinst du also mit "überall"? :lupe: :nixweiss:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
al ich hab das jetzt so gemacht
Sieht schonmal gar nicht schlecht aus. :zustimm:

Zeig doch nochmal bitte deine FormCreate und FormDestroy-Methoden. :les:

cu
Narses


Narses - Di 28.04.15 13:46

Moin!

Wie sieht´s aus? :lupe: Probleme? 8) Egal was du machst, ob mit Self oder nil als Parameter für die Shape-Erzeugung - es gibt immer irgendwo Exceptions? :P Könnte das der Grund sein, wieso hier so viel Stille herrscht... ? :zwinker:

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Wir haben aber noch ein ganz anderes, richtig krasses Problem... :? schon gefunden? :lupe:

cu
Narses


Nini - Di 28.04.15 20:24


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:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  trackbar1.Max := NMax;
  N := TrackBar1.Position;
  ClientHeight := N*25+100;
  ClientWidth := 620;
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Nil);
    Shape.Parent := Self;
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr);
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown;
    FeldShape[x,y] := Shape;
   end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
  var
    y, x: Integer;
begin
  for y := 0 to Nmax-1 do
    for x := 0 to Nmax-1 do begin
      if Assigned(FeldShape[x,y]) then begin
        FeldShape[x,y].Free;
        FeldShape[x,y] := nil;
      end;
   end;
end;

also das wären erstmal formcreate und formdestroy, aber die exceptions nerven halt total


Narses - Di 28.04.15 20:50

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
also das wären erstmal formcreate und formdestroy,
OK, danke. Aber hattest du nicht bereits Buttons für die Funktionalität (Shapes anlegen/löschen) erstellt? Dann kannst du doch den Button-Click-Handler aufrufen. ;) (und musst den Code nicht zweimal schreiben :idea:)

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
aber die exceptions nerven halt total
Wir müssen ein "nil" übergeben, da führt kein Weg dran vorbei, sonst dürfen wir die Shapes nicht freigeben. :nixweiss: Also müssen wir die Ursache für die Exceptions suchen. Dazu sollten wir erstmal rausfinden, wann die denn ganz genau auftreten (normalerweise hilft die IDE dir ja und zeigt die Stelle im Code :think:). Wo passiert´s denn? :lupe:

cu
Narses


Nini - Mo 04.05.15 20:59


Delphi-Quelltext
1:
  if (Shape.Brush.Color = clBlack) then                    

die zeile ruft das auf also in der lesenprozedure

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
procedure TForm1.btnLesenClick(Sender: TObject);
var x, y, snr: Integer;
    Shape: TShape;
begin
  N := TrackBar1.Position;
    for y := 0 to N-1 do
        for x := 0 to N-1 do begin
            snr := x +y *N +1;
            Shape := TShape(FindComponent('Shape' +IntToStr(snr)));
            if (Shape.Brush.Color = clBlack) then
               Feld[x,y] := True
            else
               Feld[x,y] := False;
        end;
end;


und das mit dem formdestroy/create dann so? O.o

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:
procedure TForm1.FormCreate(Sender: TObject);
var snr,y,x : integer;
    shape : TShape;
begin
  trackbar1.Max := NMax;
  N := TrackBar1.Position;
  ClientHeight := N*25+100;
  ClientWidth := 620;
  for y := 0 to N-1 do
   for x := 0 to N-1 do begin
    Shape := TShape.Create(Nil);
    Shape.Parent := Self;
    snr := x +y *N +1;
    Shape.Name := 'Shape'+inttostr(snr);
    Shape.Left := 10+x*25;
    Shape.Top := 80+y*25;
    Shape.Width := 25;
    Shape.Height := 25;
    Shape.OnMouseDown := @Shape1MouseDown;
    FeldShape[x,y] := Shape;
   end;
  btnShapesAnlegenClick(self)
end;

procedure TForm1.FormDestroy(Sender: TObject);
  var
    y, x: Integer;
begin
  for y := 0 to Nmax-1 do
    for x := 0 to Nmax-1 do begin
      if Assigned(FeldShape[x,y]) then begin
        FeldShape[x,y].Free;
        FeldShape[x,y] := nil;
      end;
   end;
  btnShapesLoeschenClick(self);
end;


Narses - Mo 04.05.15 22:11

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
  if (Shape.Brush.Color = clBlack) then                    
die zeile ruft das auf also in der lesenprozedure
Ja, genau. Hier wird eine Exception geworfen, weil hier:

Delphi-Quelltext
1:
Shape := TShape(FindComponent('Shape' +IntToStr(snr)));                    
das Shape nicht mehr gefunden wird (FindComponent liefert dann ein nil = nicht gefunden zurück). :idea: Aber warum? :gruebel: Ganz einfach: da wir beim Erzeugen des Shapes nil übergeben haben, gehört die Komponente nun wirklich uns und nicht mehr dem Formular - da (=im Formular) sucht FindComponent aber.

Wie kommen wir nun weiter? Ganz einfach, wir heben doch schon eine Referenz auf die Shapes in FeldShape auf, dann können wir diese ebenfalls nutzen, um auf die Shapes zuzugreifen, statt über den Namen der Komponente jedes mal danach suchen zu müssen. :think: Ganz konkret also so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.btnLesenClick(Sender: TObject);
  var
    x, y: Integer;
begin
  for y := 0 to N-1 do
    for x := 0 to N-1 do
      if (FeldShape[x,y].Brush.Color = clBlack) then // direkt auf das Shape zu greifen, statt erst danach zu suchen ;)
        Feld[x,y] := True
      else
        Feld[x,y] := False;
end;




user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
und das mit dem formdestroy/create dann so? O.o
Eher nicht. :? Nochmal kurz zur Erinnerung, was wir an dieser Stelle mit den Buttons tun: das ist ein Zwischenschritt, um die Funktionalität (Shapes erstellen/löschen) zum Testen auch mal so zwischendurch probieren zu können. Du solltest also das, was eigentlich getan werden muss, in den Button-Handler verlagern und dann in den Formularmethoden nur noch aufrufen. Konkret:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.btnShapesAnlegenClick(Sender: TObject);
  var
    x, y: Integer;
begin
  N := TrackBar1.Position;
  for y := 0 to N-1 do
    for x := 0 to N-1 do begin
      FeldShape[x,y] := TShape.Create(Nil); // die Hilfsvariable "Shape" können wir uns sparen, wenn wir direkt das FeldShape nehmen ;)
      FeldShape[x,y].Parent := Self; // und den Namen brauchen wir auch nicht mehr, wir suchen ja nicht mehr danach
      FeldShape[x,y].Left := 10+x*25;
      FeldShape[x,y].Top := 80+y*25;
      FeldShape[x,y].Width := 25;
      FeldShape[x,y].Height := 25;
      FeldShape[x,y].OnMouseDown := @Shape1MouseDown;
    end;
end;

Und dann im FormCreate nur noch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Trackbar1.Max := NMax;
  ClientHeight := N*25+100;
  ClientWidth := 620;
  btnShapesAnlegenClick(self);
end;


Deine Aufgaben sind nun:
Dann sollte es eigentlich keine Exceptions mehr geben und wir sind bereit für den letzten Schritt: Reaktion auf Änderung der Trackbar. ;)

Dann leg mal los. :zustimm:

cu
Narses


Nini - Mo 18.05.15 12:16

So jetzt hab ich endlich mal daran gedacht, hier wieder zu schreiben. Zur Zeit komme ich einfach nicht mehr zum programmieren, vielleicht später mal wieder, und das Projekt habe ich schon vor einiger Zeit mit dem damaligen Stand abgegeben. Deshalb möchte ich mich noch mal sehr bedanken für deine Hilfe.


Delphi-Laie - Mo 18.05.15 22:48

Hat da Forum eine Chance zu erfahren, ob das Ergebnis Deiner Mühe und im weiteren Sinne der Mühe vieler hier dem kritischen Blicke Deines Fachlehrers standhielt (=Benotung), liebe Nini?

Sicher wird das nicht nur diejenigen interessieren, die sich so rührend Deiner annahmen. Dein Erscheinen hier im Forum führte nicht nur zu einer neuen Dialogform - der reinen Tutor-Zögling-Beziehung -, sondern auch zur Auslagerung ursprünglich bei Dir angesiedelten "peripheren", dafür dann aber umso hitzigeren Meinungstausches.


Nini - Mo 08.06.15 20:56

Heute habe ich jetzt endlich die Info-Hausarbeit Game of life zurückbekommen, hab eine 1 :) :party: endlich mal ne 1 in info, bei der ich das Gefühl habe, auch wirklich was gelernt und verstanden zu haben, auch wenn es natürlich noch verbesserungswürdig ist. Dafür noch einmeieinmal ein Riesendankeschön :)


Delphi-Laie - Mo 08.06.15 21:06

Meine Anerkennung für das verdiente Ergebnis Deiner Audauer und Deines Fleißes, die/den aber auch etliche andere Forumsteilnehmer aufbrachten!


Nersgatt - Di 09.06.15 08:22

Sehr gut! Im wahrsten Sinne des Wortes. :zustimm:

Hier wird ja öfters nach Hausaufgabenhilfe gefragt. Aber Dein Durchhaltevermögen, Einsatz und Willen zum Lernen hat noch niemand gezeigt. Ich ziehe meinen Hut vor Dir, weiter so!
Und Dank natürlich an Narses, der mit einer Engelsgeduld viel Zeit für die Hilfe aufgebracht hat.


Narses - Do 11.06.15 17:42

Moin!

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
endlich mal ne 1 in info, bei der ich das Gefühl habe, auch wirklich was gelernt und verstanden zu haben,
:zustimm: Das hast du dir redlich verdient, meinen Respekt für dein Engagement. :party:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
Dafür noch einmeieinmal ein Riesendankeschön :)
:beer:

user profile iconNini hat folgendes geschrieben Zum zitierten Posting springen:
auch wenn es natürlich noch verbesserungswürdig ist.
Wie schon mal angedeutet: du bist herzlich willkommen an dem Projekt weiterzuarbeiten, melde dich einfach, wenn du Zeit und Lust hast. ;) Vielleicht hast du ja tatsächlich die Informatik als interessantes Hobby entdeckt... :zwinker:

cu
Narses