Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 08.02.2015, 15:33
Deman1986 Deman1986 вне форума
Прохожий
 
Регистрация: 03.11.2013
Сообщения: 32
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию генерация чисел

Уважаемы программисты помогите с решением задачи
генерацию набора цифр от нуля до девяти (количество объектов в наборе должно изменяться от одного до девяти, одинаковые цифры в наборе не допускаются);
вывод набора цифр пользователю в одной из определённых в индивидуальном задании графических форм в течение фиксированного промежутка времени;
вывод пользователю всех цифр (в заданной графической форме) для того, чтобы он мог указать, какие из них входили в набор;
индикация ошибок пользователя (при их наличии).
Графическая форма:
Римские цифры, словесная форма, цвет шрифта
реализовал вот так
Код:
unit main;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Timer1: TTimer;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

function DecToRoman(Decimal: LongInt): string;
const
Romans: array[1..9] of string =
('I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX');
  Arabics: array[1..9] of Integer =
  (1, 2, 3, 4, 5, 6, 7, 8, 9);
var
  i: Integer;
  scratch: string;
begin
  scratch := '';
  for i := 9 downto 1 do
    while (Decimal >= Arabics[i]) do
    begin
      Decimal := Decimal - Arabics[i];
      scratch := scratch + Romans[i];
    end;
  Result := scratch;
  end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
// числа от 1 до 9 включительно будут отображаться последовательно
Label1.Caption:=Label1.Caption +' ' + IntToStr(Random(8)+1);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//надо обязательно иницилизировать генератор
Randomize;
  Timer1.Interval := 5000; // 5 секунд
    Timer1.Enabled := false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Timer1.Enabled:=True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Timer1.Enabled := false;
end;

end.
Помогите пожалуйста дальше не получается. Спасибо
Ответить с цитированием
  #2  
Старый 08.02.2015, 15:50
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Ну как вариант — использовать метод распределения, иначе в дельфи можно только получить псевдослучайные числа.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
Этот пользователь сказал Спасибо M.A.D.M.A.N. за это полезное сообщение:
Deman1986 (13.02.2015)
  #3  
Старый 09.02.2015, 10:40
Deman1986 Deman1986 вне форума
Прохожий
 
Регистрация: 03.11.2013
Сообщения: 32
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Подскажите пожалуйста как реализоваьь я новичек в дельфи. Спасибо.
Ответить с цитированием
  #4  
Старый 09.02.2015, 20:59
lmikle lmikle сейчас на форуме
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,100
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Делал подобную задачу - перемешивание колоды карт.
Собственно, проблема данной задачи в том, что при прямой генерации для исключения повторения сгенерированного значения необходимо заного его генерировать. Такой алгоритм приводит к практически бесконечной генерации в конце списка.
Примененное решение заключалось в том, что производится не генерация самих значений (их список известен и конечен), а генерация их места в итоговом списке. Если позиция уже занята, то происходит просто поиск следующей свободной позиции (сдвиг).

Вот пример генерации:
Код:
procedure GetNumbers(var A : Array of Integer);
var
  I, Idx : Integer;
  B : Array [0..8] Of Integer;
begin
  If (Length(A) > 9) Or (Length(A) < 1)
    Then Raise Exception.Create('Input array should have length 1 to 9. ');

  // Init temp arrray
  For I := 0 to 8 Do B[i] := 0;

  // Generate list
  For I := 1 to 9 Do
    Begin
      Idx := Random(9);
      While B[Idx] <> 0 Do
        If Idx = 8 Then Idx := 0 Else Inc(Idx);
      B[Idx] := I;
    End;

  // Copy result to output array
  For I := Low(A) To High(A) Do A[i] := B[i];
end;

Пример использования. Пусть будут римские цифры:
Код:
// Return rome 1..9
function IntToRome(Value : Integer) : String;
const
  Romes : Array [1..9] Of String =
    ('I','II','III','IV','V','VI','VII','VIII','IX');
begin
  If Not (Value In [1..9]) 
    Then Raise Exception.Create('Value should be in range 1..9.');
  Result := Romes[Value];
end;

procedure Form1.Button1Click(Sender : TObject);
var
  N, I : Integer;
  A : Array Of Integer;
  S : String;
begin
  Randomize;
  N := Random(9)+1; // Random number of digits 1..9
  SetLength(A,N); // prepare the array
  GetNumbers(A); // Get values

  // Prepare and show result
  S := '';
  For I := Low(A) To High(A) Do
    Begin
      S := S + IntToRome(A[i]);
      If I < High(A) Then S := S + ', ';
    End;
  ShowMessage(S);
end;
Ответить с цитированием
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Deman1986 (13.02.2015)
  #5  
