Entwickler-Ecke

Sonstiges (Delphi) - Quiz mit Textdatei


Ashraf_Khan - Di 17.05.05 22:59
Titel: Quiz mit Textdatei
Hallo, ich bin gerade daran ein Quiz in Delphi zu programmieren. Die ganz einfachen Sachen mit Fragen auf den Bildschrim bringen und die Antwort überprüfen bekomme ich noch hin. Jetzt wollte ich es aber so machen, das eine gestellte Frage nicht noch einmal gestellt wird. Das habe ich wie folgt realisiert:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
  While Frage<1 do
  begin
    randomize;
   x:=random(10);
  case x of
  1:begin if ungefragt1 then begin Label1.caption:='Wie viele Chromosomen hat eine menschliche Körperzelle?';  RadioButton1.caption:='A:23';RadioButton2.caption:='B:44';RadioButton3.caption:='C:46';RadioButton4.caption:='D:22';d:=3; ungefragt1:=´false; Frage:=1;end end;
  2:begin if ungefragt2 then begin Label1.caption:='b ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=2;  ungefragt2:=false; Frage:=1;end end;
  3:begin if ungefragt3 then begin Label1.caption:=' c';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=3;  ungefragt3:=false; Frage:=1;end end;
  4:begin if ungefragt4 then begin Label1.caption:='d ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=4;  ungefragt4:=false; Frage:=1;end end;
  5:begin if ungefragt5 then begin Label1.caption:='e ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=1;  ungefragt5:=false; Frage:=1;end end;
  6:begin if ungefragt6 then begin Label1.caption:='f ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=2;  ungefragt6:=false; Frage:=1;end end;
  7:begin if ungefragt7 then begin Label1.caption:='g ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=3;  ungefragt7:=false; Frage:=1;end end;
  8:begin if ungefragt8 then begin Label1.caption:='h ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=2;  ungefragt8:=false; Frage:=1;end end;
  9:begin if ungefragt9 then begin Label1.caption:=' i';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=1;  ungefragt9:=false; Frage:=1;end end;
  10:begin if ungefragt10 then begin Label1.caption:='j ';RadioButton1.caption:=' ';RadioButton2.caption:=' ';RadioButton3.caption:=' ';RadioButton4.caption:=' ';d:=1; ungefragt10:=false; Frage:=1;end end;
   end;
end;

Das ist praktisch der Kern des Programms. Nun habe ich das Problem, dass es eine Endlosschleife geworden ist und ich nicht weis wieso, davon abgesehen, dass es mir viel zu kompliziert aussieht und ich mir sicher bin, dass es wesentlich einfacher geht. Wenn mir also jemand erklären kann, wie ich es vereinfachen kann oder wenigstens die Endloschleife löse, wäre ich wirklich sehr dankbar.

Außerdem wollte es auch noch so machen, dass die Fragen extern in einer Textdatei gespeichert werden, schon alleine, weil man dann Fragen hinzufügen kann und dann wird auch der Quelltext übersichtlicher. Kann mir da auch jemand weiterhelfen?

MfG
Khan

Moderiert von user profile iconAXMD: Code- durch Delphi-Tags ersetzt.
Moderiert von user profile iconAXMD: Topic aus Projekte (Open Source) verschoben am Di 17.05.2005 um 23:06


delfiphan - Di 17.05.05 23:03

Erstell z.B. eine Klasse "TQuizFrage", die folgende Informationen enthält:
- die Frage selbst
- die möglichen Antworten
- die richtige Antwort

Dann addst du alles Quiz-Fragen in die TObjectList. Beim Stellen einer Frage ziehst du eine zufällige Frage aus der TObjectList und löschst sie anschliessend aus der TObjectList. So wird sie nicht mehr gezogen.


Gosa - Di 17.05.05 23:28

Ich glaub das ist zu schwer...


so in der art ist das relativ einfach würd ich sagen:

(Hab das nicht ausprobiert)

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:
var FrageBeantwortet : array[1..10of boolean;

procedure NeueFrage();
var IniF : TIniFile;
    x :integer;
    gefunden : boolean
begin
  Try
    IniF := IniF.Create(C:\DeineDatei.xyz); //such mal nach IniFiles hier im Forum

    gefunden := false

    While gefunden = false do                   
      Begin
      randomize;
      x:=random(9) + 1//ich glaub das ging bei 0 los also +1

      If FrageBeantwortet[x] = false then
      Begin
        FrageBeantwortet[x] := true;
        gefunden := true;
        Label1.caption := IniF.Readstring('Frage' + intostr(x), 'Frage''Fehler');
        RadioButton1.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort1' , 'Fehler');
        RadioButton2.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort2' , 'Fehler');
        RadioButton3.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort3' , 'Fehler');
        RadioButton4.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort4' , 'Fehler');
      End;
    End;
  Finally
    IniF.Free;
  End
End;


delfiphan - Di 17.05.05 23:52

Etwas strukturiert programmieren schadet nie. Ich denke es ist sogar weniger kompliziert so. Das ganze kannste ja dann immer noch in einer INI-Datei haben.
Das ganze mal einfachheitshalber mit "Semi-OOP":


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:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
Type
TQuizFrage = class
  Frage, Antworten: String;
  KorrekteAntwort: Byte;
  constructor Create(Frage: String; Antworten: String; KorrekteAntwort: Byte);
end;

constructor TQuizFrage.Create(Frage: String; Antworten: String; KorrekteAntwort: Byte);
begin
  self.Frage := Frage;
  self.Antworten := Antworten;
  self.KorrekteAntwort := KorrekteAntwort;
end;

var
 Quiz: TObjectList;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Quiz := TObjectList.Create;
  with Quiz do
  begin
   Add(TQuizFrage.Create('Wieviele Chromo...','23;44;46;22',3));
   Add(TQuizFrage.Create('Frage2','Antwort1;Antwort2;Antwort3',1));
   Add(TQuizFrage.Create('Frage3','Antwort1;Antwort2;Antwort3',2));
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Quiz.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 I: Integer;
begin
  if Quiz.Count > 0 then 
  begin
   I := Random(Quiz.Count);
   with Quiz.Items[I] as TQuizFrage do
   begin
    // Hier stehen die Variablen "Frage", "Antworten" und "KorrekteAntwort" zur Verfügung
   end;
   Quiz.Delete(I);
  end;
end;


Ashraf_Khan - Mi 18.05.05 20:41

Erstmal danke für die Ratschläge, ich denke ich habe das mit der ini verstanden und könnte es jetzt auch umsetzten. Habe mich übrigend für die Version von gosa entschieden.
Jetzt habe ich allerdings ein weiteres Problem:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
      
If FrageBeantwortet'inttostr(x)' then //hier das Problem
      Begin
        FrageBeantwortet[x] := true;
        gefunden := true;
        Label1.caption := IniF.Readstring('Frage' + intostr(x), 'Frage''Fehler');
        RadioButton1.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort1' , 'Fehler');
        RadioButton2.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort2' , 'Fehler');
        RadioButton3.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort3' , 'Fehler');
        RadioButton4.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort4' , 'Fehler');
      End;


Also okay, ich wollte es halt so machen, dass der Name dieser Variable FrageBeantwortet um die Zahl aus x erweitert wird, damit ich mir viel schreibarbeit erspare, hat jemand dafür einen lösungsansatz?


Gosa - Mi 18.05.05 21:01

Ich verstehe deine Frage nicht wirklich... Meinst du so was: (record)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
type
  TFrage = record
    WurdeGefragt, RichtigBeantwortet : boolean
  end;

var
  vFrage : array[1..10of TFrage;


Wenn du das von delfiphan verstehst nimm das. Da kannst du RichtigBeantwortet einfach mit in die Klasse TQuizFrage tun.


Ashraf_Khan - Mi 18.05.05 21:49

Ne, das von ihm verstehe ich leider nicht. Das Ding ist, das wir zwar Delphi in der Schule hatten, aber kaum was gelernt haben und jetzt mit einem Mal Sachen können müssen, die wir nie vorher hatten.

Ich will die Schleife/If-Abfrage so konstruieren, das sie für alle Fragen gilt, das ich also nicht einzeln schreiben muss
if Fragebeantwortet1=true ... also die 1. Frage
if Fragebeantwortet2=true ... hier dann die 2. Frage

sondern halt, so, dass das x aus dem random festlegt welche von den Variablen gilt also jetzt einfach sowas wie

if Fragebeantwortetx=true... und x mit dem Randomwert unddamit für alle möglichen Fragen überprüfen, die rankommen könnten.


rjan - Mi 18.05.05 22:27

oder schau mal bei http://www.knowware.de oder so nach (bei delphi suchen. . . :lol: )


Gosa - Do 19.05.05 01:30

Das genau macht das array.

user profile iconAshraf_Khan hat folgendes geschrieben:

if Fragebeantwortetx=true... und x mit dem Randomwert unddamit für alle möglichen Fragen überprüfen, die rankommen könnten.


In Delphi code ist das das hier:

Delphi-Quelltext
1:
  If FrageBeantwortet[x] = true... then ...                    


Oder versteh ich immer noch nicht was du meinst???


Ashraf_Khan - Do 19.05.05 06:26

Achso, okay, jetzt habe ich das verstanden. Allerdings klappt das bei Type nicht, da sagt er immer ':' erwartet aber '=' gefunden, woran liegt das?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
type
  TForm1 = class(TForm)
    RadioGroup1: TRadioGroup;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    RadioButton3: TRadioButton;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    TFrage = record
     FrageBeantwortet:Boolean;


Gosa - Fr 20.05.05 00:00

das muss so aussehen: (ungefähr)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
type   
  type
  TForm1 = class(TForm)
    //hier steht bei dir noch mehr kram drin
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

//Der record muss hier hier
type //muss man nicht hinschreiben. Ich finds aber schöner.
  TFrage = record   
    WurdeGefragt, RichtigBeantwortet : boolean   
  end;   

var   
  Form1: TForm1;  
  vFrage : array[1..10of TFrage;


Ashraf_Khan - Fr 20.05.05 07:10

Okay, habe ich gemacht, aber ich habe jetzt immer noch eine Reihe von anderen Fehlern, die ich zum Tiel gar nicht verstehe:

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:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
unit Unit1;

interface

uses
  Windows, Messages, inifiles, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    RadioGroup1: TRadioGroup;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    RadioButton3: TRadioButton;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
     
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;
type
    TFrage = record
     FrageBeantwortet:Boolean;
     end;
var
  Form1: TForm1;
  FrageBeantwortet:boolean   ;

implementation

{$R *.dfm}

procedure NeueFrage();
var IniF : TIniFile;
    x :integer;
    gefunden : boolean    ;
    FrageBeantwortet: array[1..10of TFrage;
begin
  Try
    IniF := IniF.Create('C:\Fragen.ini'); //such mal nach IniFiles hier im Forum


    gefunden := false;


    While gefunden = false do
      Begin
      randomize;
      x:=random(9) + 1//ich glaub das ging bei 0 los also +1


      If FrageBeantwortet[x] then //Ausdruckstyp muss BOOLEAN sein
      Begin
        FrageBeantwortet[x] := true; //Inkompatible Typen TFrage und boolean
        gefunden := true;
        Label1.caption := IniF.Readstring('Frage' + intostr(x), 'Frage''Fehler'); //undefinierter Bezeichner inttostr
        RadioButton1.caption//Operator oder Semikolon fehlt := IniF.Readstring('Frage' + intostr(x), 'Antwort1' , 'Fehler');
        RadioButton2.caption//Operator oder Semikolon fehlt  := IniF.Readstring('Frage' + intostr(x), 'Antwort2' , 'Fehler');
        RadioButton3.caption//Operator oder Semikolon fehlt  := IniF.Readstring('Frage' + intostr(x), 'Antwort3' , 'Fehler');
      End//Außerdem sagt er mir hier bei allen Labels und Radio Buttons, undefinierter Bezeichner
    End;  
  Finally  
    IniF.Free;  
  End
end;

end.


Vor allem das mit den Labels und RadioButtons verstehe ich gar nicht, weil sie alle vorhanden sind und ich nichts rausgelöscht habe, wo sie drin standen.
Ich wäre wirklich sehr dankbar, wenn ihr mir nochmal helfen könntet.


Gosa - Fr 20.05.05 12:52

so ungefähr muss es sein:


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:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
unit Unit1;   

interface   

uses   
  Windows, Messages, inifiles, SysUtils, Variants, Classes, Graphics, Controls, Forms,   
  Dialogs, StdCtrls, ExtCtrls;   

type   
  TForm1 = class(TForm)   
    RadioGroup1: TRadioGroup;   
    RadioButton1: TRadioButton;   
    RadioButton2: TRadioButton;   
    RadioButton3: TRadioButton;   
    Button1: TButton;   
    Button2: TButton;   
    Label1: TLabel;   
    procedure Button1Click(Sender: TObject);   
        
  private   
    { Private-Deklarationen }   
  public   
    { Public-Deklarationen }   
  end;   
type   
    TFrage = record   
      FrageBeantwortet:Boolean; //ein record kann besteht aus mehreren Variablen... 
                                //wenn du nur eine da rein tust ist das nicht nötig aber egal.  
    end;   
var   
  Form1: TForm1;   
  //FrageBeantwortet:boolean   ;            //brauchst du nicht du hast doch das record...
  vFrageBeantwortet: array[1..10of TFrage; //diese Variable muss global sein da du sonst die werte nach der ausführung der 
                                             //Prozedure nicht mehr hast


implementation   

{$R *.dfm}   

procedure NeueFrage();   
var IniF : TIniFile;   
    x :integer;   
    gefunden : boolean    ;   
      
begin   
  Try   
    IniF := IniF.Create('C:\Fragen.ini'); //such mal nach IniFiles hier im Forum   


    gefunden := false;   


    While gefunden = false do   
      Begin   
      randomize;   
      x:=random(9) + 1//ich glaub das ging bei 0 los also +1   


      If vFrageBeantwortet[x].FrageBeantwortet = false then //Auf eine Varibale eines record grieft man so zu  
      Begin   
        vFrageBeantwortet[x].FrageBeantwortet := true; //Inkompatible Typen TFrage und boolean   
        gefunden := true;   
        Label1.caption := IniF.Readstring('Frage' + intostr(x), 'Frage''Fehler'); //undefinierter Bezeichner inttostr
                                                                                 //es fehlt ein 't'    
        RadioButton1.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort1' , 'Fehler');   
        RadioButton2.caption := IniF.Readstring('Frage' + intostr(x), 'Antwort2' , 'Fehler');   
        RadioButton3.caption  := IniF.Readstring('Frage' + intostr(x), 'Antwort3' , 'Fehler');   
      End//Außerdem sagt er mir hier bei allen Labels und Radio Buttons, undefinierter Bezeichner
           //hast du die den auf deine Form getan???   
    End;     
  Finally     
    IniF.Free;     
  End   
end;   

end.


Tu mal in das OnCreate der form so was:

Delphi-Quelltext
1:
2:
For i:= 1 to 10 do
   vFrageBeantwortet[x].FrageBeantwortet := false;


Ich weis nicht ob die den wert true oder false von anfang an haben. Du soltest mal ein basis tutorial durcharbeiten...


Ashraf_Khan - Fr 27.05.05 07:02

Okay, ich habe es jetzt noch mit etwas fremder Hilfe gelöst gekriegt. Ich möchte mich jetzt nochmal bei allen bedanken, die mir geholfen haben, danke! Wer will kann sich bei mir melden, dem kann ich mein Quiz schicken, zum Zeitvertreib oder so.
Gruß Khan