Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Zwei Fragen zum ersten Programm (https://www.delphipraxis.net/145748-zwei-fragen-zum-ersten-programm.html)

Bausch 7. Jan 2010 16:39


Zwei Fragen zum ersten Programm
 
Hey Leute,
ich programmier gerade mit Delphi 6 mein erstes richtiges Programm, sollte so ein Monopoly-Verschnitt werden^^.
Aufjedenfall komme ich bei zwei Problemen nicht weiter:
1. Hier geht es um das "Runden-drehen". Ich habe 16 Felder momentan, starte beim 1. und springe vom 16. wieder auf das 1., klar wie Monopoly halt. Ich habe das ganze zunächst provisorisch gelöst, indem ich, sobald das aktuelle Feld des Spielers über 16 geht, das ganze minus 16 subtrahiert wird, und er sozusagen von 17-16=1 wieder startet.
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
Wuerfel2:=1;
end;

procedure TForm1.BtWuerfelClick(Sender: TObject);
var i:integer;
begin
For i:=1 To 16 Do
      begin
      Felder[i].Visible:=false;
      end; //alle Felder werden unsichtbar

Wuerfel1:=random(6)+1;
    aktFeld:= Wuerfel1 + Wuerfel2 ;
    Felder[aktFeld].Visible:= true;
    Wuerfel2:= aktFeld;

    If (aktFeld > 16)
        then
           begin
           aktFeld:=aktFeld - 16;
           Felder[aktFeld].Visible:= true;
           Gekauft[aktFeld].Visible:= false;
           aktBetrag:= aktBetrag + 100; //Geh über Los(+100)
           FEGeld1.Value:= aktBetrag;
           end ;

...
Das dumme ist nur, dass, wenn es in die dritte Runde geht, das [aktFeld] praktisch über 32 geht, das Programm streikt. Ist ja auch klar, da dann das [aktFeld] 17 wär und es dieses nicht gibt. Wie löse ich dieses Problem?

2. Dass man Felder kaufen kann, habe ich mittlerweile auch implementiert (ein Gekauft-Feld wird dann sichtbar). Nun arbeite ich daran, dass der Spieler bezahlen muss, wenn er wieder auf dieses Feld kommt. Das ist leider ein bisschen schwierig, da ich praktisch mit Gekauft[aktFeld].Visible:=true arbeite (Notiz: das Array besteht aus Images), und hier solche Verzweigungen a la If (Gekauft[aktFeld].Visible:=true) then... nicht funktionieren. Kein Boolean-Ausdruck gibt er mir hier aus. Wie könnte ich es nun schaffen, dass er mir irgendwie erkennt, dass des Feld bereits gekauft wurde? Gekauften Feldern eine eigene Variable zuweisen?

Ich hoffe ihr könnt mir helfen, wie gesagt: Mein erstes Programm^^. Seid also nicht böse, wenn das ein oder andere doof erscheint ;D

Medium 7. Jan 2010 16:47

Re: Zwei Fragen zum ersten Programm
 
Willkommen in der :dp: !

Ich hab zunächst mal ein paar kleine Fragen zum Quellcode (-> Kommentare)
Delphi-Quellcode:
For i:=1 To 16 Do
      begin
      Felder[i].Visible:=false;
      end;

Wuerfel1:=random(6)+1;
    aktFeld:= Wuerfel1 + Wuerfel2 ; // Woher kommt Wuerfel2? Und müsste es nicht "aktFeld := aktFeld + Wuerfel1 + Wuerfel2;" heissen?
    Felder[aktFeld].Visible:= true;
    Wuerfel2:= aktFeld; // Hö?

    If (aktFeld > 16)
        then
           begin
           aktFeld:=aktFeld - 16; // Hier sollte der if-Zweig auch schon enden. aktFeld bleibt dann ja immer zwischen 1 und 16, wird also eigentlich nie 32.
           Felder[aktFeld].Visible:= true;
           Gekauft[aktFeld].Visible:= false;
           aktBetrag:= aktBetrag + 100; //Geh über Los(+100)
           FEGeld1.Value:= aktBetrag;
           end ;
Zum zweiten: "Gekauft[aktFeld].Visible := true/false". Das ":=" ist eine Zuweisung. Ein Vergleich machst du nur mit "=".

Matze 7. Jan 2010 16:53

Re: Zwei Fragen zum ersten Programm
 
Hallo, herzlich Willkommen!

Zitat:

Zitat von Bausch
1. Hier geht es um das "Runden-drehen". Ich habe 16 Felder momentan, starte beim 1. und springe vom 16. wieder auf das 1., klar wie Monopoly halt. Ich habe das ganze zunächst provisorisch gelöst, indem ich, sobald das aktuelle Feld des Spielers über 16 geht, das ganze minus 16 subtrahiert wird, und er sozusagen von 17-16=1 wieder startet.
[...]
Das dumme ist nur, dass, wenn es in die dritte Runde geht, das [aktFeld] praktisch über 32 geht, das Programm streikt. Ist ja auch klar, da dann das [aktFeld] 17 wär und es dieses nicht gibt. Wie löse ich dieses Problem?

Setze doch das Feld auf 1 anstelle 16 zu subtrahieren. Zum Zählen der Runden kannst du eine separate Variable nutzen. (Edit: Das hier ist Murks, du musst schon subtrahieren)

Delphi-Quellcode:
if aktFeld > 16 then
begin
  aktFeld := 1;
  inc(RundenNum); // oder RundenNum := RundenNum + 1;
end;
Zitat:

Zitat von Bausch
Kein Boolean-Ausdruck gibt er mir hier aus. Wie könnte ich es nun schaffen, dass er mir irgendwie erkennt, dass des Feld bereits gekauft wurde? Gekauften Feldern eine eigene Variable zuweisen?

Du kannst dafür ein Record anlegen, das ist im Prinzip eine Zusammenfassung mehrerer Variablen.

Delphi-Quellcode:
type
  TFeld: record
    Img: TImage;
    Gekauft: Boolean;
  end;

var
  Felder: array[1..16] of TFeld;
Dann kannst du so darauf zugreifen:

Delphi-Quellcode:
if Felder[aktFeld].Gekauft then
Und die Variablen natürlich beim Kaufen setzen etc.

Grüße, Matze

Edit: Das, was Medium geschrieben hat ist natürlich korrekt. So genau habe ich deinen Code nicht angesehen. Dann kommst du evtl. um das Record herum für den Anfang.
Edit 2: Ach jetzt verstehe ich, warum du 16 subtrahierst. Das musst du dann schon machen. ich bin grad bissl durcheinander. :stupid:

Bausch 7. Jan 2010 17:07

Re: Zwei Fragen zum ersten Programm
 
Zitat:

Zitat von Medium
Delphi-Quellcode:
Wuerfel1:=random(6)+1;
    aktFeld:= Wuerfel1 + Wuerfel2 ; // Woher kommt Wuerfel2? Und müsste es nicht "aktFeld := aktFeld + Wuerfel1 + Wuerfel2;" heissen?
    Felder[aktFeld].Visible:= true;
    Wuerfel2:= aktFeld; // Hö?

Habs jetzt noch editiert. Wuerfel2 ist am Anfang 1, heißt, der Spieler startet nicht aus dem nirgendwo, sondern auf Feld 1. Das aktFeld:= Wuerfel1 + Wuerfel2 soll bedeuten, dass der Spieler vom aktuellen Feld plus die neu gewürfelte Zahl springt, im folgenden wird ja das aktFeld als Wuerfel2 definiert.

Zitat:

[delphi] If (aktFeld > 16)
then
begin
aktFeld:=aktFeld - 16; // Hier sollte der if-Zweig auch schon enden. aktFeld bleibt dann ja immer zwischen 1 und 16, wird also eigentlich nie 32.
Felder[aktFeld].Visible:= true;
Gekauft[aktFeld].Visible:= false;
aktBetrag:= aktBetrag + 100; //Geh über Los(+100)
FEGeld1.Value:= aktBetrag;
end ;[delphi]
Das, was nach deinem Kommentar kommt, sorgt ja dafür, dass das Feld sichtbar wird, auf dem der Spieler nun steht. Und das mit aktBetrag:= aktBetrag + 100; //Geh über Los(+100)
FEGeld1.Value:= aktBetrag;
ist einfach nur das Geld, das man einzieht, wenn man über Los, in diesem Fall Feld 1, geht.

Zitat:

Zum zweiten: "Gekauft[aktFeld].Visible := true/false". Das ":=" ist eine Zuweisung. Ein Vergleich machst du nur mit "=".
Heißt das, If "Gekauft[aktFeld].Visible=true" then... müsste gehen? Z.B. If Gekauft[aktFeld].visible=true then showmessage('Schon gekauft'); ?

Matze 7. Jan 2010 17:11

Re: Zwei Fragen zum ersten Programm
 
Zitat:

Zitat von Bausch
Heißt das, If "Gekauft[aktFeld].Visible=true" then... müsste gehen? Z.B. If Gekauft[aktFeld].visible=true then showmessage('Schon gekauft'); ?

Besser ist es, "= true" ganz wegzulassen und einfach so zu schreiben:

Delphi-Quellcode:
if Gekauft[aktFeld].Visible then
  ShowMessage('Schon gekauft');
Wenn "Gekauft[aktFeld].Visible" nur dann "true" ist, wenn die Straße verkauft ist, dann geht es so, ja.

Bausch 7. Jan 2010 17:31

Re: Zwei Fragen zum ersten Programm
 
Super, das klappt jetzt ganz gut. Jetzt steht mir nur noch das erste Problem im Weg :?:
Ab Ende der zweiten Runde kommt die Fehlermeldung. Übrigens: Die Zeile Gekauft[aktFeld].Visible:= false; habe ich nur eingefügt, weil er mir komischerweise die Gekauft-Felder auch noch angezeigt hat, obwohl ich sie nicht gekauft habe. Zuvor war es nämlich auch so, dass er mir ab der zweiten Runde bei den Gekauft-Feldern weiter gemacht hat, sprich die normalen Felder waren unsichtbar, stattdessen ist er von einem Gekauft-Feld zum anderen gehüpft - Häh? ^^
Mit der oben erwähnten Zeile war das Problem gelöst, jedoch nicht die Fehlermeldung am Ende der 2. Runde...

Sir Rufo 7. Jan 2010 17:54

Re: Zwei Fragen zum ersten Programm
 
Warum eigentlich nicht so? Spart man sich doch das ganze IF Geraffel ...
Delphi-Quellcode:
aktFeld := ( aktFeld + Wuerfel - 1 ) MOD 16 + 1
Allerdings kann dieses wesentlich eleganter durch eine verkettete Liste dargestellt werden.
16 Feld-Instanzen, die einen Verweis auf den Nachfolger haben.

Die Instanz 1 zeigt auf 2
Die Instanz 2 zeigt auf 3
...
Die Instanz 15 zeigt auf 16
Die Instanz 16 zeigt auf 1

Und schon läuft das rund :mrgreen:

Bausch 7. Jan 2010 18:20

Re: Zwei Fragen zum ersten Programm
 
Zitat:

Zitat von Sir Rufo
Warum eigentlich nicht so? Spart man sich doch das ganze IF Geraffel ...
Delphi-Quellcode:
aktFeld := ( aktFeld + Wuerfel - 1 ) MOD 16 + 1

Ahh ok. Man muss erstmal auf sowas kommen^^ Auf jeden Fall funktionierts, vielen Dank :D

Zitat:

Allerdings kann dieses wesentlich eleganter durch eine verkettete Liste dargestellt werden.
16 Feld-Instanzen, die einen Verweis auf den Nachfolger haben.

Die Instanz 1 zeigt auf 2
Die Instanz 2 zeigt auf 3
...
Die Instanz 15 zeigt auf 16
Die Instanz 16 zeigt auf 1

Und schon läuft das rund :mrgreen:
Wie kann ich sowas anstellen? Macht das keinen Unterschied, wenn ich z.B. von Feld 1 auf Feld 4 spring?

implementation 7. Jan 2010 18:41

Re: Zwei Fragen zum ersten Programm
 
Lege erst einmal eine Klasse für ein Feld an:
Delphi-Quellcode:
type
  TFeld = class; // Prädeklaration
  TFeld = class
    // Dein Image
    Image: TImage;
    // Und hier der Verweis auf den Nachfolger
    Next: TFeld;
  end;
  TStrasse = class(TFeld)
    Gekauft: TImage;
    Name: string;
    Mietkosten: word;
  end;
  TEWWerk = class(TFeld)
    Gekauft: TImage;
    Name: string;
  end;
  TKnast = class(TFeld)
    NurzuBesuch: boolean;
  end;
  TLosFeld = class(TFeld);
  TPolizist = class(TFeld);

var
  aktFeld, erstesFeld, knastFeld: TFeld;

procedure TForm1.OnCreate(Sender:TObject);
var
  i: byte;
begin
  // Felder erstellen
  aktFeld := TLosFeld.Create;
  aktFeld.Image := TImage.Create;
  erstesFeld := aktFeld;
  for i := 0 to 14 do begin
    aktFeld.Next := TFeld.Create;
    aktFeld := aktFeld.next;
    aktFeld.Image := TImage.Create;
    aktFeld.Gekauft := TImage.Create;
  end;
  aktFeld.Next := erstesFeld;
  aktFeld := erstesFeld;
end;

procedure Ziehen(Augensumme:Byte);
begin
  for Augensumme := 1 to Augensumme do begin
    aktFeld := aktFeld.Next;
    if aktFeld is TLosFeld then Geld := Geld+100;
    if aktFeld is TKnast then TKnast(aktFeld).NurzuBesuch := true;
  end;
  if aktFeld is TPolizist then GeheInDenKnast;
  ...
end;

procedure GeheIndenKnast;
begin
  aktFeld := knastFeld;
  TKnast(aktFeld).NurZuBesuch := false;
end;
Der Code ist nicht getestet, er soll nur das Prinzip erklären.

Bausch 8. Jan 2010 11:12

Re: Zwei Fragen zum ersten Programm
 
Der Beitrag über mir scheint logisch zu sein, ich habs jedoch anderst gelöst. Hier z.B. die verschiedenen Miet-Beiträge:
Delphi-Quellcode:
 If (Gekauft[aktFeld1].Visible) then
      If (aktFeld1=1)or(aktFeld1=2)or(aktFeld1=3)or(aktFeld1=4)or(aktFeld1=5) then
        begin
        showmessage('schon vergeben -50');
        aktBetrag1:= aktBetrag1 - 50;
        FEGeld1.Value:= aktBetrag1;
        aktBetrag2:= aktBetrag2 + 50;
        FEGeld2.Value:= aktBetrag2;
        end
      else
         If (aktFeld1=6)or(aktFeld1=7)or(aktFeld1=8)or(aktFeld1=9) then
           begin
           showmessage('schon vergeben -100');
           aktBetrag1:= aktBetrag1 - 100;
           FEGeld1.Value:= aktBetrag1;
           aktBetrag2:= aktBetrag2 + 100;
           FEGeld2.Value:= aktBetrag2;
           end
         else
           If (aktFeld1=10)or(aktFeld1=11)or(aktFeld1=12)or(aktFeld1=13)or(aktFeld1=14) then
              begin
              showmessage('schon vergeben -150');
              aktBetrag1:= aktBetrag1 - 150;
              FEGeld1.Value:= aktBetrag1;
              aktBetrag2:= aktBetrag2 + 150;
              FEGeld2.Value:= aktBetrag2;
              end
            else
              If (aktFeld1=15)or(aktFeld1=16)or(aktFeld1=17)or(aktFeld1=18) then
                begin
                showmessage('schon vergeben -200');
                aktBetrag1:= aktBetrag1 - 200;
                FEGeld1.Value:= aktBetrag1;
                aktBetrag2:= aktBetrag2 + 200;
                FEGeld2.Value:= aktBetrag2;
                end;
Sieht auch für mich nach relativ viel Text aus - Kann man das irgendwie kürzen?
Ich hab jetzt auch einen zweiten Spieler eingeführt (sieht man auch an den verschiedenen Bezeichnungen), aber jetzt stehe ich vor dem Problem, dass ja nur einer Miete zahlen soll, wenn er auf das bereits gekaufte Feld kommt; nämlich der, der es nicht gekauft hat - der Mieter eben :D
Der, der es gekauft hat, muss momentan bei mir auch Miete zahlen, was ja dem Spielprinzip nicht entgegenkommt ;) Wie kann ich das nun einem bestimmten Spieler zuweisen?


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:31 Uhr.
Seite 1 von 2  1 2      

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