Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Ampelkreuzung (https://www.delphipraxis.net/172018-ampelkreuzung.html)

GoodGuyGreg 8. Dez 2012 09:47

Ampelkreuzung
 
Hey

Ich weiss, dass es zu dem thema schon mehrere threads gab, aber leider hat keiner davon mein Problem gelöst.

Also ich soll eine Ampelkreuzung Programmieren mit einem Timer und 4 ampeln habe aber folgendes Problem.
Delphi-Quellcode:
IF imlrot2.Visible=false
  then begin
imlgruen.Visible:=true  ;
imrgruen.Visible:=true   ;
imogruen.Visible:=false   ;
imugruen.Visible:=false    ;
imlgelb.Visible:=false      ;
imrgelb.Visible:=false       ;
imogelb.Visible:=false        ;
imugelb.Visible:=false         ;
imrrot.Visible:=false           ;
imlrot.Visible:=false            ;
imorot.Visible:=true             ;
imurot.Visible:=true               ;
imlrot2.Visible:=false              ;
imrrot2.Visible:=false               ;
imurot2.Visible:=false                ;
imorot2.Visible:=false                 ;
imlgelbrot.Visible:=false               ;
imrgelbrot.Visible:=false                ;
imugelbrot.Visible:=false                 ;
imogelbrot.Visible:=false ;
tiampel.Interval:=5000                     ;

end ;

 if imlgruen.visible=true
then begin ;
imlgruen.Visible:=false  ;
imrgruen.Visible:=false   ;
imogruen.Visible:=false   ;
imugruen.Visible:=faLSE    ;
imlgelb.Visible:=false      ;
imrgelb.Visible:=false       ;
imogelb.Visible:=false        ;
imugelb.Visible:=false         ;
imrrot.Visible:=false           ;
imlrot.Visible:=false            ;
imorot.Visible:=false              ;
imurot.Visible:=false               ;
imlrot2.Visible:=false              ;
imrrot2.Visible:=false               ;
imurot2.Visible:=false                ;
imorot2.Visible:=false                 ;
imlgelbrot.Visible:=true               ;
imrgelbrot.Visible:=true                ;
imugelbrot.Visible:=true                 ;
imogelbrot.Visible:=true
 end
    else if imogelbrot.Visible=true
then begin ;
imlgruen.Visible:=false  ;
imrgruen.Visible:=false   ;
imogruen.Visible:=true   ;
imugruen.Visible:=true    ;
imlgelb.Visible:=false      ;
imrgelb.Visible:=false       ;
imogelb.Visible:=false        ;
imugelb.Visible:=false         ;
imrrot.Visible:=true           ;
imlrot.Visible:=true            ;
imorot.Visible:=false              ;
imurot.Visible:=false               ;
imlrot2.Visible:=false              ;
imrrot2.Visible:=false               ;
imurot2.Visible:=false                ;
imorot2.Visible:=false                 ;
imlgelbrot.Visible:=false           ;
imrgelbrot.Visible:=false               ;
imugelbrot.Visible:=false                ;
imogelbrot.Visible:=false                 ;
Wenn ich die execute jezt ausführe springen alle ampeln Auf gelbrot und nicht wie es eig. seien sollte erst auf grün dann auf gelbrot und dann auf rot.
Wäre nett wenn mir jemand helfen könnte und sich die mühe macht meinen Quellcode zu lesen:-D

Sir Rufo 8. Dez 2012 10:11

AW: Ampelkreuzung
 
Wenn man jede Ampel für sich betrachtet, dann kann man diese zusammenfassen (ich habe jetzt ganz bewusst keine Ampelklasse angelegt, die natürlich noch besser wäre) und für die Steuerung (im Timer) erheblich leichter ansprechen.

Beispielhaft habe ich nur eine Ampel angelegt, die anderen können quasi per CopyPaste erstellt werden.

Delphi-Quellcode:
type
  TForm1 = class( TForm )
    Ampel1_Rot_Image : TImage;
    Ampel1_Gelb_Image : TImage;
    Ampel1_Gruen_Image : TImage;
    Timer1 : TTimer;
    procedure Timer1Timer( Sender : TObject );
  private
    FAmpel1_Status : Integer;
  public
    procedure Ampel1_SetStatus( Status : Integer );
    function Ampel1_GetStatus : Integer;
  end;

var
  Form1 : TForm1;

implementation

{$R *.dfm}
{ TForm1 }

function TForm1.Ampel1_GetStatus : Integer;
begin
  Result := FAmpel1_Status;
end;

procedure TForm1.Ampel1_SetStatus( Status : Integer );
begin
  FAmpel1_Status := Status;
  case Status of
    0 : // aus
      begin
        Ampel1_Rot_Image.Visible  := False;
        Ampel1_Gelb_Image.Visible := False;
        Ampel1_Gruen_Image.Visible := False;
      end;
    1 : // rot
      begin
        Ampel1_Rot_Image.Visible  := True;
        Ampel1_Gelb_Image.Visible := False;
        Ampel1_Gruen_Image.Visible := False;
      end;
    2 : // rot-gelb
      begin
        Ampel1_Rot_Image.Visible  := True;
        Ampel1_Gelb_Image.Visible := True;
        Ampel1_Gruen_Image.Visible := False;
      end;
    3 : // grün
      begin
        Ampel1_Rot_Image.Visible  := False;
        Ampel1_Gelb_Image.Visible := False;
        Ampel1_Gruen_Image.Visible := True;
      end;
    4 : // gelb
      begin
        Ampel1_Rot_Image.Visible  := False;
        Ampel1_Gelb_Image.Visible := True;
        Ampel1_Gruen_Image.Visible := False;
      end;
  end;
end;

procedure TForm1.Timer1Timer( Sender : TObject );
var
  LStatusNeu : Integer;
begin
  LStatusNeu := Ampel1_GetStatus;
  if LStatusNeu = 4
  then
    LStatusNeu := 1
  else
    LStatusNeu := LStatusNeu + 1;
  Ampel1_SetStatus( LStatusNeu );
end;

GoodGuyGreg 8. Dez 2012 10:12

AW: Ampelkreuzung
 
Ahh vielen Dank jezt hab ich's :D

DeddyH 8. Dez 2012 10:13

AW: Ampelkreuzung
 
Hallo und Willkommen in der DP :dp:,

fang doch erst einmal im Kleinen an. Eine Ampel kennt ja nur 4 Zustände, da bietet sich also ein eigener Datentyp dafür an.
Delphi-Quellcode:
type
  TAmpelzustand = (azGruen, azGelb, azRot, azRotGelb);
Bei jeder Schaltphase wird dieser Zustand dann im 1 erhöht bzw. auf Anfang zurückgesetzt. Wir lösen das jetzt auf die simpleste Art und Weise, auch wenn sie nicht ganz so elegant ist:
Delphi-Quellcode:
procedure TAmpel.NaechstePhase;
begin
  case Zustand of
    azGruen:
      Zustand := azGelb;
    azGelb:
      Zustand := azRot;
    azRot:
      Zustand := azRotGelb;
    azRotGelb:
      Zustand := azGruen;
  end;
  Anzeigen;
end;
In der "Anzeigen"-Methode werden nun also die Images/Shapes oder was auch immer aktualisiert. Versuch das nun zunächst mit einer einzigen Ampel umzusetzen, danach sind mehrere auch kein großes Problem mehr.
Übrigens: bitte nicht mit true oder false vergleichen, das kann u.U. in die Hose gehen, auch wenn manche Benutzer das nicht einsehen wollen.
Delphi-Quellcode:
if Dings = true then
wird einfach zu
Delphi-Quellcode:
if Dings then
und
Delphi-Quellcode:
if Dings = false then
wird zu
Delphi-Quellcode:
if not Dings then
[edit] Trotz roten Kastens gepostet, da Ansatz ähnlich, aber nicht gleich ;) [/edit]

