Показать сообщение отдельно
  #4  
Старый 21.12.2023, 15:31
xchgeaxeax xchgeaxeax вне форума
Прохожий
 
Регистрация: 11.05.2023
Сообщения: 15
Версия Delphi: D7, Laz v2.2.6
Репутация: 10
По умолчанию

Не знаю что вы там поменяли. Я вам говорил про другое. Сейчас вы загружаете данные в два разных списка и предполагаете, что они будут синхронизированы по индексам. Но что, если из одного файла удалят одну строку, а из второго другую (с разными индексами). Тогда все ваши данные станут не верными. Я же вам сказал Загрузить данные в связанные структуры в памяти. Т.е. сделайте так:
Код:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Buttons, StdCtrls;

type
  TResults = packed record
    question: String;
    answer: Boolean;
    user_ans: LongInt;
  end;
  TQWSArray = array of TResults;

  { TForm1 }

  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    Memo1: TMemo;
    procedure BitBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    qws: TQWSArray;
    idx: LongInt;
    procedure GetResults();
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
const
  qwsFileName = 'qws.txt';
var
  tmp: TStringList;
  i: LongInt;
begin
  tmp := TStringList.Create;
  if FileExists(qwsFileName) then
    tmp.LoadFromFile(qwsFileName);
  SetLength(qws, tmp.Count);
  for i := 0 to tmp.Count - 1 do with qws[i + Low(qws)] do begin
    question := copy(tmp[i], 2, Length(tmp[i]));
    answer   := tmp[i][1] = '1';
    user_ans := -1;
  end;
  tmp.Free;
  if Length(qws) > 0 then begin
    idx := Low(qws);
    Memo1.Text := qws[idx].question;
  end else
    GetResults();
end;

procedure TForm1.BitBtnClick(Sender: TObject);
var
  answer: Boolean;
begin
  answer := (Sender as TBitBtn).Tag = 1;
  if answer = qws[idx].answer then
    qws[idx].user_ans := 1
  else
    qws[idx].user_ans := 0;
  inc(idx);
  if idx <= High(qws) then
    Memo1.Text := qws[idx].question
  else
    GetResults;
end;

procedure TForm1.GetResults;
const
  ansFileName = 'ans.txt';
var
  i, c: LongInt;
  tmp: TStringList;
begin
  c := 0;
  BitBtn1.Visible := False;
  BitBtn2.Visible := False;
  Memo1.Clear;
  Memo1.Lines.Add('Результаты:');
  for i := Low(qws) to High(qws) do begin
    case qws[i].user_ans of
      1: Memo1.Lines.Add(qws[i].question + ' Ответ: Да');
      0: Memo1.Lines.Add(qws[i].question + ' Ответ: Нет');
    else
      Memo1.Clear;
      Memo1.Lines.Add('Ошибка в результатах теста');
      Exit;
    end;
    c := c + qws[i].user_ans;
  end;
  tmp := TStringList.Create;
  if FileExists(ansFileName) then begin
    tmp.LoadFromFile(ansFileName);
    if c < tmp.Count then
      Memo1.Lines.Add(tmp[c])
    else
      Memo1.Lines.Add('Результат не определен!');
  end;
  tmp.Free;
end;

end.
Как-то так. Теперь ошибка если и будет, то только в результатах подсчёта баллов, но зная точную цифру его можно поправить. И не получится ошибиться в сопоставлении строк в разных файлах т.к. и вопросы и ответы сохранены в одном файле. Но вопрос начинающийся с символа отличного от 1 будет требовать ответа "Нет", а с 1 в начале - "Да". Но эти символы анализируются один раз при загрузке данных из файла в память и попадают в отдельную переменную (поле структуры) до того, как пользователь ответит на вопрос. При этом переменная с ответами на вопросы от пользователя изначально содержит значение -1, но при прохождении того или иного вопроса получает значение 0 или 1. Дальше они просто суммируются и результат уже выбирается из файла, в котором перечислены строки с ответами на разное число очков. Это можно упростить, если добавить к ответам описания диапазонов. Но это уже сделаете сами.
Ответить с цитированием