Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - kleines lottoprogramm erstellen


noo.bee - Mi 21.04.10 19:36
Titel: kleines lottoprogramm erstellen
ich möchte gern für mich ein kleines lottotool schreiben.
ich habe mal ganz einfach angefangen und mir einfach n FORM geöffnet. nun stellt sich mir die überlegung ob es sinnvoll ist, 49 EDITs im form zu platzieren oder vllt eine radiogroup. allerdings kann man ja bei einer radiogroup nur einwas auswählen. ich bräuchte aber 6 auswahlmöglichkeiten.

danach natürlich noch die frage, was sich einfacher speichern lässt. also 49 EDITs oder die radiogroup ? und ich muss ja noch vergleichen können. also die mit gezogenen zahlen ;)

bevor ich jetzt anfange meinen anfängercode zu schreiben, wolle ich erst mal eure gedanken dazu hören. bitte kein fachchinesisch :p


elundril - Mi 21.04.10 22:28

Warum brauchst du 49 Edits? Ist bei Lotto nicht 6 aus 49 bzw 6 aus 45 oder sonst was? Demnach interessieren dich ja eigentlich nur 6 Zahlen, oder?

lg elundril


noo.bee - Mi 21.04.10 22:55

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
Warum brauchst du 49 Edits?


ja stimmt, ich brauche entweder nur 6 EDITs in die ich meine Zahlen eintrage oder ne 49er RADIOGROUP in der ich 6 felder anklicken kann. denkfehler :(


Xentar - Mi 21.04.10 23:00

Wieso Radiogroup? Da kann man doch nur eins auswählen..
Wenn überhaupt, dann Checkboxen.


elundril - Do 22.04.10 00:17

also ich würde am ehesten zu 6 editfeldern raten, oder zu einer Listbox. Da kann man auch schön einen vorkommenscheck machen.

lg elundril


martin300 - Do 22.04.10 09:48

user profile iconnoo.bee hat folgendes geschrieben Zum zitierten Posting springen:
ich möchte gern für mich ein kleines lottotool schreiben.

Welche Funktionalität soll das Programm haben? Tipps berechnen? oder?


jaenicke - Do 22.04.10 09:55

Das sieht schon sehr nach einem typischen Beispiel für eine selbst gezeichnete Oberfläche aus. Das spart die ganzen visuellen Komponenten und lässt sich auch sehr viel besser im Design verändern.

Ein Beispiel dafür ist mein Periodensystem (wobei dein Lotto Programm natürlich deutlich einfacher ist):
http://www.delphi-forum.de/viewtopic.php?p=557541


noo.bee - Do 22.04.10 17:01

Zitat:
Welche Funktionalität soll das Programm haben? Tipps berechnen? oder?

ich möchte nur für mich n kleines programm, in das ich meine tips eintrage. unten gibts dann nochmal EDITs, in welche ich die aktuellen zahlen der ziehung eintrage. dann will ich, dass bei meinen tips die hervorgehoben werden, welche die treffer sind...
also eben nur was einfaches kleines zum anfang ;)

erweitern oder so kann ich später immer noch :D erstmal muss das "einfache" funktionieren


Hidden - Do 22.04.10 19:00

Hi :)

In Checkboxen könnte man beliebig viele Einträge anklicken, mit Radiobutton jeweils nur einen - beides falsch.

Wenn es ein größere Projekt werden soll, kannst du dir später überlegen, auf etwas selbstgezeichnetes umzusteigen.

Eintippen ist blöd, insofern würde ich wirklich 49 Checkboxen nehmen. Die kannst du entweder dynamisch(im Quelltext) erzeugen, oder auf das Formular ziehen.

In jedem Fall kannst du sie nachher über FindComponent() ansprechen: (FindComponent('Checkbox' + IntToStr(i)) as TCheckbox).Checked := ..

Jetzt kann jede dieser Checkboxen ja eine Methode "OnCheck(Sender: TObject)" haben; diese würde ich nutzen, und eine Integervariable entsprechend um eins erhöhen, wenn gescheckt bzw. um eins absenken, wenn unchecked wird. So kannst du immer kontrollieren, ob denn nun genügend Boxen gecheckt sind.

lg,


noo.bee - Do 22.04.10 19:42

Zitat:
Eintippen ist blöd, insofern würde ich wirklich 49 Checkboxen nehmen. Die kannst du entweder dynamisch(im Quelltext) erzeugen, oder auf das Formular ziehen.

In jedem Fall kannst du sie nachher über FindComponent() ansprechen: (FindComponent('Checkbox' + IntToStr(i)) as TCheckbox).Checked := ..

Jetzt kann jede dieser Checkboxen ja eine Methode "OnCheck(Sender: TObject)" haben; diese würde ich nutzen, und eine Integervariable entsprechend um eins erhöhen, wenn gescheckt bzw. um eins absenken, wenn unchecked wird. So kannst du immer kontrollieren, ob denn nun genügend Boxen gecheckt sind.

schön erklärt ;) aber fürn anfänger nich sooo verständlich :p zumindest nicht für mich :D

ich hab jetzt erst mal 6 EDITs erstellt für den 1. tip und nochmals 6 EDITs wo die akt. lottozahlen reinkommen. mein ansatz war jetzt dieser:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Button1Click(Sender: TObject);
begin
Treffer1 := 0;
if edit80.Text = edit1.Text then inc (Treffer1); //edit80 = 1. akt. lottozahl
if edit80.Text = edit2.Text then inc (Treffer1); //edit1-6 = meine 1. tipreihe
if edit80.Text = edit3.Text then inc (Treffer1);
if edit80.Text = edit4.Text then inc (Treffer1);
if edit80.Text = edit5.Text then inc (Treffer1);
if edit80.Text = edit6.Text then inc (Treffer1);
Label5.Caption := inttostr(Treffer1);            //label5 = anzeige trefferanzahl
end;


nur ist das doch ziemlich viel tipparbeit. ich hatte erst

Delphi-Quelltext
1:
if edit80.Text = edit1.Text or edit2.Text or ... or edit6.Text then inc (Treffer1)                    

aber or darf ich da irgendwie nicht verwenden :(
also gehts etwas einfacher, um mir tipparbeit zu sparen ?


Hidden - Do 22.04.10 20:14

Hi :)

Kommt ja noch, kommt ja noch - erstmal muss das Programm geschrieben sein :P


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:
uses Math;

procedure TMainFrm.CheckBox1Click(Sender: TObject);
const
  CrossAddRemove: Array[0..1of String = ('machen!''entfernen!');
begin
  if (Sender as TCheckBox).Checked then
    Dec(FKreuze)  //Spieler muss ein Kreuz weniger machen
  else Inc(FKreuze);  //Spieler muss ein Kreuz mehr machen
  if FKreuze = 0 then begin  //labelBeschriftung 1: Lottoschein richtig
    labScheinOkay.Font.Color := clLime;
    labScheinOkay.Font.Style := [fsBold];
    labScheinOkay.Caption := 'Chance: 1 / 13.983.816';
  end else begin  //Labelbeschriftung 0: Lottoschein falsch
    labScheinOkay.Font.Color := clRed;
    labScheinOkay.Font.Style := [fsItalic];
    labScheinOkay.Caption := 'Sie müssen noch genau ' + IntToStr(Abs(FKreuze))
                           + ' Kreuze ' +
                           CrossAddRemove[IfThen(FKreuze > 001)];  //entweder 'kreuz machen' oder 'kreuz entfernen', je nachdem, ob zu viel oder zu wenig kreuze da sind.
  end;
end;

procedure TMainFrm.FormCreate(Sender: TObject);
var
  i: Integer;
  aCheckBox: TCheckBox;
begin
  FKreuze := 6;  //6 Kreuze fehlen auf dem lottoschein
  for i := 1 to 49 do begin  //für i=1..49 Checkboxen
    aCheckBox := (FindComponent('Checkbox' + IntToStr(i)) as TCheckBox);  //Checkbox auswählen
    aCheckBox.OnClick := self.CheckBox1Click;  //Wenn diese Checkbox gedrückt wird, wird die Anzahl der verbleibenden Kreuze angepasst
    aCheckBox.Caption := IntToStr(i);  //Der Text auf dieser Checkbox ist ihre Nummer.
  end;
end;


lg,


noo.bee - Do 22.04.10 20:26

what the hell ...

also ich trau mich ja gar nicht zu sagen, dass ich deinen code nicht nehmen will, weil das ja sicher ne menge arbeit war. aber ich versteh da leider nicht mal annähern 1% :D - naja ok, n bißchen mehr wie 1% isses schon.
dann doch lieber mit meinen umständlichen EDITs. die versteh ich noch :p
ich kann zwar grob erklären, was dein code so n bissi macht, aber mehr auch net. ich muss das erstmal sacken lassen ;)

im anhang meine idee mit meinem kleinen wissen :D


Hidden - Do 22.04.10 20:42

Hi :)

'tschuldigung, das war nur so schnell zusammengehackt, das geht gewöhnlicherweise nach "wenig tippen, bisschen kompliziertere Befehle". Hab's kommentiert.

Der Source war auch so gedacht, dass er nicht kopiert werden kann. :P Wenn mit den Kommentaren jetzt die wichtigen Zeilen klar werden, ist alles richtig. :D

lg,


noo.bee - Do 22.04.10 21:10

Zitat:
Der Source war auch so gedacht, dass er nicht kopiert werden kann. :P

kopieren wäre eh nicht gegangen, weil ich sowieso nicht weis, was wie wohin kopiert werden muss. ausserdem will ich ja MEIN programm erstellen :) ähm, also mit eurer hilfe :p

so, noch ne frage: ich hab jetzt 12 tipreihen mit je 6 tips (also nen kompletten lottoschein). wie speichere ich denn alle 72 EDITs in eine datei? den TSAVEDIALOG hab ich schon gefunden. und ich hab auch schon DEFAULTEXT in *.txt geändert. wenn ich jetzt speichern drücke, speichert er aber nüx ab ?!? ich krieg nicht hin, alle EDITs in eine datei zu speichern.


der organist - Do 22.04.10 21:24

hei!

hab dein Programm mal getestet. Was auf jeden Fall noch gemacht werden sollte is ne Abfrage auf Gültigkeit:

-Zahlen die kleiner als 1 und größer als 49 sind
-doppelt eingegeben Zahlen...

Gruss,


Hidden - Do 22.04.10 21:30

Hi :)

Die Edits direkt abspeichern, kannst du damit auch nicht.
Der Dialog dient eigentlich nur dazu, einen Dateipfad fürs Speichern auszuwählen. Abspeichern kannst du beispielsweise mit TStringlist.SaveToFile.

Dazu musst du die Texte aus den Editfeldern aber erstmal in eine Stringlist bzw. einen String schreiben:

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:
procedure SaveLotto(const aFilePath: String);  //Strings immer als const übergeben, sonst werden sie nochmal kopiert und es entsteht overhead
var
  aStringList: TStringList;
  i: Integer;
begin
  aStringList := TStringList.Create;
  try //bei File-Operationen kann immer was schiefgehen. Hier(und nur hier) ein try verwenden
    for i := 0 to EditCount - 1 do
      aStringList.Append(Edit[i].Text);
    aStringList.SaveToFile(aFilePath);
  finally
    aStringList.Free;
  end;  
end;

procedure LoadLotto(const aFilePath: String);  //Strings immer als const übergeben, sonst werden sie nochmal kopiert und es entsteht overhead
var
  aStringList: TStringList;
  i: Integer;
begin
  aStringList := TStringList.Create;
  try //bei File-Operationen kann immer was schiefgehen. Hier(und nur hier) ein try verwenden
    aStringList.LoadFromFile(aFilePath);
    for i := 0 to EditCount - 1 do
      Edit[i].Text := aStringList[i];
  finally
    aStringList.Free;
  end;  
end;


Die for-Schleifen musst du jeweils durch die Aktion mit dem einzelnen Edit ersetzen, wenn du sie nicht durchnummeriert hast(entweder in nem Array, oder über FindComponent).

lg,


noo.bee - Do 22.04.10 22:27

Zitat:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
    for i := 0 to EditCount do
      aStringList.Append(Edit[i].Text);
    aStringList.SaveToFile(aFilePath);


    aStringList.LoadFromFile(aFilePath);
    for i := 0 to EditCount do
      Edit[i].Text := aStringList[i];


Die for-Schleifen musst du jeweils durch die Aktion mit dem einzelnen Edit ersetzen, wenn du sie nicht durchnummeriert hast(entweder in nem Array, oder über FindComponent).


ok, ordentlich durchnummeriert sind meine EDITs. also kann ich direkt den EditCount mit 72 ersetzen.

Zitat:
Abfrage auf Gültigkeit:

-Zahlen die kleiner als 1 und größer als 49 sind
-doppelt eingegeben Zahlen...

an >0 <50 hab ich gedacht, nur noch nix eingebaut. aber an doppelte hatte ich noch nicht gedacht. dankö ;)


Hidden - Fr 23.04.10 10:17

for i := 0 to EditCount - 1, muss es natürlich heißen :oops:, denn von 0 bis EditCount sind ja (EditCount+1) Zahlen.


Stread - Fr 23.04.10 13:36

Ich habe früher auch mal ein Lotto Programm erstellt deshalb hier mal ein Bild als Anregung. Auf Wunsch kann ich auch sagen wie die einzelnen Sachen funktionieren.

lotto

Moderiert von user profile iconNarses: Bild als Anhang hochgeladen.


noo.bee - Fr 23.04.10 23:25

Zitat:
for i := 0 to EditCount - 1

hab ich schon bemerkt :D aber irgendwo hängts noch...

[DCC Fehler] lotto.pas(265): E2003 Undeklarierter Bezeichner: 'Edit'

Delphi-Quelltext
1:
aStringList.Append(Edit[i].Text);                    


@Stread: dein bild geht net


Hidden - Sa 24.04.10 06:48

Hi :)

Das geht auch nur, wenn die Edit-Felder in einem Array of TEdit sind.

Für FindComponent müsstest du Edit[i] durch TEdit(FindComponent('Edit' + IntToStr(i))) ersetzen.

lg,


Stread - Sa 24.04.10 09:15

Komisch, gestern gings noch. Habs reineditiert aber hier nochmal.

Moderiert von user profile iconNarses: Das Bild ist in diesem Beitrag [http://branch.delphi-forum.de/viewtopic.php?p=603238#603238] zu sehen.


noo.bee - Sa 24.04.10 14:49

@stread: gute arbeit. aber ich will gern nen ganzen schein abgleichen. bei dir ist ja nur 1 tip abgedeckt. weist wie ich meine ?

mag mal einer schauen woran es bei mir hängt ?


Hidden - Sa 24.04.10 20:11

Wenn du uns sagst, was dein Compiler dir für Meldungen ausgibst, was passiert und was passieren soll ;)


noo.bee - So 25.04.10 16:42

[DCC Fehler] lotto.pas(265): E2003 Undeklarierter Bezeichner: 'Edit'

Delphi-Quelltext
1:
aStringList.Append(Edit[i].Text);                    


Zitat:
Das geht auch nur, wenn die Edit-Felder in einem Array of TEdit sind.
Für FindComponent müsstest du Edit[i] durch FindComponent('Edit' + IntToStr(i)) ersetzen.


findcomponent hab ich nich mit drin. muss das mit rein ?


jaenicke - So 25.04.10 18:45

Ja


Hidden - So 25.04.10 19:49

Hi :)

Wenn du die Edit-Felder über einen Index ansprechen willst, ja: Array oder Findcomponent. Und in ein Array müssen sie zu Anfang einmal hereingespeichert werden.

lg,


noo.bee - Mi 28.04.10 19:15

muss ich denn die edit felder über n array ansprechen zum speichern ? oder gehts auch anders/einfacher/schneller ? die edit felder ändern sich ja nicht mehr in der anzahl.


Hidden - Mi 28.04.10 19:58

Hi :)

Wenn du sie in ein Array speichern willst, musst du sie dazu ja einzeln ansprechen, und reinschreiben. :nixweiss:
Die Zweite Möglichkeit wäre wi gesagt FindComponent(), das ist etwas langsamer. Aber das ist hier ja egal :)

lg,


noo.bee - Do 29.04.10 20:26

kannst du mal schauen ?


noo.bee - Sa 01.05.10 17:03

muss ich die edits extern speichern ? also muss das immer in ne textdatei oder so sein ? kann man das nicht so machen, dass die jedesmal wenn ich das programm schließe automatisch in der exe gespeichert werden ?
oder wäre das eine für mich unlösbare aufgabe ?


blaky - Sa 01.05.10 17:56

als kleine Anregung kannste dir die Lottozahlen auch von hier
http://www.dielottozahlen.de/lotto/6aus49/6aus49.html

auslesen.

lotto


noo.bee - So 02.05.10 12:47

ich kann dein proggie nicht downloaden :( --> EDIT: ging doch
fehler beim ausführen deines proggies: " ist kein gültiger integerwert
hab aber alles ordentlich ausgefüllt

die idee, die zahlen ausm netz auszulesen hatte ich auch ;) aber das wäre erst dann eingebaut worden, wenn ich das wissen dazu habe :D
immo hängts ja schon bei einfachen sachen wie speichern :p wie hast du das bei dir hinbekommen ? da speicherst du ja alles schön in eine ini rein. gefällt mir

trotzdem danke für die idee mit onlineabgleich ;)


blaky - So 02.05.10 14:42

:cry: grade gestern ändern die ihre Webpage wo ich die Zahlen herhole...

hier die gefixte Version

Was die InI Files angeht such mal nach Tinifiles.. ist eigentlich ganz einfach

MFG
blaky


noo.bee - So 02.05.10 16:28

wie finde ich tinifile ? ich hab CodeGear Delphi 2009 und da isses nich dabei. muss ich das irgendwie erst "reininstallieren" ?


jaenicke - So 02.05.10 16:32

user profile iconnoo.bee hat folgendes geschrieben Zum zitierten Posting springen:
wie finde ich tinifile ?
Indem du F1 drückst und in der Hilfe feststellst, dass es in der Suche in der Delphi-Reference UNIT INIFILES enthalten ist... :roll:

Wobei man nicht vergessen sollte, dass die INI-Dateien bzw. die Methoden für den Zugriff darauf als veraltet markiert sind. Diese sind nur für Kompatibilität mit Windows 3.1 noch enthalten, könnten also jederzeit in einer neuen Windowsversion verschwinden... (ist ja immerhin schon über 15 Jahre alt)


noo.bee - So 02.05.10 16:59

jo habs grad schon gefunden gehabt, trotzdem danke ;)

habs jetzt so:


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:
// Speichern
procedure TForm1.Button2Click(Sender: TObject);
begin
  ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+
    'lotto.ini');
    ini.WriteString('Feld 1','Tip 1',edit1.Text);
    ini.WriteString('Feld 1','Tip 2',edit2.Text);
    ini.WriteString('Feld 1','Tip 3',edit3.Text);
    ini.WriteString('Feld 1','Tip 4',edit4.Text);
    ini.WriteString('Feld 1','Tip 5',edit5.Text);
    ini.WriteString('Feld 1','Tip 6',edit6.Text);
end;

//Laden
procedure TForm1.Button3Click(Sender: TObject);
begin
  try
    edit1.Text:=ini.ReadString('Feld 1','Tip 1',edit1.Text);
    edit2.Text:=ini.ReadString('Feld 1','Tip 2',edit2.Text);
    edit3.Text:=ini.ReadString('Feld 1','Tip 3',edit3.Text);
    edit4.Text:=ini.ReadString('Feld 1','Tip 4',edit4.Text);
    edit5.Text:=ini.ReadString('Feld 1','Tip 5',edit5.Text);
    edit6.Text:=ini.ReadString('Feld 1','Tip 6',edit6.Text);
  finally
    ini.free;
  end;
end;


speichern geht wunderbar. in der ini steht alles so drin wie es soll. aber ich bekomme beim laden immer zugriffsverletzung. wo is da mein fehler ?


Stundenplan - So 02.05.10 18:59

Vielleicht hast du noch nicht auf Laden geklickt - da wird nämlich erst "ini" erzeugt!

Mache ini mal lokal, also so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure ButtonXYZClick(Sender: TObject);
var ini: TIniFile;
begin
   ini:=TIniFile.create(ExtractFilePath(ParamStr(0))+    'lotto.ini');
   try
     //Zugriffe
   finally
     ini.Free;
   end;
end;


noo.bee - So 02.05.10 19:03

höö, hat tatsächlich funktioniert :D dann kann ich ja endlich das nächste prob angehen.

DANKE AN ALLE HELFENDEN