Popov 8. Dez 2012 10:18

AW: Ampelkreuzung
 
Delphi-Quellcode:
  IF imlrot2.Visible=false then
  begin
    imlgruen.Visible:=true ; //<<<
    //...
    imogelbrot.Visible:=false ; //<<<
    tiampel.Interval:=5000 ;
  end ;

  if imlgruen.visible=true then
  begin ;
    imlgruen.Visible:=false ; //<<<
    //...
    imogelbrot.Visible:=true //<<<
  end
  else
  if imogelbrot.Visible=true then
  begin ;
    imlgruen.Visible:=false ; //<<<
    //...
    imogelbrot.Visible:=false ; //<<<
Wenn am Anfang imlrot2.Visible True ist, dann wird imlgruen.Visible True und imogelbrot.Visible False;

Bei der zweiten Anfrage ist imlgruen.Visible True, also werden imlgruen.Visible False und imogelbrot.Visible True. Und das war es dann.

generic 9. Dez 2012 11:19

AW: Ampelkreuzung
 
Da in der Software Entwicklung derzeit "Design-Patterns" sehr beliebt sind, könntest du für Fortbildungzwecke das "State-Pattern" anschauen.

Eine Ampel ist eine State-Maschine. Verschiedene Ampelphasen können nur in bestimmten Phasen enden.

