![]() |
Magische 21
Hallo,
Ich habe versucht das Spiel "Die Magische 21 zu programmieren" Nur irgendwie funktioniert das nicht richtig. Hier der Quellcodeausschnitt:
Delphi-Quellcode:
Ich hoffe, dass mir jemand weiterhelfen kann!
procedure TForm1.Button1Click(Sender: TObject);
var wAugenzahl, wSumme, wVorher : real; begin wAugenzahl:=random(6)+1; wVorher:=StrToFloat(Edit1.Text); wSumme:=wVorher + wAugenzahl; ESumme.Text:=FloatToStr(wSumme); Edit1.Text:=FloatToStr(wAugenzahl); end MfG |
AW: Magische 21
Wie sollen wir dir weiterhelfen, wenn wir nicht wissen was irgendwie nicht funktioniert?
|
AW: Magische 21
War mein Fehler! :(
Das Programm würfelt beim ersten Klick eine Zahl zwischen 1 und 6 und gibt diese in zwei Fenstern aus. Beim nächsten Klick Würfelt er wieder eine Zahl gibt diese in einem Fenster aus und addiert sie mit der ersten und gibt das Ergebnis in einem Weiteren Fenster aus. Das funktioniert nur beim 1. und 2. Mal. danach nicht mehr. Das ist das Problem |
AW: Magische 21
Hallo Jan,
beim ersten Drüberschauen ist mir folgendes aufgefallen: 1. Da Augenzahlen beim Würfeln immer Ganzzahlen sind, solltest Du statt Real eher Integer als Datentyp nehmen. Entsprechend dann Befehle wie StrToInt verwenden! Falls es beim Randombefehl deshalb Probleme mit dem Datentyp gibt, einfach einen Trunc-Befehl um die rechte Seite legen (schneidet eine Kommazahl hinter dem Komma ab und macht sie zum Integer). 2. Die in der Prozedur verwendeten Variablen sind lokal definiert, d. h. wenn Du sie nicht explizit belegst, können darin Zufallswerte stehen. Du solltest die Variablen wSumme und wVorher global (im Variablendeklarationteil des Programms) definieren, da sie über die "Lebensdauer" eines Clickereignisses hinaus präsent sein sollen. wAugenzahl kann dagegen lokal definiert bleiben, da es eh bei jedem Click neu belegt wird. 3. Muss es nicht: wSumme := wSumme + wAugenzahl heißen? Hoffe das hilft Dir! |
AW: Magische 21
Zitat:
|
AW: Magische 21
Nein, bitte nicht global ... vor allem dann, wenn es nicht notwendig ist.
Für das Spiel benötigt man einen Würfel (TDice) und einen Spieler (TPlayer) die man wie folgt definieren kann
Delphi-Quellcode:
und für das Spiel dann so benutzt
unit Game;
interface type TDice = class private FEyes : Integer; protected procedure SetEyes( const Value : Integer ); public constructor Create; procedure Roll; virtual; property Eyes : Integer read FEyes; end; TPlayer = class private FSum : Integer; public procedure RollDice( ADice : TDice ); virtual; property Sum : Integer read FSum; end; TStandardDice = class( TDice ) public procedure Roll; override; end; implementation { TDice } constructor TDice.Create; begin inherited; Roll; end; procedure TDice.Roll; begin end; procedure TDice.SetEyes( const Value : Integer ); begin FEyes := Value; end; { TPlayer } procedure TPlayer.RollDice( ADice : TDice ); begin ADice.Roll; FSum := FSum + ADice.Eyes; end; { TStandardDice } procedure TStandardDice.Roll; begin inherited; SetEyes( Random( 6 ) + 1 ); end; end.
Delphi-Quellcode:
und schon programmiert man so, wie das Spiel im wahren Leben auch funktioniert.
unit Main_ViewU;
interface uses Game, Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TMain_View = class( TForm ) DiceEyes_Label : TLabel; PlayerSum_Label : TLabel; RollDice_Button : TButton; procedure RollDice_ButtonClick( Sender : TObject ); procedure FormCreate( Sender : TObject ); procedure FormDestroy( Sender : TObject ); procedure FormShow( Sender : TObject ); private FDice : TDice; FPlayer : TPlayer; procedure ShowPlayer( APlayer : TPlayer ); procedure ShowDice( ADice : TDice ); public end; var Main_View : TMain_View; implementation {$R *.dfm} { TForm1 } procedure TMain_View.FormCreate( Sender : TObject ); begin FDice := TStandardDice.Create; FPlayer := TPlayer.Create; end; procedure TMain_View.FormDestroy( Sender : TObject ); begin FPlayer.Free; FDice.Free; end; procedure TMain_View.FormShow( Sender : TObject ); begin ShowPlayer( FPlayer ); ShowDice( FDice ); end; procedure TMain_View.RollDice_ButtonClick( Sender : TObject ); begin FPlayer.RollDice( FDice ); ShowDice( FDice ); ShowPlayer( FPlayer ); end; procedure TMain_View.ShowDice( ADice : TDice ); begin DiceEyes_Label.Caption := IntToStr( ADice.Eyes ); end; procedure TMain_View.ShowPlayer( APlayer : TPlayer ); begin PlayerSum_Label.Caption := IntToStr( APlayer.Sum ); end; end. Der Spieler nimmt einen Würfel und würfelt
Delphi-Quellcode:
FPlayer.RollDice( FDice );
|
AW: Magische 21
Geht das nicht auch ein bisschen einfacher?
|
AW: Magische 21
Zitat:
|
AW: Magische 21
Welche Komponenten brauche ich denn für das Programm? (Label, edititierfenster...)
|
AW: Magische 21
Zitat:
Delphi-Quellcode:
2 Label und 1 Button (ordentlich benannt;))
TMain_View = class( TForm )
DiceEyes_Label : TLabel; PlayerSum_Label : TLabel; RollDice_Button : TButton; |
AW: Magische 21
@Sir Rufo
Deine Lösung ist sicher fachmännisch, ich hatte aber bei meiner Antwort versucht, den offenbaren Kenntnisstand des Fragestellers mit einzubeziehen. Man kann schlecht alles auf einmal erklären.:-D |
AW: Magische 21
Zitat:
|
AW: Magische 21
Du kannst auch einfach deinen Original-Code nehmen und wvorher aus ESumme und nicht Edit1 beziehen. Ansonsten war dein Code schon ganz richtig und der Aufgabe völlig angemessen.
DIe Verwendung von Integer statt real und StrToInt/IntToStr statt der Float-Funktionen wurde ja schon angesprochen. |
AW: Magische 21
Ach ja, und für globale Variablen besteht kein Anlass, da du die relevanten Daten ja schon in den Edit-Feldern speicherst.
Natürlich kann man das Problem auch komplexer oder mit unterschiedlichen Paradigma lösen. Aber wenn der ganze relevante Code in eine Handvoll Zeilen im Button-Click Event passt, ist jedes andere Vorgehen Overkill. Etwas anderes ist es allerdings, wenn das Projekt erweiterbar sein soll, aber dann fehlen dazu die Spezifikationen. Auch wenn du objektorientierte Programmierung lernen willst, kann man das natürlich auch entsprechend lösen. Aber dafür gibt es bessere Beispiele. |
AW: Magische 21
Auch auf die Gefahr hin, der böse zu sein..
Aber ich glaube es hilft ihm mehr, einfach mal zu zeigen, wie der Code umgeschrieben ausschaut (also Integer, statt real)
Delphi-Quellcode:
SirRufo´s Ausführung ist natürlich die Profi-Ausführung (wenn man das so sagen darf)
procedure TForm1.Button1Click(Sender: TObject);
var wAugenzahl: Integer; wSumme : Integer; wVorher : Integer; begin wAugenzahl := random(6) + 1; wVorher := StrToInt(Edit1.Text); wSumme := wVorher + wAugenzahl; ESumme.Text := IntToStr(wSumme); Edit1.Text := IntToStr(wAugenzahl); end; procedure TForm1.FormCreate(Sender: TObject); begin Randomize; end; [Edit] Delphi7 kennt schon "TryStrToInt" Dann würde auch folgende Fehlerbehandlung gehen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var wAugenzahl: Integer; wSumme : Integer; wVorher : Integer; begin If not TryStrtoInt(Edit1.Text, wVorher) then begin ShowMessage('Edit1 beinhaltet keine Zahl!'); exit; end; wAugenzahl := random(6) + 1; wSumme := wVorher + wAugenzahl; ESumme.Text := IntToStr(wSumme); Edit1.Text := IntToStr(wAugenzahl); end; |
AW: Magische 21
Randomize - Reposition the Random number generator next value
randomize; //z.B. in FormCreate einfügen ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:51 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