Книга: Delphi. Учимся на примерах

Разработка программного кода

Разработка программного кода

Для начала, объявим все глобальные переменные:

var
 Form1: TForm1;
 i, a, n, balls, vopr: integer; {различные счетчики и переменные для подсчета баллов}
 dir, dir2, ss, zz, yes: string; {путь к файлу с вопросами, к программе и расшифрованной базе}
 win: TIniFile; //переменная для работы с ini-файлами
 mass: array[1..100] of integer; {содержит номера уже заданных вопросы, чтобы они не повторялись}
 f1, f2: file of char; //переменные для работы с файлами
 сор: char; //для работы с каждым символом отдельно

Добавим в раздел uses ссылку на модуль IniFiles, который потребуется для работы с классом TIniFile. Мы также разработаем четыре собственные процедуры. Объявим их как закрытые члены класса формы:

type
TForm1 = class(TForm)
 …
private
 { Private declarations }
 procedure start; //начало теста
 procedure question_select; //выбор вопроса
 procedure vars(var variant: integer); {сортировка и определение правильного варианта ответа}
 procedureverno(); {проверка: правильно ли ответил пользователь}
public
 { Public declarations }
end;

Теперь создадим сами процедуры в разделе implementation. Процедура Start:

procedure TForm1.start();
begin
 Randomize; //Включаем генератор случайных чисел
 for i:=1 to n do mass[i] := 0; //n – количеству вопросов
 {$I-} //отключаем контроль ошибок ввода/вывода.
 //делаем все элементы видимыми для пользователя
 Memo1.Visible:= True;
 RadioGroup1.Visible:= True;
 Label1.Visible:= True;
 an1.Visible:= True;
 an2.Visible:= True;
 an3.Visible:= True;
 an4.Visible:= True;
 p1.Visible:= True;
 p2.Visible:= False;
 p3.Visible:= False;
 p4.Visible:= False;
 p5.Visible:= False;
 balls:= 0;
 Label2.Visible:= False; //прячем результаты
 Label1.Caption:= 'Первый вопрос:';
 dir2:= 'C:base.bsd'; //путь к расшифрованной базе
 //копируем зашифрованную базу на диск С:
 CopyFile(PChar(ss), PChar(dir2), True);
 //связываем переменную f1 с зашифрованным ini-файлом
 AssignFile(f1, ss);
 //связываем переменную f2 с файлом C:base.bsd
 AssignFile(f2, dir2);
 Reset(f1); //открываем первый файл на чтение
 Rewrite(f2); //второй – на запись
 while not Eof(fl) do
 begin //пока не достигнут конец первого файла
  Read(f1, cop); //считываем один символ из файла
  сор:= Chr(Ord(cop) xor 101); //расшифровываем символ
  Write(f2, сор); //записываем расшифрованный символ в файл
 end;
 CloseFile(f1); //закрываем первый файл
 CloseFile(f2); //закрываем второй файл
 {$I+} //включаем контроль ошибок ввода/вывода
 Win:= TIniFile.Create(dir2); //работаем с ini-файлом
 //считываем количество вопросов в базе
 ss:= Win.ReadString('num', 'num', ss);
 //преобразовываем строку в число и записываем значение в n
 n:= StrToInt(ss);
 vopr:=Random(4) + 1;
//случайное число от 1 до 4
 vars(vopr); {передаем число процедуре vars, которая сортирует варианты ответов}
end;

Эта процедура начинает игру. Сначала делаем все элементы видимыми и прячем метку, отображающую результат прохождения теста. Затем открываем файл, содержащий вопросы, и считываем из него по одному символу. Каждый байт расшифровывается особо и записывается в отдельный файл. Далее мы работаем с расшифрованным файлом как с обычным ini-файлом. Первое, что мы считываем, — это общее количество вопросов в базе.

Теперь очередь процедуры question_select:

procedure TForm1.question_seleсt();
label ran; //метка ran для быстрого перехода
begin
 Randomize;
ran:
 a:=Random(n); //выбираем случайный вопрос из базы
 //проверяем: не задавали ли мы этот вопрос ранее
 for i:=1 to n do
  if mass[i] = a then goto ran;
 for i:=1 to n do
  if mass[i] = 0 then begin
   mass[i]:= а; {записываем номер вопроса, чтобы не задавать его больше }
   Break;
  end;
 //сбрасываем флажки со всех вариантов ответов
 an1.Checked:= False;
 an2.Checked:= False;
 an3.Checked:= False;
 an4.Checked:= False;
end;

Эта процедура случайным образом выбирает вопрос. Затем выполняется проверка: не задавался ли этот вопрос ранее. Если мы нашли вопрос, который еще не был задан, то задаем его и помечаем как уже заданный, чтобы не задавать его больше в текущей сессии.

