Здравствуйте, имеется программа тест с базой данных. Скажите пожалуйста, как сделать, чтобы не только шли рандомно вопросы, но и ответы. А также, чтобы выводились баллы не 1 и 0, а в процентном соотношение.
procedure FillArray(var A: array of Integer); var I, S, R: Integer; begin for I := 0 to High(A) do A[I] := I; for i := High(A) downto 0 do begin R := Random(I); S := A[R]; A[R] := A[I]; A[I] := S; end; end;
procedure Ttest.Vopros(nomer:integer); begin DataModule2.Vopros.Locate('Номер',mass[nomer],[]); //варианты ответов DataModule2.Variant.First; RadioButton1.Caption:=DataModule2.Variant.FieldValues['Ответ']; if DataModule2.Variant.FieldValues['Правильный']=true then RadioButton1.Tag:=1 else RadioButton1.Tag:=0;
DataModule2.Variant.Next; RadioButton2.Caption:=DataModule2.Variant.FieldValues['Ответ']; if DataModule2.Variant.FieldValues['Правильный']=true then RadioButton2.Tag:=1 else RadioButton2.Tag:=0;
DataModule2.Variant.Next; RadioButton3.Caption:=DataModule2.Variant.FieldValues['Ответ']; if DataModule2.Variant.FieldValues['Правильный']=true then RadioButton3.Tag:=1 else RadioButton3.Tag:=0;
DataModule2.Variant.Next; RadioButton4.Caption:=DataModule2.Variant.FieldValues['Ответ']; if DataModule2.Variant.FieldValues['Правильный']=true then RadioButton4.Tag:=1 else RadioButton4.Tag:=0; Label2.Caption:=inttostr(strtoint(Label2.Caption)+1); end;
procedure Ttest.Button1Click(Sender: TObject); var i:integer; RB:TRadioButton; cena:string; begin if ((RadioButton1.Checked=true) or (RadioButton2.Checked=true) or (RadioButton3.Checked=true) or (RadioButton4.Checked=true) )
then begin for i := 0 to GroupBox1.ControlCount-1 do begin RB:=TRadioButton(GroupBox1.Controls[i]); if RB.Checked=true then Label1.Caption:=inttostr(strtoint(Label1.Caption)+RB.Tag); end;
if strtoint(Label2.Caption)<16 then begin Vopros(strtoint(Label2.Caption)); RadioButton1.Checked:=false; RadioButton2.Checked:=false; RadioButton3.Checked:=false; RadioButton4.Checked:=false;
test.Caption:='Тестирование.Вопрос'+inttostr(strtoint(Label2.Caption)-1)+' из 15'; end else begin if strtoint(Label1.Caption)>8 then ocen:='5' else if strtoint(Label1.Caption)>6 then ocen:='4' else if strtoint(Label1.Caption)>4 then ocen:='3' else ocen:='2';
end; end else showmessage('Вы не выбрали вариант ответа!'); end;
procedure Ttesti.Button2Click(Sender: TObject); var i,kol:integer; begin For i:=1 to DataModule2.Vopros.RecordCount do begin DataModule2.Vopros.Edit; DataModule2.Vopros.FieldValues['Номер']:=i; DataModule2.Vopros.Post; DataModule2.Vopros.Next; end; DataModule2.Vopros.Last; kol:=DataModule2.Vopros.FieldValues['id'];
Randomize;
SetLength(mass,kol); FillArray(mass);
Vopros(strtoint(Label2.Caption)); testi.Caption:='Тестирование. Вопрос 1 из 50';
Как я понял, DataModule2.Vopros.Locate делает запрос из БД. Сам этот запрос, наверное, можно изменить так, чтоб был случайный порядок (ORDER BY RANDOM()). Или ORDER BY IFF(id MOD 4 = 0, …, …), где перебираются все возможные остатки id от деления на 4 и в зависимости от этого подставляются номера из случайно сгенеренного масива вроде того, что делает FillArray.
Или запросить всё сразу, а потом переставить:
procedure Ttest.Vopros(nomer:integer); type TOtvet = record Text: string; Verno: Boolean; end; var Perestanovka: array[0 .. 4] of Integer; Otvet: array[0 .. 4] of TOtvet; I: Integer; begin DataModule2.Vopros.Locate('Номер',mass[nomer],[]);
for I := 0 to 3 do begin if I = 0 then DataModule2.Variant.First; else DataModule2.Variant.Next; Otvet[I].Text := DataModule2.Variant.FieldValues['Ответ']; Otvet[I].Verno := DataModule2.Variant.FieldValues['Правильный']=True; end;
FillArray(Perestanovka);
//варианты ответов RadioButton1.Caption:=Otvet[Perestanovka[0]].Text; if Otvet[Perestanovka[0]].Verno then RadioButton1.Tag:=1 else RadioButton1.Tag:=0;
RadioButton2.Caption:=Otvet[Perestanovka[1]].Text; if Otvet[Perestanovka[1]].Verno then RadioButton2.Tag:=1 else RadioButton2.Tag:=0;
RadioButton3.Caption:=Otvet[Perestanovka[2]].Text; if Otvet[Perestanovka[2]].Verno then RadioButton3.Tag:=1 else RadioButton3.Tag:=0;
RadioButton4.Caption:=Otvet[Perestanovka[3]].Text; if Otvet[Perestanovka[3]].Verno then RadioButton4.Tag:=1 else RadioButton4.Tag:=0; Label2.Caption:=inttostr(strtoint(Label2.Caption)+1); end;
Сообщение отредактировано: OCTAGRAM -
--------------------
If you want to get to the top, you have to start at the bottom
Как я понял, DataModule2.Vopros.Locate делает запрос из БД. Сам этот запрос, наверное, можно изменить так, чтоб был случайный порядок (ORDER BY RANDOM()). Или ORDER BY IFF(id MOD 4 = 0, …, …), где перебираются все возможные остатки id от деления на 4 и в зависимости от этого подставляются номера из случайно сгенеренного масива вроде того, что делает FillArray.
Или запросить всё сразу, а потом переставить:
procedure Ttest.Vopros(nomer:integer); type TOtvet = record Text: string; Verno: Boolean; end; var Perestanovka: array[0 .. 4] of Integer; Otvet: array[0 .. 4] of TOtvet; I: Integer; begin DataModule2.Vopros.Locate('Номер',mass[nomer],[]);
for I := 0 to 3 do begin if I = 0 then DataModule2.Variant.First; else DataModule2.Variant.Next; Otvet[I].Text := DataModule2.Variant.FieldValues['Ответ']; Otvet[I].Verno := DataModule2.Variant.FieldValues['Правильный']=True; end;
FillArray(Perestanovka);
//варианты ответов RadioButton1.Caption:=Otvet[Perestanovka[0]].Text; if Otvet[Perestanovka[0]].Verno then RadioButton1.Tag:=1 else RadioButton1.Tag:=0;
RadioButton2.Caption:=Otvet[Perestanovka[1]].Text; if Otvet[Perestanovka[1]].Verno then RadioButton2.Tag:=1 else RadioButton2.Tag:=0;
RadioButton3.Caption:=Otvet[Perestanovka[2]].Text; if Otvet[Perestanovka[2]].Verno then RadioButton3.Tag:=1 else RadioButton3.Tag:=0;
RadioButton4.Caption:=Otvet[Perestanovka[3]].Text; if Otvet[Perestanovka[3]].Verno then RadioButton4.Tag:=1 else RadioButton4.Tag:=0; Label2.Caption:=inttostr(strtoint(Label2.Caption)+1); end;
Спасибо большое, изменила код на присланный вами. Варианты ответов стали меняться. Только вот вопросы, в принципе как и раньше, повторяются следуя сразу друг за другом, и с каждым новым прохождением повторение увеличивается.
Есть гипотеза, что в начало Ttesti.Button2Click надо добавить
DataModule2.Vopros.First;
Спасибо большое, теперь не повторяются. А вы не подскажете еще как написать, чтобы можно было ставить разное количество баллов, а не только 1. Чтобы выводилась сумма баллов и ее % от максимума и правильные ответы на те вопросы, по которым тестируемый дал неверные ответ.
А вы не подскажете еще как написать, чтобы можно было ставить разное количество баллов, а не только 1. Чтобы выводилась сумма баллов
Например, в RadioButton3.Tag ставить не 0 или 1, как сейчас, а 0 или баллы за вопрос. DataModule2.Vopros.FieldValues['Баллы'].AsInteger или что-нибудь вроде того. Сложение уже делается так, что менять сильно не надо.
Цитата(Vera @ 10.12.2017 15:24)
и ее % от максимума
Можно параллельно реальной сумме баллов вести сумму балов, сколько могло бы быть максимум. Я заметил, вы не используете нормальный механизм для этого, приватные поля, а вместо этого всё держите в метках и гоняете из числа в строку и обратно постоянно. Я не вижу, mass — глобальная переменная или поле, но рядом с ним не мешало бы побольше данных хранить в типизированном виде. Можно, конечно, завести невидимый TLabel под текущий максимум баллов. Или при подведении итогов запрос к базе данных сделать на максимум. В конце умножить реальную сумму на 100 и поделить целочисленно (div) на максимум. Это будут проценты.
Цитата(Vera @ 10.12.2017 15:24)
и правильные ответы на те вопросы, по которым тестируемый дал неверные ответ.
Для этого можно (если не сильно заботиться о типизации) завести поле типа string и при неправильных ответах дописывать в него информацию о том, какой был правильный и какой правильный:
А вы не подскажете еще как написать, чтобы можно было ставить разное количество баллов, а не только 1. Чтобы выводилась сумма баллов
Например, в RadioButton3.Tag ставить не 0 или 1, как сейчас, а 0 или баллы за вопрос. DataModule2.Vopros.FieldValues['Баллы'].AsInteger или что-нибудь вроде того. Сложение уже делается так, что менять сильно не надо.
Цитата(Vera @ 10.12.2017 15:24)
и ее % от максимума
Можно параллельно реальной сумме баллов вести сумму балов, сколько могло бы быть максимум. Я заметил, вы не используете нормальный механизм для этого, приватные поля, а вместо этого всё держите в метках и гоняете из числа в строку и обратно постоянно. Я не вижу, mass — глобальная переменная или поле, но рядом с ним не мешало бы побольше данных хранить в типизированном виде. Можно, конечно, завести невидимый TLabel под текущий максимум баллов. Или при подведении итогов запрос к базе данных сделать на максимум. В конце умножить реальную сумму на 100 и поделить целочисленно (div) на максимум. Это будут проценты.
Цитата(Vera @ 10.12.2017 15:24)
и правильные ответы на те вопросы, по которым тестируемый дал неверные ответ.
Для этого можно (если не сильно заботиться о типизации) завести поле типа string и при неправильных ответах дописывать в него информацию о том, какой был правильный и какой правильный:
А потом при подведении итогов в MessageDlg написать + FText в конце. #13#10 — это спецсимволы CR и LF, перенос строки в Windows.
С полем FText не получается, про % тоже не понятно, чтобы выводилось в таком виде (if (...<=100) and ...r>=80) then t:=5 и тд). mass глобальная переменная.
Там расписывать надо, какой вопрос, какой был выбран ответ и какой ответ был правильным.
Эту информацию, как я понимаю, надо вытаскивать из элементов управления. Если не переделывать структуру (не переносить информацию в приватные поля), то это будут развесистые if'ы, сравнения тегов переключателей и т.п.
--------------------
If you want to get to the top, you have to start at the bottom