Старый 09.02.2015, 22:44
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

А можно и так ещё, в лоб
Код:
...
type
 rdm = array [{1} 0..9] of string;

procedure rds(var ds: rdm);
var
 i, p, b: integer;
 s, r: string;
begin
 i:= {1} 0;
 while i <= 9 do
  begin
   p:= Random(10);
   b:= Random(10);
   s:= ds[p];
   r:= ds[b];
   ds[p]:= r;
   ds[b]:= s;
   inc(i);
  end;
end;
пример использования
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
 i: integer;
 m: rdm;
begin
 Randomize;
 for i:= {1} 0 to 9 do m[i]:=  IntToStr(i); { IntToRome(i);}
 Edit1.Text:='';
 rds(m);
 for i:= {1} 0 to 9 {Random(8)+2} do Edit1.Text:= Edit1.Text + m[i];
end;
в фигурных скобочках - вариант с ромой и переменной длинной наборчика
Ответить с цитированием
  #6  
Старый 10.02.2015, 02:35
lmikle lmikle сейчас на форуме
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,100
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Да, можно прямым перемешиванием, хотя, при особом невезении, можно получить неперемешанный массив. Да, инициализацию массива забыл. И еще одна проблема в твоем коде - в моем варианте я всегда генерирую любое число от 1 до 9 не зависимо от длинны переданного массива. Именно поэтому используется временный массив, из которого потом производится копирование. Это не очень хорошо, если надо сгенерировать РЕАЛЬНО большую последоватиельность (например, если надо генерировать числа от 1 до, допустим, 1 млрд), памяти дополнительной много сожрет. С другой стороны, в твоем варианте все равно есть проблема, если надо сгенерировать любые 5 чисел из диапазона 1..9, как мне кажется, хотя очень внимательно не смотрел.
Ответить с цитированием
  #7  
Старый 10.02.2015, 07:04
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

В рамках поставленной задачи генерация здесь выходит и не нужна, достаточно банальной перестановки константных элементов массива.
"Микроскопы" лучше приберечь для более сложных ситуаций
Ответить с цитированием
  #8  
Старый 10.02.2015, 13:16
Deman1986 Deman1986 вне форума
Прохожий
 
Регистрация: 03.11.2013
Сообщения: 32
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Оригинально конечно получилось. Протестил спасибо большое. Вот так набрал в дельфи.
Код:
unit main;

interface

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

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

function IntToRome(Value : Integer) : String;
const
  Romes : Array [1..9] Of String =
    ('I','II','III','IV','V','VI','VII','VIII','IX');
begin
  If Not (Value In [1..9])
    Then Raise Exception.Create('значение должно быть в диапазоне 1..9.');
  Result := Romes[Value];
end;

procedure GetNumbers(var A : Array of Integer);
var
  I, Idx : Integer;
  B : Array [0..8] Of Integer;
begin
  If (Length(A) > 9) Or (Length(A) < 1)
    Then Raise Exception.Create('входной массив дорлжен иметь длину 1 to 9. ');

  // инициализация временного массива
  For I := 0 to 8 Do B[i] := 0;
 
  // генерация листа
  For I := 1 to 9 Do
    Begin
      Idx := Random(9);
      While B[Idx] <> 0 Do
        If Idx = 8 Then Idx := 0 Else Inc(Idx);
      B[Idx] := I;
    End;
 
  // копирование результатат в выходной массив
  For I := Low(A) To High(A) Do A[i] := B[i];
end;

procedure TForm1.Button1Click(Sender: TObject);
var
N, I : Integer;
  A : Array Of Integer;
    S : String;
begin
Randomize;
  N := Random(9)+1; // Random числа 1..9
    SetLength(A,N); // выделение памяти массиву
      GetNumbers(A);
// Отображение результата
S := '';
  For I := Low(A) To High(A) Do
    Begin
      S := S + IntToRome(A[i]);
      If I < High(A) Then S := S + ', ';
    End;
  ShowMessage(S);
end;

end.
А как сделать словестную форму и цвет?
Ответить с цитированием
  #9  
Старый 10.02.2015, 13:29
Аватар для Alegun
Alegun Alegun вне форума
LMD-DML
 
Регистрация: 12.07.2009
Адрес: Богородское
Сообщения: 3,025
Версия Delphi: D7E
Репутация: 1834
По умолчанию

Если словесная - это 'Один','Два','Три','итд.', то аналогично заменой содержимого текстового массива, а если звуком, то тогда туда нужно поместить имена звуковых файлов и воспроизводить их медиаплеером. Цветом (если это не 'Красный','Жёлтый','Зелёный','итд.') почти тоже самое, только вместо строк использовать в массиве тип TColor, напр. clRed
Ответить с цитированием
  #10  
Старый 11.02.2015, 01:51
lmikle lmikle сейчас на форуме
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,100
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

я специально вынес конвертацию в римские цифры в отдельную функцию.
По аналогии задается любой другой вид. Фактически, у тебя в сгенерированном массиве индексы элементов массива значений. Т.е. собственно, надо просто брать элемент из нужного массива.

Пусть у нас есть RadioGroup c 2 вариантами - Римские цифры (0) и Слова (1).
тогда:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
N, I : Integer;
  A : Array Of Integer;
    S : String;
begin
Randomize;
  N := Random(9)+1; // Random числа 1..9
    SetLength(A,N); // выделение памяти массиву
      GetNumbers(A);
// Отображение результата
S := '';
  For I := Low(A) To High(A) Do
    Begin
      Case RadioGroup1.ItemIndex Of // не помню как точно св-во нвзывается
        0 : S := S + IntToRome(A[i]);
        1 : S := S + IntToWord(A[i]);
        Else Raise Exception.Create('Unknown transformation.');
      End;
      If I < High(A) Then S := S + ', ';
    End;
  ShowMessage(S);
end;

Функцию IntToWord сам напишешь по аналогии...
Ответить с цитированием
  #11  
Старый 12.02.2015, 14:31
Deman1986 Deman1986 вне форума
Прохожий
 
Регистрация: 03.11.2013
Сообщения: 32
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Я сделал немного по хитрому добавил вторую кнопку с названием "Словестная форма"
Код:
unit main;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Timer1: TTimer;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.dfm}

function IntToRome(Value : Integer) : String;
const
  Romes : Array [1..9] Of String =
    ('I','II','III','IV','V','VI','VII','VIII','IX');
begin
  If Not (Value In [1..9])
    Then Raise Exception.Create('значение должно быть в диапазоне 1..9.');
  Result := Romes[Value];
end;

function IntToWord(Value : Integer) : String;
const
  Wordes : Array [1..9] of String =
    ('Один','Два','Три','Четыре','Пять','Шесть','Семь','Восемь','Девять');
begin
  If not (Value In [1..9])
    Then Raise Exception.Create('значение должно быть в диапазоне Один..Девять.');
  Result := Wordes[Value];
end;

procedure GetNumbers(var A : Array of Integer);
var
  I, Idx : Integer;
  B : Array [0..8] Of Integer;
begin
  If (Length(A) > 9) Or (Length(A) < 1)
    Then Raise Exception.Create('входной массив дорлжен иметь длину 1 to 9. ');

  // инициализация временного массива
  For I := 0 to 8 Do B[i] := 0;
 
  // генерация листа
  For I := 1 to 9 Do
    Begin
      Idx := Random(9);
      While B[Idx] <> 0 Do
        If Idx = 8 Then Idx := 0 Else Inc(Idx);
      B[Idx] := I;
    End;
 
  // копирование результатат в выходной массив
  For I := Low(A) To High(A) Do A[i] := B[i];
end;

procedure TForm1.Button1Click(Sender: TObject);
var
N, I : Integer;
  A : Array Of Integer;
    S : String;
begin
Randomize;
  N := Random(9)+1; // Random числа 1..9
    SetLength(A,N); // выделение памяти массиву
      GetNumbers(A);
// Отображение результата
S := '';
  For I := Low(A) To High(A) Do
    Begin
        S := S + IntToRome(A[i]);
      If I < High(A) Then S := S + ', ';
    End;
  ShowMessage(S);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
N, I : Integer;
  A : Array Of Integer;
    S : String;
begin
Randomize;
  N := Random(9)+1; // Random слова Один..Девять
    SetLength(A,N); // выделение памяти массиву
      GetNumbers(A);
// Отображение результата
S := '';
  For I := Low(A) To High(A) Do
    Begin
        S := S + IntToWord(A[i]);
      If I < High(A) Then S := S + ', ';
    End;
  ShowMessage(S);
end;

end.
вот так получилось
Ответить с цитированием
  #12  
Старый 12.02.2015, 14:34
Deman1986 Deman1986 вне форума
Прохожий
 
Регистрация: 03.11.2013
Сообщения: 32
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

а еще вопросик, можно как нибудь на таймер это все завязать, что выводил сообщение с определённым интервалом времени. спасибо
Ответить с цитированием
  #13  
Старый 12.02.2015, 15:43
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Сам то как думаешь?
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #14  
Старый 13.02.2015, 11:16
Deman1986 Deman1986 вне форума
Прохожий
 
Регистрация: 03.11.2013
Сообщения: 32
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

все спасибо всем огромное разобрался.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 21:50.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025