Процедура verno:

procedure TForm1.verno();
begin
 if an1.Checked then
  if yes = an1.Caption then balls:= balls + 1;
 if an2.Checked then
  if yes = an2.Caption then balls:= balls + 1;
 if an3.Checked then
  if yes = an3.Caption then balls:= balls + 1;
 if an4.Checked then
  if yes = an4.Caption then balls:= balls + 1;
end;

Здесь мы сравниваем правильный ответ с вариантом, который дал пользователь, и в случае правильного ответа пополняем счетчик правильных ответов.

Процедура vars:

procedure TForm1.vars(var variant: integer);
begin
 //вызываем процедуру выбора случайного вопроса question_select();
 case variant of
 1:
  begin
   Win:= TIniFile.Create(dir2); //открываем ini-файл
   //считываем вопрос
   Memo1.Text:= Win.ReadString('Q', IntToStr(a), Memo1.Text);
   //считываем правильный вариант ответа
   an1.Caption:= Win.ReadString('A', IntToStr(a), an1.Caption);
   //считываем три неверных варианта к данному вопросу
   an2.Caption:= Win.ReadString('W1', IntToStr(a), an2.Caption);
   an3.Caption:= Win.ReadString('W2', IntToStr(a), an3.Caption);
   an4.Caption:= Win.ReadString('W3', IntToStr(a), an4.Caption);
   Win.Free; //освобождаем ini-файл
   //помечаем первый вариант как правильный
   yes:= an1.Caption;
  end;
 2:
  begin
   Win:= TIniFile.Create(dir2);
   Memo1.Text:= Win.ReadString('Q', IntToStr(a), Memo1.Text);
   an2.Caption:= Win.Readstring('A', IntToStr(a), an2.Caption);
   an1.Caption:= Win.Readstring('W1', IntToStr(a), an1.Caption);
   an3.Caption:= Win.ReadString('W2', IntToStr(a), an3.Caption);
   an4.Caption:= Win.ReadString('W3', IntToStr(a), an4.Caption);
   Win.Free;
   yes: = an2.Caption;
  end;
 3:
  begin
   Win:= TIniFile.Create(dir2);
   Memo1.Text:= Win.ReadString('Q', IntToStr(a), Memo1.Text);
   an3.Caption:= Win.ReadString('A', IntToStr(a), an3.Caption);
   an2.Caption:= Win.ReadString('W1', IntToStr(a), an2.Caption);
   an1.Caption:= Win.ReadString('W2', IntToStr(a), an1.Caption);
   an4.Caption:= Win.ReadString('W3', IntToStr(a), an4.Caption);
   Win.Free;
   yes:= an3.Caption;
  end;
 4:
  begin
   Win:= TIniFile.Create(dir2);
   Memo1.Text:= Win.ReadString('Q', IntToStr(a), Memo1.Text);
   an4.Caption:= Win.ReadString('A', IntToStr(a), an4.Caption);
   an2.Caption:= Win.ReadString('Wl', IntToStr(a), an2.Caption);
   an3.Caption:= Win.ReadString('W2', IntToStr(a), an3.Caption);
   an1.Caption:= Win.ReadString('W3', IntToStr(a), an1.Caption);
   Win.Free;
   yes:= an4.Caption;
  end;
 end;
end;

Здесь мы вначале запускаем процедуру выбора вопроса. Потом проверяем: какой вариант ответа является правильным. Затем считываем вопрос и варианты ответов к нему. Сортируем и отображаем все это на форме.

Обработчик события создания главной формы будет выглядеть следующим образом:

procedure TForm1.FormCreate(Sender: TObject);
begin
 Randomize;
 //получаем каталог, в котором находится наша программа
 dir:= GetCurrentDir;
 ss:= dir + 'comp.ini'; //путь к базе вопросов
 zz:= ss;
 start(); //начинаем тест
end;

Теперь создадим обработчик события главной формы OnDestroy (возникает при выходе из программы):

procedure TForm1.FormDestroy(Sender: TObject);
begin
 DeleteFile('c:base.bsd'); //удаляем расшифрованную базу
end;

Теперь обрабатываем команды меню. Обработчик события OnClick для пункта Игра?Заново:

procedure TForm1.N1Click(Sender: TObject);
begin
 Randomize;
 ss:= zz;
 start(); //начало теста
end;

Поскольку у нас весь основной код вынесен в процедуры, теперь достаточно только вызвать процедуру начала игры.

Обработчик события OnClick для пункта меню Игра?Загрузить базу:

procedure TForm1.N2Click(Sender: TObject);
begin
 Randomize;
 //начинаем обзор с текущего каталога
 Open1.InitialDir:= GetCurrentDir;
 if not Open1.Execute then ShowMessage('Вы не выбрали файл!')
 else begin
  ss:= Open1.FileName; //открываем выбранный файл
  zz:= ss; //запоминаем путь к базе
  start(); //начинаем тест
 end;
