Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Hilfe mit Textadventure (https://www.delphipraxis.net/183425-hilfe-mit-textadventure.html)

MW28 8. Jan 2015 17:15

Hilfe mit Textadventure
 
Hallo ,

ich muss für die Schule als Projekt ein Textadventure mit Delphi 7 erstellen(nichts allzu kompliziertes). Ich habe nun schon ein wenig angefangen soweit ich konnte, jetzt komm ich aber bei den Attributen(?) für die Klassen nicht so recht weiter. Das ganze compiled zwar, nimmt aber die Attribute nicht so recht an (bleiben auf nil). Falls ich irgendeinen offensichlichen Fahler gemacht hab tut es mir leid aber wir haben erst ca. 15 Doppelstunden Informatik gehabt und unser Lehrer ist nicht grade gut im Erklären bzw. erklärt garnichts sondern gibt einfach nur Arbeitsblätter.

Hier der Quellcode von Form1 :
Delphi-Quellcode:
unit DelphiSpiel;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, URaum, ExtCtrls, StdCtrls, JPEG ;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Edit1: TEdit;
    Button1: TButton;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
   
  public

  end;

var
  Form1: TForm1;
  info_aktuellerRaum : string ;
  info_startRaum : string     ;
  info_raum1 : string         ;
  info_raum2 : string         ;
  info_raum3 : string         ;
  aktuellerRaum , startRaum , raum1 , raum2 , raum3 : TRaum ;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
image1.canvas.create ;

startRaum := TRaum.Create;
startRaum.setAusgang(raum1,nil,nil,nil);
info_startRaum := 'Dies ist der Start. Hier geht es nur in eine Richtung' ;

raum1 := TRaum.Create  ;
raum1.setAusgang(raum2,nil,raum3,nil,);
info_raum1 := 'dies ist raum1' ;

raum2 := TRaum.Create  ;
raum2.setAusgang(nil,raum1,nil,nil);
info_raum2 := 'dies ist raum2' ;

raum3 := TRaum.Create  ;
raum3.setAusgang(nil,nil,nil,raum1);
info_raum3 := 'dies ist raum3' ;

aktuellerRaum := TRaum.Create ;
aktuellerRaum.setAusgang(nil,nil,nil,nil);
info_aktuellerRaum := 'fehler' ;

aktuellerRaum := startRaum ;
info_aktuellerRaum := info_startRaum ;

Memo1.Clear ;
Memo1.Lines.add(info_aktuellerRaum) ;
if aktuellerRaum.Fnorth <> nil then Memo1.Lines.add('---->Norden') ;
if aktuellerRaum.Fsouth <> nil then Memo1.Lines.add('---->Süden') ;
if aktuellerRaum.Feast <> nil then Memo1.Lines.add('---->Osten') ;
if aktuellerRaum.Fwest <> nil then Memo1.Lines.add('---->Westen') ;
if startRaum.Fnorth = nil then Memo1.Lines.add('attribute wurden nicht richtig festgelegt');


end;

procedure TForm1.Button1Click(Sender: TObject);
var eingabe : string;
begin
eingabe := edit1.Text ;
if (eingabe = 'Norden')and (aktuellerRaum.Fnorth = nil) then aktuellerRaum := aktuellerRaum.Fnorth ;
if (eingabe = 'Süden')and (aktuellerRaum.Fsouth <> nil) then aktuellerRaum := aktuellerRaum.Fsouth ;
if (eingabe = 'Osten')and (aktuellerRaum.Feast <> nil) then aktuellerRaum := aktuellerRaum.Feast ;
if (eingabe = 'Westen')and (aktuellerRaum.Fwest <> nil) then aktuellerRaum := aktuellerRaum.Fwest ;

Memo1.clear ;
Memo1.Lines.add(info_aktuellerRaum);

if aktuellerRaum.Fnorth <> nil then Memo1.Lines.add('---->Norden') ;
if aktuellerRaum.Fsouth <> nil then Memo1.Lines.add('---->Süden') ;
if aktuellerRaum.Feast <> nil then Memo1.Lines.add('---->Osten') ;
if aktuellerRaum.Fwest <> nil then Memo1.Lines.add('---->Westen') ;

end;

end.
Und hier der von URaum:
Delphi-Quellcode:
unit URaum;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, JPEG;

type
  TRaum = class
   Fnorth,Fsouth,Feast,Fwest : TRaum;
   procedure setAusgang(n,s,e,w : TRaum);
   Constructor Create;

   private

   public

end;

implementation
Constructor TRaum.Create;
begin
self.Fnorth := Fnorth;
self.Fsouth := Fsouth;
self.Feast := Feast;
self.Fwest := Fwest;
end;

procedure TRaum.setAusgang(n,s,e,w : TRaum) ;
begin
self.Fnorth := Fnorth;
self.Fsouth := Fsouth;
self.Feast := Feast;
self.Fwest := Fwest;
end;
end.
Soweit ich inzwischen weiß müsste man das garnicht in verschieden Dateien machen, aber unser Leherer hat uns das so gezeigt.

Schon mal vielen Dank im Vorraus.

Jonas Shinaniganz 8. Jan 2015 17:25

AW: Hilfe mit Textadventure
 
Ich drück mal beide Augen fest zu und antworte möglichst produktiv.
Schau mal hier:
Delphi-Quellcode:
procedure TRaum.setAusgang(n,s,e,w : TRaum) ;
begin
 self.Fnorth := Fnorth;
 self.Fsouth := Fsouth;
 self.Feast := Feast;
 self.Fwest := Fwest;
end;
Untersuche genau, was du hier zuweist.
gruß j

DeddyH 8. Jan 2015 17:31

AW: Hilfe mit Textadventure
 
Und den Sinn von
Zitat:

Delphi-Quellcode:
image1.canvas.create ;

solltest Du uns vielleicht auch einmal erklären.

Sir Rufo 8. Jan 2015 17:50

AW: Hilfe mit Textadventure
 
Also den Raum selber würde ich schon anders aufbauen. Warum merkt sich der Raum nicht die Beschreibung selber?

Und wenn ich mich von einem Raum in eine Richtung x bewege, dann kann diese Methode doch einfach eine Raum-Instanz zurückliefern. Gibt es keinen Raum in Richtung x, dann liefert der Raum einfach die eigene Instanz zurück.

Delphi-Quellcode:
Procedure TForm.Move ( ADirection : TDirection );
begin
  FCurrentRoom := FCurrentRoom.MoveTo ( ADirection );
end;
Sieht viel einfacher aus und ist auch leichter zu verstehen.

MW28 8. Jan 2015 18:16

AW: Hilfe mit Textadventure
 
Zitat:

Zitat von Jonas Shinaniganz (Beitrag 1285937)
Untersuche genau, was du hier zuweist.
gruß j

Ich vermute mal das ist total unnötig? Zu meiner Verteidigung muss ich sagen das das nach den etwas dürftigen AB's meines Lehrers entstanden ist.

Zitat:

Zitat von DeddyH
Und den Sinn von
Zitat:

image1.canvas.create ;
solltest Du uns vielleicht auch einmal erklären.

Das ist lediglich zum Testen bzw. als Platzhalter drin. Wir sollen zu jedem Raum ein Bild anzeigen lassen.

Sir Rufo 8. Jan 2015 18:39

AW: Hilfe mit Textadventure
 
Zitat:

Zitat von MW28 (Beitrag 1285948)
Zitat:

Zitat von Jonas Shinaniganz (Beitrag 1285937)
Untersuche genau, was du hier zuweist.
gruß j

Ich vermute mal das ist total unnötig? Zu meiner Verteidigung muss ich sagen das das nach den etwas dürftigen AB's meines Lehrers entstanden ist.

Zitat:

Zitat von DeddyH
Und den Sinn von
Zitat:

image1.canvas.create ;
solltest Du uns vielleicht auch einmal erklären.

Das ist lediglich zum Testen bzw. als Platzhalter drin. Wir sollen zu jedem Raum ein Bild anzeigen lassen.

Das ist nicht unnötig, sondern du weist dem Wert den gleichen Wert zu. Du legst also die 5€ in deine Geldbörse, die da schon drin waren und denkst, jetzt habe ich 10€.
Delphi-Quellcode:
var
  a : Integer;
begin
  a := a; // toll ... aber wozu, in a steht eh schon der Wert von a drin, weil ist ja auch a
end;
Delphi-Quellcode:
procedure TRaum.setAusgang(n,s,e,w : TRaum) ;
begin
 self.Fnorth := n;
 self.Fsouth := s;
 self.Feast := e;
 self.Fwest := w;
end;
Somit ist das nicht der Fehler auf dem AB deines Lehrers, sondern DU hast das nicht verstanden.

Delphi-Quellcode:
image.canvas.create;
ruft den
Delphi-Quellcode:
constructor
der bereits erzeugten Instanz auf. Es wird dadurch keine neue Instanz erzeugt. Ist in diesem Zusammenhang also sinnlos.

MW28 8. Jan 2015 19:47

AW: Hilfe mit Textadventure
 
[QUOTE=Sir Rufo;1285957][QUOTE=MW28;1285948]
Zitat:

Zitat von Jonas Shinaniganz (Beitrag 1285937)

Somit ist das nicht der Fehler auf dem AB deines Lehrers, sondern DU hast das nicht verstanden.

Delphi-Quellcode:
constructor TFruit.Create(name: string);
begin
  // And save the fruit name
  self.name := name;
end;
Auszug aus dem PDF Arbeitsblatt zum Constructor. Wir haben allerdings auch ein Blatt bekommen wo das so wie du das gemacht hast(also mit n,s,e,w) angedeutet wird.Die Möglichkeit die du nennst hatte ich schon einmal ausprobiert, macht aber auch keinen Unterschied. Das Problem bleibt bestehen.

Sir Rufo 8. Jan 2015 20:03

AW: Hilfe mit Textadventure
 
Also schauen wir uns mal das vom Arbeitsblatt an
Delphi-Quellcode:
constructor TFruit.Create(name: string);
begin
  // And save the fruit name
  self.name := name;
end;
und das was du daraus gemacht hast
Delphi-Quellcode:
constructor TFruit.Create(name: string);
begin
  // And save the fruit name
  self.Fname := Fname;
end;
Was fällt uns auf? Eben, denn richtig wäre
Delphi-Quellcode:
constructor TFruit.Create(name: string);
begin
  // And save the fruit name
  self.Fname := name;
end;
denn
Delphi-Quellcode:
constructor TFruit.Create( {Argument} name: string);
begin
  // And save the fruit name
  self.name := {Argument} name;
end;
Es hat einfach damit zu tun, dass der Compiler sich hier entscheiden muss, worauf sich
Delphi-Quellcode:
name
denn nun bezieht. Auf ein Element der Klasse oder eben das Argument. Da das Argument der Methode in der Methode aber näher ist als die Klasse, bezieht sich
Delphi-Quellcode:
name
auf das Argument. Um auf die Klassen-Variable zuzugreifen muss man den Scope mit angeben durch
Delphi-Quellcode:
self.name
.

OlafSt 8. Jan 2015 21:11

AW: Hilfe mit Textadventure
 
Es hat schon seinen Grund, warum Borland mal empfohlen hat, Parameter mit einem "A" als Prefix zu versehen, sowie Felder mit einem "F"-Prefix:
Delphi-Quellcode:

constructor TFruit.Create(AName: string);
begin
  // And save the fruit name
  self.FName := AName;
end;
Nochmal hervorgehoben: self.FName := AName;
So gibts auch keine babylonische Sprachverwirrung mit "name" als Parameter und "name" als Feld. Ich glaube, das der TE nämlich diesen Zusammenhang gar nicht erkannt hat. Und Asche auf das Haupt des Lehrers, der das selbst nicht gerafft hat.

Sir Rufo 8. Jan 2015 21:25

AW: Hilfe mit Textadventure
 
Woraus schliesst du, dass der Lehrer da was nicht gerafft hat? Das kann ich daraus nicht ableiten.

MW28 8. Jan 2015 21:30

AW: Hilfe mit Textadventure
 
Ich der hat das glaube ich schon gerafft, aber den Schülern (also uns) hat der das nicht erklärt. Der Untericht frei im Stil von "Wenn ihr was nicht wisst googlt es." Das ist erstmal garkeine so schlechte Idee aber das ist auch nicht der Sinn eines Lehrers.

Edit: Hab jetzt den Code auf das hier geändert
Delphi-Quellcode:
procedure TRaum.setAusgang(Anorth,Asouth,Aeast,Awest : TRaum) ;
begin
self.Fnorth := Anorth;
self.Fsouth := Asouth;
self.Feast := Aeast;
self.Fwest := Awest;
end;
Allerdings kann ich mit dieser procedure immer noch nicht die Ausgänge festlegen , da sie auf nil bleiben. Ich glaub ich hab das ganze immer noch nicht richtig verstanden. Oder liegt der Fehler jetzt woanders?

Medium 8. Jan 2015 23:43

AW: Hilfe mit Textadventure
 
Du hast noch ein anderes Problem. Mal ein Auszug aus deinem Code:
Delphi-Quellcode:
// 0
startRaum := TRaum.Create;
startRaum.setAusgang(raum1,nil,nil,nil);
info_startRaum := 'Dies ist der Start. Hier geht es nur in eine Richtung' ;

// 1
raum1 := TRaum.Create;
raum1.setAusgang(raum2,nil,raum3,nil);
info_raum1 := 'dies ist raum1' ;

// 2
raum2 := TRaum.Create  ;
raum2.setAusgang(nil,raum1,nil,nil);
info_raum2 := 'dies ist raum2';
Bei "// 0" setzt du den ersten Parameter in setAusgang() auf "raum1". "raum1" ist zu diesem Zeitpunkt allerdings noch überhaupt nicht erstellt worden, und ist somit "nil". Dort steht also effektiv daher
Delphi-Quellcode:
startRaum.setAusgang(nil,nil,nil,nil);
. Nachträglich an "raum1" zugewiesene Werte werden nicht automatisch an in der Vergangenheit gemachte Zuweisungen weitergeleitet.
Bei "// 1" hast du letztlich genau dasselbe Problem, "raum2" und "raum3" sind dort noch "nil".
Bei "// 2" müsste aber "raum1" bereits mit einer Instanz von TRaum belegt sein, und somit wird dort NICHT "nil" im 2. Parameter übergeben. Dort sollte es tatsächlich passen.

Das simpelste wäre hier wohl, wenn man zuerst alle Räume erstellt, und erst danach allen ihre Ausgänge zuweist:
Delphi-Quellcode:
startRaum := TRaum.Create;
raum1 := TRaum.Create;
raum2 := TRaum.Create  ;

info_startRaum := 'Dies ist der Start. Hier geht es nur in eine Richtung' ;
info_raum1 := 'dies ist raum1' ;
info_raum2 := 'dies ist raum2';

startRaum.setAusgang(raum1,nil,nil,nil);
raum1.setAusgang(raum2,nil,raum3,nil);
raum2.setAusgang(nil,raum1,nil,nil);
Auf die strukturellen "Fehler" sollten wir hier denke ich erstmal nicht weiter eingehen, das würde für ein Schulprojekt wohl zu weit führen, und den TE eher noch mehr verwirren. (So Dinge wie, dass die "info_*" Variablen nach OOP eigentlich ein Feld von TRaum sein sollten z.B.) Wichtiger ist erst mal, dass es überhaupt schon mal klappt. Alleine schon um den Spaß dran zu behalten.

MW28 9. Jan 2015 12:51

AW: Hilfe mit Textadventure
 
Vielen Dank für die Hilfe. Ich hab den Code jetzt auf das hier verändert:
Delphi-Quellcode:
unit DelphiSpiel;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, URaum, ExtCtrls, StdCtrls, JPEG ;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Edit1: TEdit;
    Button1: TButton;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
   
  public

  end;

var
  Form1: TForm1;
  info_aktuellerRaum : string ;
  info_startRaum : string     ;
  info_raum1 : string         ;
  info_raum2 : string         ;
  info_raum3 : string         ;
  aktuellerRaum , startRaum , raum1 , raum2 , raum3 : TRaum ;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
image1.canvas.create ;

startRaum := TRaum.Create ;
raum1 := TRaum.Create ;
raum2 := TRaum.Create ;
raum3 := TRaum.Create ;
aktuellerRaum := TRaum.Create ;

startRaum.setAusgang(raum1,nil,nil,nil,'Dies ist der Start. Hier geht es nur in eine Richtung');
raum1.setAusgang(raum2,nil,raum3,nil,'dies ist raum1');
raum2.setAusgang(nil,raum1,nil,nil,'dies ist raum2');
raum3.setAusgang(nil,nil,nil,raum1,'dies ist raum3');
aktuellerRaum.setAusgang(nil,nil,nil,nil,'fehler');

info_startRaum := 'Dies ist der Start. Hier geht es nur in eine Richtung' ;
info_raum1 := 'dies ist raum1' ;
info_raum2 := 'dies ist raum2' ;
info_raum3 := 'dies ist raum3' ;
info_aktuellerRaum := 'fehler' ;

aktuellerRaum := startRaum ;
info_aktuellerRaum := info_startRaum ;

Memo1.Clear ;
Memo1.Lines.add(aktuellerRaum.Finfo) ;
if aktuellerRaum.Fnorth <> nil then Memo1.Lines.add('---->Norden') ;
if aktuellerRaum.Fsouth <> nil then Memo1.Lines.add('---->Süden') ;
if aktuellerRaum.Feast <> nil then Memo1.Lines.add('---->Osten') ;
if aktuellerRaum.Fwest <> nil then Memo1.Lines.add('---->Westen') ;
if startRaum.Fnorth = nil then Memo1.Lines.add('attribute wurden nicht richtig festgelegt');


end;

procedure TForm1.Button1Click(Sender: TObject);
var eingabe : string;
begin
eingabe := edit1.Text ;
if (eingabe = 'Norden')and (aktuellerRaum.Fnorth <> nil) then aktuellerRaum := aktuellerRaum.Fnorth ;
if (eingabe = 'Süden')and (aktuellerRaum.Fsouth <> nil) then aktuellerRaum := aktuellerRaum.Fsouth ;
if (eingabe = 'Osten')and (aktuellerRaum.Feast <> nil) then aktuellerRaum := aktuellerRaum.Feast ;
if (eingabe = 'Westen')and (aktuellerRaum.Fwest <> nil) then aktuellerRaum := aktuellerRaum.Fwest ;

Memo1.clear ;
Memo1.Lines.add(aktuellerRaum.Finfo);

if aktuellerRaum.Fnorth <> nil then Memo1.Lines.add('---->Norden') ;
if aktuellerRaum.Fsouth <> nil then Memo1.Lines.add('---->Süden') ;
if aktuellerRaum.Feast <> nil then Memo1.Lines.add('---->Osten') ;
if aktuellerRaum.Fwest <> nil then Memo1.Lines.add('---->Westen') ;

end;

end.
Delphi-Quellcode:
unit URaum;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, JPEG;

type
  TRaum = class
   Fnorth,Fsouth,Feast,Fwest : TRaum;
   Finfo : string;
   procedure setAusgang(Anorth,Asouth,Aeast,Awest: TRaum; Ainfo :string);
   Constructor Create;

   private

   public

end;

implementation
Constructor TRaum.Create;
begin

end;

procedure TRaum.setAusgang(Anorth,Asouth,Aeast,Awest : TRaum ; Ainfo :string) ;
begin
self.Fnorth := Anorth;
self.Fsouth := Asouth;
self.Feast := Aeast;
self.Fwest := Awest;
self.Finfo := Ainfo;
end;
end.
Funktioniert gut soweit. Ich komm vermutlich jetzt wieder alleine weiter. Nochmal vielen Dank.

OlafSt 9. Jan 2015 13:16

AW: Hilfe mit Textadventure
 
Eine unschöne Sache ist da noch drin. Der leere constructor.

Konstruktoren dienen dazu, die einzelnen Felder des Objekts zu initialisieren. So, wie du es nun hast, gibt es ein Problem: Nach dem Aufruf von TRaum.Create; sind die Felder FNorth...FEast von TRaum mit "irgendwas" gefüllt. Ein Test auf nil (um festzustellen, das es in diese Richtung nicht weitergeht) kann also problemlos ergeben "da gehts weiter", denn "irgendwas" ist nicht nil. Du arbeitest dann mit ungültigen Daten, was direkt in eine Schutzverletzung mündet.

Nutze den Konstruktor also, um solche Probleme gar nicht erst entstehen zu lassen und setze die Felder von TRaum auf nil. Das erspart viel Ärger und womöglich aufwändige Fehlersucherei.

Der schöne Günther 9. Jan 2015 13:20

AW: Hilfe mit Textadventure
 
Das der leere Konstruktor unnötig ist stimmt zwar, die Begründung ist aber Quatsch. Die Felder sind definitiv mit
Delphi-Quellcode:
Nil
initialisiert. Das verwechselst du mit lokalen Variablen in einer Methode, die sind es nämlich nicht.

Sir Rufo 9. Jan 2015 13:30

AW: Hilfe mit Textadventure
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1286070)
Das der leere Konstruktor unnötig ist stimmt zwar, die Begründung ist aber Quatsch. Die Felder sind definitiv mit
Delphi-Quellcode:
Nil
initialisiert. Das verwechselst du mit lokalen Variablen in einer Methode, die sind es nämlich nicht.

So isses :thumb:

p80286 9. Jan 2015 13:42

AW: Hilfe mit Textadventure
 
Zitat:

Zitat von Sir Rufo (Beitrag 1286071)
Zitat:

Zitat von Der schöne Günther (Beitrag 1286070)
Das der leere Konstruktor unnötig ist stimmt zwar, die Begründung ist aber Quatsch. Die Felder sind definitiv mit
Delphi-Quellcode:
Nil
initialisiert. Das verwechselst du mit lokalen Variablen in einer Methode, die sind es nämlich nicht.

So isses :thumb:

Mal isses so, mal isses so, machen und dann weiß man was man hat.
(Dann gibt es auch kein "Oh, das hab' ich glaub' ich verwechselt")

Gruß
K-H

Sir Rufo 9. Jan 2015 13:45

AW: Hilfe mit Textadventure
 
Lokale Variablen werden nicht initialisiert, das sollte bekannt sein.
Record Felder mit nicht gemanagten Typen, sind nicht initialisiert, sollte auch bekannt sein.
Der Rest ist initialisiert.

Was ist daran mal so mal so?


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:47 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz