is-Logo Karel D. Robot
Programmiertips

S. Spolwig

[Delphi | OOP]
Startseite

Wie kann ich ...
  1. meine Übungen strukturieren und speichern?
     
  2. ein neues Objekt in das Programm einfügen?
     
  3. die Methoden verändern von TRobot (oder anderen Klassen) ?
     
  4. ein Bild als Attribut eines Objekts einfügen?
     
  5. dem Roboter beibringen, ein Objekt zu identifizieren, damit er es z. B. aufnehmen kann?
     
  6. eine Aktion in Karels Gedächtnis aufnehmen?
     
  7. das Protokoll der Roboter-Actions aktivieren?
     
  8. einen Roboter zu einem entfernten Feld springen lassen?
     
  9. einen Roboter schneller machen?
     
  10. eine Meldung ausgeben?

 

 

Antworten

1. meine Übungen strukturieren und speichern?

Zur Strukturierung

Vor 30 Jahren war man in der Schule stolz, wenn als 1. Programm auf einem ansonsten schwarzen Bildschirm in grüner Schrift erschien: HALLO WORLD
 

Das ganze Programm dazu so aus:

Genauso winzig war die Datei, die
das Programm speicherte.

program hallo;
begin
  writeln('HALLO WORLD');
end.

Sie haben den Vorzug mit einem professionellen Programm zu arbeiten, das entsprechend umfangreich ist. Dabei operieren Sie zunächst immer nur an einem ziemlich kleinen Teil eines lebenden Organismus. Man muß die Übersicht behalten und kann nicht für jede kleine Änderung jedesmal das gesamte Projekt mit seinen rund 2 MB abspeichern. Läßt man alle Änderungen im ControlFrm stehen, wird das schnell lang und unübersichtlich.

Anfangs werden Sie wahrscheinlich im ControlFrm arbeiten. Nehmen wir an, die Aufgabe lautet
RD1 soll dreimal im Kreis herumlaufen.

A)

In vielen Delphi-Anfängerbüchern würden Sie einen Vorschlag wie diesen finden.

Oder noch vielleicht viel längere Prozeduren bei anderen Problemen.

 

 


So nicht !

Ein Lichtschalter an der Wand produziert weder die Elektrizität noch erhellt er den Raum. Er schaltet nur den Strom ein. Genau das soll ein Button tun.


B) Die bessere Lösung ist aufgeteilt:

    in die Ereignismethode (der Button-Click)

procedure TControlFrm.Button1Click(Sender: TObject);
begin
 
ImKreisHerum;
end;

   und eine private Methode, die das Problem bearbeitet und bei Bedarf aufgerufen wird

procedure TControlFrm.ImKreisHerum;
var i : integer;
begin
  for i := 1 to 12 do
  begin
    RD1.Vor;
    RD1.RechtsDrehen
  end;
end;

Das ist guter Programmierstil. Es sieht zunächst umständlich aus, schafft aber klar strukturierte Programme, in denen das an der Stelle steht, wo es hingehört (Lokalität). Sie brauchen auch nur einen Button, um verschiedene Methoden aufzurufen und zu testen.

C) Genau genommen haben Sie eine neue Methode für Roboter entwickelt,  die in die Roboterklasse
     aufgenommen werden kann und dann für jeden Roboter zur Verfügung steht.

Zum Speichern von Übungen im ControlFrm

- Die pragmatische Lösung: Statt das gesamte Projekt zu speichern, können Sie einzelne Prozeduren / Lösungen aus dem ControlFrm ausschneiden und in eine separate Textdatei zur Speicherung kopieren und bei Bedarf später wieder zurückkopieren. Das funktioniert aber nicht mit der Lösung A, sondern nur mit B (ohne die ButtonClick-Methode).

- Die professionelle Lösung: Wenn es eine gute Methode wert ist, als neue allgemeine Roboter-Methode implementiert zu werden, gehen wie in C vor und speichern die Unit mit der Roboterklasse.

 

2.  ein neues Objekt in das Programm einfügen?
 

var Auto : TCritter;   // in ControlFrm bei var deklarieren

Auto := TAuto.Create;  // Objekt erzeugen
                          z.B. Auto in procedure ItemsErzeugen
Auto.SetPos ('G',2);   // und an die gewünschte Stelle setzen

 

3.  die Methoden von TRobot (oder anderen Klassen) verändern?

Im Prinzip in der Unit uRobot. Davon wird aber dringend abgeraten, wenn Sie nicht sehr genau wissen, was Sie tun, weil jede Änderung sich in den Unterklassen ebenfalls auswirkt.

Es ist besser, eine neue Unterklasse TMyRobot (oder so ähnlich genannt) zu erstellen und dort die geerbte Methode zu überschreiben und dann mit TMyKarel weiterarbeiten.
Beispiel:

Unit uMyRobot;
INTERFACE
uses uRobot;

type
  TMyRobot = class (TRobot)   // erbt alles

  procedure Vor; override;    // hier überschreiben mit der eigenen Methode
  ...

 

4.  ein Bild als Attribut einfügen?

Zweckmäßigerweise sollten alle Exemplare der betreffenden Klasse dasselbe Bild tragen. Dann fügen Sie in die Initialisierungsprozedur die Zeile ein:

procedure Txyz.Init;
begin

  ...
  Blume.SetBild ('.\bilder\blume.bmp');
end;

Zuvor müssen Sie das Bild blume.bmp in das Verzeichnis \bilder kopieren. Format : 28 x 28 pixel.
 

 

5.  dem Roboter beibringen, ein Objekt zu identifizieren, damit er es z. B. aufnehmen kann?

Man kann Objekte fragen, zu welchem Typ sie gehören. Wenn Karel z. B. vor einem Baum steht, liefert seine Methode 'HindernisPruefen : TItem' die entsprechende Klasse.

if (RD1.HindernisPruefen is TBaum)
then ...

 

6.  eine Aktion in Karels Gedächtnis aufnehmen?

Derzeitig werden die Methoden 'Vor' und 'RechtsDrehen' ins Gedächtnis gemerkt.
Fügen Sie die Anweisung 'InsGedaechtnis ('...'); in die gewünschte Prozedur der Roboterklasse ein. Im Parameter steht der string, der die Aktion bezeichnet.
Beispiel:

procedure TMyKarel.Rueckwaerts;
begin

   ...
   InsGedaechtnis('Rueckwaerts');
end;

 

7.  das Protokoll der Roboter-Actions aktivieren?

Da bei der Entwicklung dieses Programms noch nicht bekannt ist, wie Ihr Roboter später vielleicht heißen wird, aktivieren Sie das Protokoll selbst. Das Protokollformular bekommt mitgeteilt, welcher Roboter die Daten zur Anzeige liefert, z. B. RD1:

ProtokollFrm.Aktualisieren(RD1);

Fügen Sie im ControlFrm diese Anweisung in die Methode  ein, mit der Sie den Roboter starten.
Beispiel:

procedure TControlFrm.GoBtnClick(Sender: TObject);
begin
  inherited;
  while NOT RD1.BatterieLeer do
    begin
     if RD1.VorneFrei
     then RD1.Vor
     ....
     ...
    
ProtokollFrm.Aktualisieren(RD1);  // jede Aktion wird angezeigt
  end;
end;

Sie können die Anweisung auch in mehreren Prozeduren implementieren;
außer in TControlFrm.ItemsErzeugen (Absturz!)

 

8.  einen Roboter zu einem entfernten Feld springen lassen?

Am besten gar nicht!
Angenommen beim Programmstart heißt es 'RD1.SetPos('B',1)'. Diese Anweisung registriert ihn mit dieser Position in der Welt. Mit einer Anweisung 'RD1.Vor' würde er sich sauber abmelden, mit einem Sprung z. B. nach ('D',5) aber nicht: damit ist er dann zweimal in der Welt registriert.
Im unmittelbaren Programmablauf scheint das zunächst nicht zu stören, hat aber Probleme. B,1 ist besetzt, obwohl nichts zu sehen ist und spätestens beim Programmende erscheint eine Fehlermeldung, weil die Welt nicht sauber geschlossen werden kann.
Wenn Sie dennoch den Roboter 'fliegen' lassen wollen, sorgen Sie für eine korrekte Abmeldung mit der Anweisung

Begin
  ...
 
Welt.Abmelden(RD1);  
  RD1.SetPos(...);  // neue Position
  ...

 

9.  einen Roboter schneller machen?

Die Darstellungsgeschwindigkeit hängt einerseits von uGrafik und dem darin implementierten Modell und zweitens von der Prozessorgeschwindigkeit ab.
Setzen Sie zunächst die Geschwindigkeit des Objekts herauf mit z. B. RD1.SetGeschwindigkeit(8);
(max. 10). Wenn das nicht hilft und Sie einen langsamen Rechner haben, hilft nur noch eine Anpassung in uZeit.pas bei der

  procedure TZeit.SetPause(millisec : longint);
  (* ------------------------------------------------- *)
  var i : LongInt;
  begin
    for i := 1 to 22400 * millisec do // ca. 1 mSek Bratzeit
    Application.ProcessMessages;
  end;


Die Schleife verheizt einfach Prozessorzeit: setzen Sie den Wert herunter bis die Pause (die in allen Critter-Bewegungen steckt) kürzer wird. Dadurch werden die Bewegungen schneller.

 

10.  eine Meldung ausgeben?

Beispiel:

procedure TControlFrm.GoBtnClick(Sender: TObject);
// -----------------------------------------------------------------------
begin
  inherited;
  RD1.AllesEinsammeln;
 
Meldung(' Fertig');
end;
 


©  05. Oktober 2008    Siegfried Spolwig

page_top