end;

Здесь мы предлагаем пользователю выбрать через диалоговое окно обзора ini– или любой другой файл, в котором содержатся зашифрованные вопросы и варианты ответов. Когда пользователь выбрал файл, мы запускаем процедуру start и, тем самым, начинаем тест.

Обработчик события OnClick для пункта меню Игра?Выход:

procedure TForm1.N4Click(Sender: TObject);
begin
 Halt; //выход из программы
end;

Теперь обработаем щелчок мышью на панели p1:

procedure TForm1.p1Click(Sender: TObject);
begin
 Label1.Caption:= 'Второй вопрос:';
 verno(); //принимаем вариант ответа
 p1.Visible:= False; //убираем первую панель
 р2.Visible:=True; //активизируем вторую панель
 vopr:= Random(4) +1; //выбираем случайный вариант ответа
 vars(vopr); //задаем вопрос
end;

Здесь мы вначале изменяем заголовок на "Второй вопрос:", после чего принимаем вариант ответа, выбранный пользователем, вызывая процедуру verno.

Затем готовим форму ко второму вопросу: прячем первую панель и выводим вторую. Вызываем процедуру vars, которая выбирает вопрос и отображает его вместе с вариантами ответа.

Обработаем щелчок мышью на второй панели:

procedure TForm1.p2Click(Sender: TObject);
begin
 Label1.Caption:= 'Третий вопрос:';
 verno();
 p2.Visible:= False;
 p3.Visible:= True;
 vopr:= Random(4) + 1;
 vars(vopr);
end;

Здесь происходит то же самое, что и для панели p1, только надпись метки принимает значение "Третий вопрос", мы прячем вторую "кнопку" и активизируем третью для следующего вопроса.

Аналогичные обработчики события OnClick создаем для третьей и четвертой панелей:

procedure TForm1.p3Click(Sender: TObject);
begin
 Label1.Caption:= 'Четвертый вопрос:';
 verno();
 р3.Visible:= False;
 p4.Visible:= True;
 vopr:= Random(4) + 1;
 vars(vopr);
end;
procedure TForm1.p4Click(Sender: TObject);
begin
 Label1.Caption:= 'Пятый вопрос:';
 verno();
 p4.Visible:= False;
 p5.Visible:= True;
 vopr:= Random(4) + 1;
 vars(vopr);
end;

Для пятой (последней) панели обработчик события OnClick будет выглядеть несколько иначе:

procedure TForm1.p5Click(Sender: TObject);
begin
 //проверяем правильность ответа на последний вопрос
 verno() ;
 //узнаем, сколько баллов набрал пользователь
 ss:= IntToStr(balls);
 //делаем почти все компоненты невидимыми
 Memo1.Visible:= False;
 р5.Visible:= False;
 RadioGroup1.Visible:= False;
 Label1.Visible:= False;
 an1.Visible:= False;
 an2.Visible:= False;
 an3.Visible:= False;
 an4.Visible:= False;
 Label2.Visible:=True;//показываем метку с результатом
 Label2.Align:= alClient;//растягиваем ее на всю форму
 //Отображаем процент правильных ответов
 Label2.Caption:= 'Правильных ответов' + IntToStr(balls*(100 div 5))+'%';
end;

После проверки правильности ответа на последний вопрос, мы прячем почти все компоненты на форме, оставляя видимой только метку Label2 для вывода результата и меню, чтобы можно было продолжить работу с программой. С помощью метки мы отображаем процент правильных ответов пользователя по формуле: "количество правильных ответов * (100 / количество заданных вопросов)". Пример отображения результата теста представлен на рис. 13.3.


Рис. 13.3. Отображение результата теста

Единственное, что осталось сделать, — реализовать имитацию нажатия кнопки при щелчке на панели мышью. Для того чтобы "оживить" панель, для нее следует создать обработчики двух событий: OnMouseDown и OnMouseUp. Первое событие возникает при щелчке мышью, а второе — при отпускании кнопки мыши. Для панели pi эти обработчики будут выглядеть следующим образом:

procedure TForm1.p1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 p1.BevelInner:= bvLowered;
 p1.BevelOuter:= bvRaised;
end;
procedure TForm1.p1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 p1.BevelInner:=bvRaised;
 p1.BevelOuter:=bvLowered;
end;

Для всех остальных панелей обработчики этих событий будут выглядеть аналогичным образом за исключением того, что имя p1 потребуется изменить на имя р2, p3, р4 или р5.

Программа тестирования в действии показана на рис. 13.4.


Рис. 13.4. Программа тестирования в действии

Оглавление книги


Генерация: 0.028. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз