Anfänger hat Probleme - Wiedermahl ein Delphiquiz

pixelpark

Mitglied
Hallo Zusammen :)

also Folgendes:

Wir sollen in der Schule ein Lernspiel entwickeln. Soweit haben alle angefangen Figuren und Brettspiele zu basteln, aber ich habe mich dazu entschieden, das Ganze am PC zu schreiben - Quiz-mäßig (nach dem WWM-Prinzip).

Die Fragen, Antworten und Lösungsmöglichkeiten werden in Arrays abgelegt (ich weiß, nich gerade die beste Art, aber ich bin noch totaler Anfänger =). Auch mein Programmierstiel ist nicht gerade der Beste (keine Prozeduren etc.), aber ich mein: das Ergebnis zählt. Die Lehrerin kann sowieso den Quell-Code nicht bewerten.

Hatte soweit das Programm auch fertiggestellt. Lief so ab: Frage wurde gestellt, Antwort eingetippt und zum Schluß gabs dann ein neues Fenster mit Auswertung und den richtigen Lösungen. Hat auch soweit alles geklappt!

Nur: die Fragen liefen der Reihenfolge ab. Ich möchte aber einen Aufgabenpool haben z.b. 40 und davon 30 random-mäßig ziehn (im Momment nur 4 bzw.5)...auf jedenfall hab ich das eingebaut und jetzt klappt nixmehr... Irgendwie wertet der jetzt die Antworten falsch aus und außerdem stürtzt er nach Eingabe der letzten Lösung ab, manchmal auch früher.


Kann mir vielleicht jemand weiterhelfen?


Danke im Voraus!



Anbei der Quelltext:



unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls, ToolWin, ComCtrls;

type
TForm1 = class(TForm)
Antwortedit: TEdit;
Fragelabel: TLabel;
GroupBox1: TGroupBox;
Panel1: TPanel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
BitBtn1: TBitBtn;
Button1: TButton;
Panel2: TPanel;
Richtiglabel: TLabel;
Falschlabel: TLabel;
Punktestandlabel: TLabel;
Auswahllabel1: TLabel;
Auswahllabel2: TLabel;
Label1: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
Rundenlabel: TLabel;
prozlabel: TLabel;
Panel3: TPanel;
Auswahllabel3: TLabel;
Auswahllabel4: TLabel;
einsatzedit: TEdit;
Label10: TLabel;
Label11: TLabel;
Label12: TLabel;
procedure BitBtn1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Frage:array[1..5] of string;
Auswahl: array [1..20] of string;
Antwort: array [1..5] of integer;
Loesung: array [1..5] of integer;
gezogen: array [1..5] of boolean;
i, richtige, falsch, einsatz, counter, runde, testwert: integer;
teuros, proz:real;
end;

var
Form1: TForm1;


implementation

uses Unit2;
Code:
{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
      if runde <= 4 then
        begin
                //i:=random(5)+1;
                //while (gezogen[i]=true) do
                 //       begin
                  //              i:=random(5)+1;
                   //     end;

                gezogen[i]:=true;
                       // Fragelabel.Caption:= frage[i];
                       // Auswahllabel1.Caption:= auswahl[i*4+1];
                       // Auswahllabel2.Caption:= auswahl[i*4+2];
                       // Auswahllabel3.Caption:= auswahl[i*4+3];
                       // Auswahllabel4.Caption:= auswahl[i*4+4];
                antwortedit.setfocus;
                Antwort[i]:=strtoint (Antwortedit.Text);
                einsatz:= strtoint (einsatzedit.Text);
                        if antwort [i]<> Loesung[i] then
                                begin
                                        showmessage('Sorry. Richtige Antwort ist Nr. ' + inttostr (Loesung[i]));
                                        falsch:=falsch +1;
                                        Falschlabel.Caption:=inttostr (falsch);
                                end;

                        if antwort [i]= Loesung[i] then
                                begin
                                        richtige:=richtige+1;
                                        Richtiglabel.Caption:= inttostr (richtige);

                                end;
                        runde:=runde+1;
                        proz:=(richtige*100)/(runde-1);
                        if antwort[i]= loesung [i] then teuros:=((Einsatz*teuros)/100)+teuros;
                        if antwort[i]<> loesung [i] then teuros:= teuros-((i*750)*(einsatz/100));
                        if teuros<=500 then teuros:=500;
                        Punktestandlabel.Caption:= (formatfloat('#0.00', teuros))+' EUR';
                        Prozlabel.Caption:=formatfloat('#0.0', proz);
                        Punktestandlabel.Caption:=(formatfloat('#0.00', teuros))+'EUR';
                        rundenlabel.Caption:= inttostr (runde);


        end;
                i:=random(5)+1;
                                while (gezogen[i]=true) do
                                        begin
                                                i:=random(5)+1;
                                        end;
                Fragelabel.Caption:= frage[i];
                Auswahllabel1.Caption:= auswahl[i*4+1];
                Auswahllabel2.Caption:= auswahl[i*4+2]; 

// hier gibts dann ne fehlermeldung. allerdings nachdem das programm am laufen ist. meistens nach der 4ten eingabe:
project project1.exe raised exception class eaccessviolation with message 'access violation at address 004046fa in module 'project1.exe'. read of address ffffffffff'. process stopped. use step or run to continue.

                Auswahllabel3.Caption:= auswahl[i*4+3];
                Auswahllabel4.Caption:= auswahl[i*4+4];


        if runde = 5 then
                begin
                        rundenlabel.Caption:='4';
                        Fragelabel.Caption:= 'Geschafft';
                        Auswahllabel1.Caption:= '';
                        Auswahllabel2.Caption:= '';
                        Auswahllabel3.Caption:= '';
                        Auswahllabel4.Caption:= '';
                        Showmessage('Spiel beendet');


                        Form2.stringgrid1.cells[0,0]:='Aufgabe';
                        Form2.stringgrid1.cells[1,0]:='Frage';
                        Form2.stringgrid1.cells[2,0]:='Antwort';
                        Form2.stringgrid1.cells[3,0]:='Gelöst';

                        counter:=1;

                         while counter <=4 do
                                 begin
                                        while gezogen [counter] = true do
                                                begin
                                                        Form2.stringgrid1.Cells[0,counter]:=inttostr (counter);
                                                        Form2.stringgrid1.Cells[1,counter]:=Frage[counter];
                                                        Form2.stringgrid1.Cells[2,counter]:=Auswahl[(counter-1)*4 +(loesung[counter])];

                                                                if loesung[counter]=antwort[counter] then
                                                                        Form2.stringgrid1.Cells[3,counter]:='Ja';
                                                                if loesung [counter]<>antwort[counter] then
                                                                        Form2.stringgrid1.Cells[3,counter]:='Nein';
                                                end;
                                                counter:=counter+1;
                                 end;

                                 form2.richtigefragenlabel.caption:= inttostr(richtige);
                                 form2.falschefragenlabel.caption:= inttostr(falsch);
                                 form2.richtiginprozlabel.caption:= (formatfloat('#0.00', proz))+' %';
                                 form2.ktostandlabel.caption:=(formatfloat('#0.00', teuros))+' EUR';

                      //form1.Close;
                      form2.Show;

                end;


end;

procedure TForm1.Button1Click(Sender: TObject);
begin
        form1.Close;


end;

procedure TForm1.FormCreate(Sender: TObject);
begin
        randomize;
        i:=1;
        falsch:=0;
        richtige:=0;
        teuros:=1000;
        runde:=1;
        proz:=0;
        einsatz:=0;
        einsatzedit.Text:='100';

        while i<6 do
                begin
                        Antwort[i]:=0;
                        i:= i+1;
                end;
        i:=1;
        while i<6 do
                begin
                        gezogen[i]:=false;
                        i:=i+1;
                end;

        i:=random (5)+1;
        Frage[1]:='Was versteht man unter BlaBlaBla?';
        Frage[2]:='Testfrage 2';
        Frage[3]:='Testfrage 3';
        Frage[4]:='Testfrage 4';
        Frage[5]:='Testfrage 5';

        Auswahl[1]:='TestAntwort 1';
        Auswahl[2]:='TestAntwort 2';
        Auswahl[3]:='TestAntwort 3';
        Auswahl[4]:='TestAntwort 4';
        Auswahl[5]:='TestAntwort 5';
        Auswahl[6]:='TestAntwort 6';
        Auswahl[7]:='TestAntwort 7';
        Auswahl[8]:='TestAntwort 8';
        Auswahl[9]:='TestAntwort 9';
        Auswahl[10]:='TestAntwort 10';
        Auswahl[11]:='TestAntwort 11';
        Auswahl[12]:='TestAntwort 12';
        Auswahl[13]:='TestAntwort 13';
        Auswahl[14]:='TestAntwort 14';
        Auswahl[15]:='TestAntwort 15';
        Auswahl[16]:='TestAntwort 16';
        Auswahl[17]:='TestAntwort 17';
        Auswahl[18]:='TestAntwort 18';
        Auswahl[19]:='TestAntwort 19';
        Auswahl[20]:='TestAntwort 20';

        Loesung[1]:=1;
        Loesung[2]:=4;
        Loesung[3]:=3;
        Loesung[4]:=3;
        Loesung[5]:=4;

        Richtiglabel.Caption:='0';
        Falschlabel.Caption:='0';
        rundenlabel.Caption:='1';
        prozlabel.Caption:='0.00';
        Punktestandlabel.Caption:= (formatfloat('#0.00', teuros))+' EUR';
        Fragelabel.Caption:=frage[i];
        Auswahllabel1.Caption:=Auswahl[i];
        Auswahllabel2.Caption:=Auswahl[i];
        Auswahllabel3.Caption:=Auswahl[i];
        Auswahllabel4.Caption:=Auswahl[i];


end;

end.
 
Ich hab mir den Code jetzt nicht vollständig angeschaut, aber eine EAccessViolation tritt bei Arrays gerne auf, wenn man versucht, einen Index zu lesen, den es nicht gibt. Sprich: dein Array geht von 0 bis x, nur so als Beispiel, und das programm will auch x+1 oder -1 oder sowas zugreifen.

Wenn ich nachher mehr Zeit habe und das Problem immernoch besteht, schau ich noch mal rein, denke aber, du kannst das Problem jetzt schon lösen.

Hellie
 
War vorhin etwas voreilig.... die Überprüfung & Auswahl der Fragen scheint doch zu gehen...

Mit der Arraygeschichte komm ich nich wirklich weiter. Hab Alles nochma daraufhin überprüft, aber ich find nicht den Fehler :(
 
Trotz der quasi gegebenen Unlesbarkeit deines Codes (weil du keine Codetags benutzt hast) sticht sofort ins Auge, dass du deine Arraygrenzen verletzt:

Code:
i:=random(5)+1;

Auswahllabel1.Caption:= auswahl[i*4+1];
Auswahllabel2.Caption:= auswahl[i*4+2];
Auswahllabel3.Caption:= auswahl[i*4+3];
Auswahllabel4.Caption:= auswahl[i*4+4];

Du hast dein Array im Intervall [1,20] definiert. Wieso addierst du zu dem Maximalwert i*4=20 noch etwas hinzu? Damit übertrittst du die obere Intervallgrenze um Werte von 1 bis 4.

Den Rest des Programms habe ich nicht analysiert, allerdings ist mir aufgefallen, dass die Variable i im Beginn des Eventhandlers nicht initialisiert wird.

Tip: Wenn du einfach nur i hochzählen willst, brauchst du das nicht mit einer while-Schleife tun. Dafür gibt es die for-Schleife. Noch ein Tip: Wenn du i um 1 erhöhen willst, schreib lieber Inc(i) anstatt i:=i+1. Letzteres ist Basic-Sprech und recht ineffizient!

Gawayn
 
Ersteinma Danke!

Hab soweit alles überarbeitet.

Was meinst du denn mit "Variable i im Beginn des Eventhandlers nicht initialisiert"?

Danke für den Tipp mit den Arrays. War, weil ich nicht daran gedacht habe, dass nach dem random Einbau der auch über Aufgabe 4 hinaus geht. Jetzt stimmts aber.

Wenn ich aber nun die letzte Spielrunde beendet habe, hängt das Programm. D.h. es kommt nicht die zweite Form mit den Ergebnissen und das Spielfenster bekommt n Freeze.

Woran liegt das denn?


Quellcode:

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls, ToolWin, ComCtrls;

type
  TForm1 = class(TForm)
    Antwortedit: TEdit;
    Fragelabel: TLabel;
    GroupBox1: TGroupBox;
    Panel1: TPanel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    BitBtn1: TBitBtn;
    Button1: TButton;
    Panel2: TPanel;
    Richtiglabel: TLabel;
    Falschlabel: TLabel;
    Punktestandlabel: TLabel;
    Auswahllabel1: TLabel;
    Auswahllabel2: TLabel;
    Label1: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Rundenlabel: TLabel;
    prozlabel: TLabel;
    Panel3: TPanel;
    Auswahllabel3: TLabel;
    Auswahllabel4: TLabel;
    einsatzedit: TEdit;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    procedure BitBtn1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Frage:array[1..5] of string;
    Auswahl: array [1..20] of string;
    Antwort: array [1..5] of integer;
    Loesung: array [1..5] of integer;
    gezogen: array [1..5] of boolean;
    i, richtige, falsch, einsatz, counter, runde, testwert: integer;
    teuros, proz:real;
    end;

var
  Form1: TForm1;


implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
      if runde <= 4 then
        begin

                gezogen[i]:=true;                             //Einlesen Antwort & Einsatz
                antwortedit.setfocus;
                Antwort[i]:=strtoint (Antwortedit.Text);
                einsatz:= strtoint (einsatzedit.Text);
                        if antwort [i]<> Loesung[i] then          //Prüfung der Antwort
                                begin
                                        showmessage('Sorry. Richtige Antwort ist Nr. ' + inttostr (Loesung[i]));
                                        Inc(falsch);
                                        Falschlabel.Caption:=inttostr (falsch);
                                end;

                        if antwort [i]= Loesung[i] then
                                begin
                                        Inc(richtige);
                                        Richtiglabel.Caption:= inttostr (richtige);

                                end;
                        runde:=runde+1;                       // Spielstatistiken berechnen
                        proz:=(richtige*100)/(runde-1); 
                        if antwort[i]= loesung [i] then teuros:=((Einsatz*teuros)/100)+teuros;
                        if antwort[i]<> loesung [i] then teuros:= teuros-((i*750)*(einsatz/100));
                        if teuros<=500 then teuros:=500;
                        Punktestandlabel.Caption:=(formatfloat('#0.00', teuros))+' EUR';
                        Prozlabel.Caption:=formatfloat('#0.0', proz);
                        rundenlabel.Caption:= inttostr (runde);


        end;
                i:=random(5)+1;                                 //Auswahl der neuen Frage
                                while (gezogen[i]=true) do 
                                        begin
                                                i:=random(5)+1;
                                        end;
                Fragelabel.Caption:= frage[i];
                Auswahllabel1.Caption:= auswahl[i*4-3];
                Auswahllabel2.Caption:= auswahl[i*4-2];
                Auswahllabel3.Caption:= auswahl[i*4-1];
                Auswahllabel4.Caption:= auswahl[i*4];


        if runde = 5 then               //Spielende mit Auswertung und Statistik auf Form2
                begin
                        rundenlabel.Caption:='4';
                        Fragelabel.Caption:= 'Geschafft';
                        Auswahllabel1.Caption:= '';
                        Auswahllabel2.Caption:= '';
                        Auswahllabel3.Caption:= '';
                        Auswahllabel4.Caption:= '';
                        Showmessage('Spiel beendet');


                        Form2.stringgrid1.cells[0,0]:='Aufgabe';
                        Form2.stringgrid1.cells[1,0]:='Frage';
                        Form2.stringgrid1.cells[2,0]:='Antwort';
                        Form2.stringgrid1.cells[3,0]:='Gelöst';

                        counter:=1;

                         while counter <=4 do      //Ausgabe der Spielergebnisse auf Form2
                                 begin
                                        while gezogen [counter] = true do
                                                begin
                                                        Form2.stringgrid1.Cells[0,counter]:=inttostr (counter);
                                                        Form2.stringgrid1.Cells[1,counter]:=Frage[counter];
                                                        Form2.stringgrid1.Cells[2,counter]:=Auswahl[(counter-1)*4 +(loesung[counter])];

                                                                if loesung[counter]=antwort[counter] then
                                                                        Form2.stringgrid1.Cells[3,counter]:='Ja';
                                                                if loesung [counter]<>antwort[counter] then
                                                                        Form2.stringgrid1.Cells[3,counter]:='Nein';
                                                end;
                                                Inc(counter);
                                 end;

                                 form2.richtigefragenlabel.caption:= inttostr(richtige);
                                 form2.falschefragenlabel.caption:= inttostr(falsch);
                                 form2.richtiginprozlabel.caption:= (formatfloat('#0.00', proz))+' %';
                                 form2.ktostandlabel.caption:=(formatfloat('#0.00', teuros))+' EUR';


                      form2.Show;

                end;


end;

procedure TForm1.Button1Click(Sender: TObject);
begin
        form1.Close;


end;

procedure TForm1.FormCreate(Sender: TObject);
begin
        randomize;                                //Variable auf 0 bzw. Anfangsstand setzen
        i:=1;
        falsch:=0;
        richtige:=0;
        teuros:=1000;
        runde:=1;
        proz:=0;
        einsatz:=0;
        einsatzedit.Text:='100';

        while i<6 do
                begin
                        Antwort[i]:=0;
                        Inc(i);
                end;
        i:=1;
        while i<6 do
                begin
                        gezogen[i]:=false;
                        Inc(i);
                end;

        i:=random (5)+1;

        Frage[1]:='Was versteht man unter BlaBlaBla?';                      //Aufgabenpool
        Frage[2]:='Testfrage 2';
        Frage[3]:='Testfrage 3';
        Frage[4]:='Testfrage 4';
        Frage[5]:='Testfrage 5';

        Auswahl[1]:='TestAntwort 1';
        Auswahl[2]:='TestAntwort 2';
        Auswahl[3]:='TestAntwort 3';
        Auswahl[4]:='TestAntwort 4';
        Auswahl[5]:='TestAntwort 5';
        Auswahl[6]:='TestAntwort 6';
        Auswahl[7]:='TestAntwort 7';
        Auswahl[8]:='TestAntwort 8';
        Auswahl[9]:='TestAntwort 9';
        Auswahl[10]:='TestAntwort 10';
        Auswahl[11]:='TestAntwort 11';
        Auswahl[12]:='TestAntwort 12';
        Auswahl[13]:='TestAntwort 13';
        Auswahl[14]:='TestAntwort 14';
        Auswahl[15]:='TestAntwort 15';
        Auswahl[16]:='TestAntwort 16';
        Auswahl[17]:='TestAntwort 17';
        Auswahl[18]:='TestAntwort 18';
        Auswahl[19]:='TestAntwort 19';
        Auswahl[20]:='TestAntwort 20';

        Loesung[1]:=1;
        Loesung[2]:=4;
        Loesung[3]:=3;
        Loesung[4]:=3;
        Loesung[5]:=4;

                             //Ausgabe der Fragen und des Spielstandes für die erste Runde
                   
        Richtiglabel.Caption:='0'; 
        Falschlabel.Caption:='0';
        rundenlabel.Caption:='1';
        prozlabel.Caption:='0.00';
        Punktestandlabel.Caption:= (formatfloat('#0.00', teuros))+' EUR';
        Fragelabel.Caption:=frage[i];
        Auswahllabel1.Caption:=Auswahl[i*4-3];
        Auswahllabel2.Caption:=Auswahl[i*4-2];
        Auswahllabel3.Caption:=Auswahl[i*4-1];
        Auswahllabel4.Caption:=Auswahl[i*4];


end;

end.
 
Mit "Variable i im Eventhandler nicht intialisiert" meine ich, dass du die Variable i in der Handlerprozedur BitBtn1Click nicht initialisierst. Da wird einfach so die Variable i verwendet. Da i als Klassenvariable quasi global ist, behält sie zwischen den Prozedur-Aufrufen ihren Wert bei, jedoch weiß ich nicht, ob das beabsichtigt ist.

Ich habe den Eindruck, dass du Delphis integrierten Debugger nicht verwendest. Das würde dir sehr helfen. Den meisten der Fehlern würdest du so selbst auf die Spur kommen.

Nun zum Freeze. Wenn irgendeine Form von Fehler aufträte, würde Delphi eine Exception werfen. Da dies nicht geschieht, gibt es letzten Endes nur noch die Lösung, dass dein Programm in eine Endlosschleife tritt. Und in der Tat erscheint mir die letzte while-Schleife als bester Kandidat dafür. In dieser Schleife ist die Austrittsbedingung: gezogen[counter]=false. Bist du sicher, dass dieser Fall eintreten kann? Ich habe den Verdacht, dass das gesamte gezogen-Array nur true-Werte enthält.

Gawayn
 
Zurück