Durch Patterns soll der Quelltext u.a. übersichtlicher werden.

http://de.wikipedia.org/wiki/Zustand...wurfsmuster%29
http://www.philipphauer.de/study/se/...tern/state.php

Sir Rufo 9. Dez 2012 12:28

AW: Ampelkreuzung
 
Zitat:

Zitat von generic (Beitrag 1194825)
Da in der Software Entwicklung derzeit "Design-Patterns" sehr beliebt sind, könntest du für Fortbildungzwecke das "State-Pattern" anschauen.

Eine Ampel ist eine State-Maschine. Verschiedene Ampelphasen können nur in bestimmten Phasen enden.

Durch Patterns soll der Quelltext u.a. übersichtlicher werden.

http://de.wikipedia.org/wiki/Zustand...wurfsmuster%29
http://www.philipphauer.de/study/se/...tern/state.php

Übersichtlicher ist hierbei nicht zu verwechseln mit weniger Code. Im Gegenteil es gibt mehr Code.
Der Vorteil ist aber, dass man die Gesamtproblematik zerlegt in kleine übersichtliche Häppchen (die einzelnen States).

Und je komplizierter der Sachverhalt umso mehr Vorteile bringt es.

Zum Vergleich mal FizzBuzz (Fun Code of the Week # 5 - Nick Hodges) in der simpelsten Version:
Delphi-Quellcode:
program FizzBuzz;

uses
  SysUtils, StrUtils;

var
  s: string;
  i: Integer;

begin

  for i := 1 to 100 do
    begin
      s := ifThen( i mod 3 = 0, 'Fizz', '' );
      s := IfThen( i mod 5 = 0, s + 'Buzz', s );
      WriteLn( IfThen( s = '', IntToStr( i ), s ) )
    end;

  ReadLn;
 
end.
und einmal mit dem StatePattern
Delphi-Quellcode:
program FizzBuzz_StatePattern;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  FizzBuzz in 'FizzBuzz.pas',
  FizzBuzzStates in 'FizzBuzzStates.pas';

var
  FizzBuzz : TFizzBuzz;

begin

  FizzBuzz := TFizzBuzz.Create;
  try

    FizzBuzz.Execute( 1, 100 );

  finally
    FizzBuzz.Free;
  end;

  Readln;

end.
Delphi-Quellcode:
unit FizzBuzz;

interface

type
  TCustomFizzBuzzState = class;
  TFizzBuzzStateClass = class of TCustomFizzBuzzState;

  TFizzBuzz = class
    private
      FIndex : Integer;
      FState : TCustomFizzBuzzState;
    protected
      procedure DoWriteIndex;
      procedure DoWriteString( const AString : string );
      procedure DoWriteEOL;
      procedure DoIncIndex;
      procedure DoSetState( AStateClass : TFizzBuzzStateClass );
    public
      procedure Execute( AIndex, ACount : Integer );
  end;

  TCustomFizzBuzzState = class
    private
      FContext : TFizzBuzz;
    protected
      procedure DoWriteIndex;
      procedure DoWriteString( const AString : string );
      procedure DoWriteEOL;
      procedure DoIncIndex;
      procedure DoSetState( AStateClass : TFizzBuzzStateClass );
    public
      constructor Create( AContext : TFizzBuzz );
      procedure Consume( AValue : Integer ); virtual; abstract;
  end;

implementation

uses
  FizzBuzzStates;

  { TFizzBuzzStateBase }

constructor TCustomFizzBuzzState.Create( AContext : TFizzBuzz );
begin
  inherited Create;
  FContext := AContext;
end;

procedure TCustomFizzBuzzState.DoIncIndex;
begin
  FContext.DoIncIndex;
end;

procedure TCustomFizzBuzzState.DoSetState( AStateClass : TFizzBuzzStateClass );
begin
  FContext.DoSetState( AStateClass );
end;

procedure TCustomFizzBuzzState.DoWriteEOL;
begin
  FContext.DoWriteEOL;
end;

procedure TCustomFizzBuzzState.DoWriteIndex;
begin
  FContext.DoWriteIndex;
end;

procedure TCustomFizzBuzzState.DoWriteString( const AString : string );
begin
  FContext.DoWriteString( AString );
end;

{ TFizzBuzz }

procedure TFizzBuzz.Execute( AIndex, ACount : Integer );
begin
  DoSetState( TFizzState );
  FIndex := AIndex;
  while FIndex < AIndex + ACount do
    begin
      FState.Consume( FIndex );
    end;
end;

procedure TFizzBuzz.DoIncIndex;
begin
  Inc( FIndex );
end;

procedure TFizzBuzz.DoSetState( AStateClass : TFizzBuzzStateClass );
begin
  if Assigned( FState )
  then
    FState.Free;

  FState := AStateClass.Create( Self );
end;

procedure TFizzBuzz.DoWriteEOL;
begin
  Writeln;
end;

procedure TFizzBuzz.DoWriteIndex;
begin
  write( FIndex );
end;

procedure TFizzBuzz.DoWriteString( const AString : string );
begin
  write( AString );
end;

end.
Delphi-Quellcode:
unit FizzBuzzStates;

interface

uses
  FizzBuzz;

type
  TStartState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TFizzState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TBuzzState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TFizzBuzzState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TNumberState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

  TEndLineState = class( TCustomFizzBuzzState )
  public
    procedure Consume( AValue : Integer ); override;
  end;

implementation

{ TStartState }

procedure TStartState.Consume( AValue : Integer );
begin
  DoSetState( TFizzState );
end;

{ TFizzState }

procedure TFizzState.Consume( AValue : Integer );
begin
  if AValue mod 3 = 0
  then
    begin
      DoWriteString( 'Fizz' );
      DoSetState( TFizzBuzzState );
    end
  else
    DoSetState( TBuzzState );
end;

{ TEndLineState }

procedure TEndLineState.Consume( AValue : Integer );
begin
  DoWriteEOL;
  DoIncIndex;
  DoSetState( TStartState );
end;

{ TBuzzState }

procedure TBuzzState.Consume( AValue : Integer );
begin
  if AValue mod 5 = 0
  then
    begin
      DoWriteString( 'Buzz' );
      DoSetState( TEndLineState );
    end
  else
    DoSetState( TNumberState );
end;

{ TNumberState }

procedure TNumberState.Consume( AValue : Integer );
begin
  DoWriteIndex;
  DoSetState( TEndLineState );
end;

{ TFizzBuzzState }

procedure TFizzBuzzState.Consume( AValue : Integer );
begin
  if AValue mod 5 = 0
  then
    begin
      DoWriteString( 'Buzz' );
    end;
  DoSetState( TEndLineState );
end;

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:17 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