Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Zahlenraten-Programm: Zahlenbereich vom User frei wählbar?


Anka - Mo 06.06.11 10:51
Titel: Zahlenraten-Programm: Zahlenbereich vom User frei wählbar?
Hallo Leute,
habe gerade ein kleines Zahlenratenprogramm programmiert und wollte eigentlich den Zahlenbereich, in welchem der Computer sich eine Zahl ausdenkt, die der User erraten muss, vom User durch ein Editfeld frei wählbar machen.
Dabei bin ich aber auf das Problem gestoßen, dass ich die Zufallszahl bei FormCreate erstellen lassen muss, weil sonst bei jedem neuen Klick auf den Button Raten eine neue Zufallszahl erzeugt wird.
Mein Code sieht momentan so aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  Zufallszahl:= Random(StrToInt(EdtZahlenbereich.Text))+1;
end;


Allerdings kann der User vor Programmstart natürlich keinen Zahlenbereich angeben -.-

Möchte eigentlich aus optischen Gründen nicht noch einen Button für das Zahlenbereichbestätigen erstellen.
Irgendwer eine Idee, wäre super :)

Liebe Grüße
Anka

Moderiert von user profile iconChristian S.: Delphi-Tags hinzugefügt
Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Di 07.06.2011 um 14:49


MaxWurzel - Mo 06.06.11 11:03

Benutze das OnChange Ereignis des Editfeldes.


zuma - Mo 06.06.11 11:04

oder das onExit des Editfeldes
(wenn Feld verlassen und Bereich geändert, dann neu Random, usw., sonst nix machen)


Anka - Mo 06.06.11 20:33

wie genau funktionieren die beiden Ereignisse bzw. welchen Code müsste ich verwenden?
Reicht es, wenn ich einfach
Zufallszahl:=Random(StrToInt(EdtZahlenbereich.Text));
in die procedure schreibe?

Ich stehe noch relativ am Anfang meiner Delphi-Karriere, also bitte vereziht mir solche (wahrscheinlich) sehr einfachen Fragen ;)


Yogu - Mo 06.06.11 20:37

user profile iconAnka hat folgendes geschrieben Zum zitierten Posting springen:
wie genau funktionieren die beiden Ereignisse bzw. welchen Code müsste ich verwenden?

Wenn du damit fragen willst, wie du die Prozeduren für die Ereignisse erstellen kannst: Einfach im Objektinspektor auf Ereignisse schalten, die Namen raussuchen und doppelklicken. Die dann erstellte Prozedur wird immer dann ausgeführt, wenn das Ereignis auftritt.

user profile iconAnka hat folgendes geschrieben Zum zitierten Posting springen:
Reicht es, wenn ich einfach
Zufallszahl:=Random(StrToInt(EdtZahlenbereich.Text));
in die procedure schreibe?

Ich stehe noch relativ am Anfang meiner Delphi-Karriere, also bitte vereziht mir solche (wahrscheinlich) sehr einfachen Fragen ;)

Das dürfte wahrscheinlich schon funktionieren, aber es hängt auch vom restlichen Code ab. Probier es doch einfach mal aus - genau das ist am Anfang (und auch später) wichtig.


Anka - Mo 06.06.11 20:59

Zitat:
Wenn du damit fragen willst, wie du die Prozeduren für die Ereignisse erstellen kannst: Einfach im Objektinspektor auf Ereignisse schalten, die Namen raussuchen und doppelklicken. Die dann erstellte Prozedur wird immer dann ausgeführt, wenn das Ereignis auftritt.


Nicht ganz, soweit komme ich glücklicherweise ;) Ich meinte eher, was die Ereignisse OnChange und OnExit jedes für sich machen, bei OnClick ist beispielsweise das "Draufklicken" angesprochen, etc.


Ok, irgendwas mache ich glaube ich gerade richtig falsch, die Zufallszahl wird nicht im richtigen Zahlenbereich erzeugt. Mein Code sieht wie folgt aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
implementation

{$R *.dfm}
var Zufallszahl, Ratezahl, OptimaleZahl: Integer; //globale Variablen


procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ShowMessage ('Um ein neues Spiel zu starten, geben Sie bitte einen Zahlenbereich ein und drücken Sie den Neu-Button');
end;


procedure TForm1.BtnRatenClick(Sender: TObject);
begin
  Ratezahl:= StrToInt(EdtRaten.Text);

  if Ratezahl = Zufallszahl then
    LblErgebnis.Caption:= 'Richtig geraten!'
    else if Ratezahl < Zufallszahl then
      LblErgebnis.Caption:= 'Die Zahl ist zu klein!'
      else if Ratezahl > Zufallszahl then
        LblErgebnis.Caption:= 'Die Zahl ist zu groß!';
end;

procedure TForm1.EdtZahlenbereichChange(Sender: TObject);
begin
  Zufallszahl:=Random(StrToInt(EdtZahlenbereich.Text))+1;
end;


Moderiert von user profile iconMartok: Delphi-Tags hinzugefügt


HenryHux - Mo 06.06.11 21:05

Das Problem ist hier, dass du bei jeder neuen Eingabe eine neue Zufallszahl anlegst.
Willst du, dass der Benutzer mehrere Versuche hat?


Anka - Mo 06.06.11 21:11

jop :)


HenryHux - Mo 06.06.11 21:15

Dann lege doch eine neue Variable an, die speichert wieviele Versuche er schon hatte.
Wenn er x-Versuche hatte, dann machst du halt eine neue Variable.

lg


Anka - Mo 06.06.11 21:18

Ich glaube ich stehe gerade auf dem Schlauch :)

Wenn ich jetzt eine neue Variable mit der Anzahl der bisherigen Versuche erstelle, löst das doch nicht mein Problem, dass ich bei jedem neuraten eine neue Zufallszahl erzeuge, oder=
Steht der Randombefehl eigentlich in meinem Code an der richtigen Stelle?


HenryHux - Mo 06.06.11 21:22

user profile iconAnka hat folgendes geschrieben Zum zitierten Posting springen:

Steht der Randombefehl eigentlich in meinem Code an der richtigen Stelle?


Nein.

Mache den Random Befehle doch auf den Button Click!
Wenn die Versuche = 0 sind oder = x dann wird eine neue erzeugt.
Ansonsten bleibt die Alte.


Anka - Mo 06.06.11 21:36


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
implementation

{$R *.dfm}
var Zufallszahl, Versuche, Ratezahl, OptimaleZahl: Integer; //globale Variablen


procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ShowMessage ('Um ein neues Spiel zu starten, geben Sie bitte einen Zahlenbereich ein und drücken Sie den Neu-Button');
  Veruche :=0;
end;


procedure TForm1.BtnRatenClick(Sender: TObject);
begin 
  
  Inc(Versuche); 

  if Versuche 10then
    Zufallszahl:= Random(StrToInt(EdtZahlenbereich.Text))+1;  

  Ratezahl:= StrToInt(EdtRaten.Text);

  if Ratezahl = Zufallszahl then
    LblErgebnis.Caption:= 'Richtig geraten!'
    else if Ratezahl < Zufallszahl then
      LblErgebnis.Caption:= 'Die Zahl ist zu klein!'
      else if Ratezahl > Zufallszahl then
        LblErgebnis.Caption:= 'Die Zahl ist zu groß!';
end;


Ok, Änderungen übernommen, aber wie wird jetzt bei Programmstart eine neue Zufallszahl erzeugt?


HenryHux - Mo 06.06.11 21:55

So klappt das nicht, du erzeugst ja immernoch immer neue Zahlen.



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
implementation

{$R *.dfm}
var Zufallszahl, Versuche, Ratezahl, OptimaleZahl: Integer; //globale Variablen


procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ShowMessage ('Um ein neues Spiel zu starten, geben Sie bitte einen Zahlenbereich ein und drücken Sie den Neu-Button');
  Zufallszahl := Random(StrToInt(EdtZahlenbereich.Text))+1;
  Versuche := 0;
end;


procedure TForm1.BtnRatenClick(Sender: TObject);
begin 
  if (Versuche in [010]) then begin
    Versuche := 0;
    Zufallszahl := Random(StrToInt(EdtZahlenbereich.Text))+1
  end;

  Inc(Versuche); 

  Ratezahl:= StrToInt(EdtRaten.Text);

  if Ratezahl = Zufallszahl then begin
    LblErgebnis.Caption:= 'Richtig geraten!';
    Versuche := 0;
  end
    else if Ratezahl < Zufallszahl then
      LblErgebnis.Caption:= 'Die Zahl ist zu klein!'
      else if Ratezahl > Zufallszahl then
        LblErgebnis.Caption:= 'Die Zahl ist zu groß!';
end;


So sollte es klappen.

lg


der organist - Di 07.06.11 00:44

user profile iconHenryHux hat folgendes geschrieben Zum zitierten Posting springen:
Das Problem ist hier, dass du bei jeder neuen Eingabe eine neue Zufallszahl anlegst.
Willst du, dass der Benutzer mehrere Versuche hat?


- wo bitte wird bei jeder Eingabe die Zufallszahl verändert?

Das passiert erst im letzen Codebeispiel...

- mehrere Versuche hat der Spieler auch sonst, nur zum mitzählen brauchst du ne Variable


HenryHux - Di 07.06.11 07:10

user profile iconder organist hat folgendes geschrieben Zum zitierten Posting springen:

- wo bitte wird bei jeder Eingabe die Zufallszahl verändert?

hier?


Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.EdtZahlenbereichChange(Sender: TObject);
begin
  Zufallszahl:=Random(StrToInt(EdtZahlenbereich.Text))+1;
end;


OT: Wieso klappen Tags nicht mehr beim Klicken?


der organist - Di 07.06.11 08:16

das ist doch aber beim Edit für die Eingabe der Zufallszahl. Die Eingabe für das Raten geschieht doch in einem anderen Editfeld...?

user profile iconAnka hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
Wenn du damit fragen willst, wie du die Prozeduren für die Ereignisse erstellen kannst: Einfach im Objektinspektor auf Ereignisse schalten, die Namen raussuchen und doppelklicken. Die dann erstellte Prozedur wird immer dann ausgeführt, wenn das Ereignis auftritt.


Nicht ganz, soweit komme ich glücklicherweise ;) Ich meinte eher, was die Ereignisse OnChange und OnExit jedes für sich machen, bei OnClick ist beispielsweise das "Draufklicken" angesprochen, etc.


Ok, irgendwas mache ich glaube ich gerade richtig falsch, die Zufallszahl wird nicht im richtigen Zahlenbereich erzeugt. Mein Code sieht wie folgt aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
implementation

{$R *.dfm}
var Zufallszahl, Ratezahl, OptimaleZahl: Integer; //globale Variablen


procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ShowMessage ('Um ein neues Spiel zu starten, geben Sie bitte einen Zahlenbereich ein und drücken Sie den Neu-Button');
end;


procedure TForm1.BtnRatenClick(Sender: TObject);
begin
  Ratezahl:= StrToInt(EdtRaten.Text);

  if Ratezahl = Zufallszahl then
    LblErgebnis.Caption:= 'Richtig geraten!'
    else if Ratezahl < Zufallszahl then
      LblErgebnis.Caption:= 'Die Zahl ist zu klein!'
      else if Ratezahl > Zufallszahl then
        LblErgebnis.Caption:= 'Die Zahl ist zu groß!';
end;

procedure TForm1.EdtZahlenbereichChange(Sender: TObject);
begin
  Zufallszahl:=Random(StrToInt(EdtZahlenbereich.Text))+1;
end;


Yogu - Di 07.06.11 15:04

user profile iconAnka hat folgendes geschrieben Zum zitierten Posting springen:
Ok, irgendwas mache ich glaube ich gerade richtig falsch, die Zufallszahl wird nicht im richtigen Zahlenbereich erzeugt.

Das war doch das ursprüngliche, noch ungelöste Problem. In welchem Bereich liegen die Zufallszahlen denn?


zuma - Di 07.06.11 15:55

user profile iconAnka hat folgendes geschrieben Zum zitierten Posting springen:
wie genau funktionieren die beiden Ereignisse bzw. welchen Code müsste ich verwenden?
Reicht es, wenn ich einfach
Zufallszahl:=Random(StrToInt(EdtZahlenbereich.Text));
in die procedure schreibe?

Ich stehe noch relativ am Anfang meiner Delphi-Karriere, also bitte vereziht mir solche (wahrscheinlich) sehr einfachen Fragen ;)


wenn du mal das aus dem englischen übersetzt, wird eigtl. schon klar, was es mit den ereignissen auf sich hat.
onchange = bei Änderung = tritt auf, wenn das Feld geändert wird
onexit = bei Verlassen = tritt auf, wenn das Feld den Focus verliert

Um nur dann eine neue Zufallszahl zu generieren, wenn die Eingabe sich verändert, merkst du dir einfach immer die letzte Eingabe und benutzt die dann zum Vergleichen. So wird keine neue Zufallszahl erzeugt, wenn man einfach nur das Feld verlässt, ohne zu ändern (z.b. beim 'durchtabben').

ich empfehle dir mal, das beim onExit zu machen


Delphi-Quelltext
1:
2:
3:
4:
5:
if (AlterZahlenBereich <> StrToInt(EdtZahlenBereich.Text)) then
begin
 Zufallszahl        := Random(StrToInt(EdtZahlenbereich.Text))+1;
 AlterZahlenBereich := StrToInt(EdtZahlenBereich.Text); 
end;


n1con - Do 23.06.11 13:44

Ich hab dir das jetzt mal zusammengefasst. Was wichtig ist, du musst die Variable Zufallszahl global deklarieren. Außerdem reicht es wenn du sie nur einmal im OnCreate Ereignis im Bereich Random(StrToInt(EdtZahlenbereich.Text))+1 generierst. Jetzt kannst du jedes mal im OnExit Ereignis des Edit Feldes das OnCreate Ereignis aufrufen und fertig. Ich häng dir mal meine Version an, dann siehst du wie ich es meine.

LG n1con