![]() |
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:
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.
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 ; Wäre nett wenn mir jemand helfen könnte und sich die mühe macht meinen Quellcode zu lesen:-D |
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; |
AW: Ampelkreuzung
Ahh vielen Dank jezt hab ich's :D
|
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:
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:
type
TAmpelzustand = (azGruen, azGelb, azRot, azRotGelb);
Delphi-Quellcode:
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.
procedure TAmpel.NaechstePhase;
begin case Zustand of azGruen: Zustand := azGelb; azGelb: Zustand := azRot; azRot: Zustand := azRotGelb; azRotGelb: Zustand := azGruen; end; Anzeigen; end; Ü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:
wird einfach zu
if Dings = true then
Delphi-Quellcode:
und
if Dings then
Delphi-Quellcode:
wird zu
if Dings = false then
Delphi-Quellcode:
[edit] Trotz roten Kastens gepostet, da Ansatz ähnlich, aber nicht gleich ;) [/edit]
if not Dings then
|
AW: Ampelkreuzung
Delphi-Quellcode:
Wenn am Anfang imlrot2.Visible True ist, dann wird imlgruen.Visible True und imogelbrot.Visible False;
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 ; //<<< Bei der zweiten Anfrage ist imlgruen.Visible True, also werden imlgruen.Visible False und imogelbrot.Visible True. Und das war es dann. |
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. ![]() ![]() |
AW: Ampelkreuzung
Zitat:
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 ( ![]()
Delphi-Quellcode:
und einmal mit dem StatePattern
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.
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 12:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz