Главная » Free Pascal » Знакомство с простыми программами Free Pascal

0

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

ЗАДАЧА 2. 1

Необходимо написать программу, которая вычислит и выведет на экран результаты в виде таблицы (табл. 2.1).

Таблица 2.1

x

sin(x)

cos(x)

0.0

0.000000

1.000000

0.1

0.099833

0.995004

0.2

0.198669

0.980067

0.3

0,295520

0.955336

0.4

0.389418

0.921061

0.5

0.479426

0.877583

0.6

0.564642

0.825336

0.7

0.644218

0.764842

0.8

0.717356

0.696708

0.9

0.783327

0.621610

Обратите внимание на то, что в таблице аргумент x задается в радианах. Хоте- лось бы написать более универсальную программу, которая выводит k строк по- добной таблицы, начиная с заданного значения x0. Приведенный выше фрагмент таблицы должен получиться при k=10 и x0=0.

Самый простой (и одновременно самый тупой) вариант тела программы может состоять из строк, представленных в листинге 2.1.

   Листинг 2.1. Программа  table1                                               

program table1; var

x:double; begin

writeln(‘x’,’   sin(x)’,’   cos(x)’); x:=0.0;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x));

x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x)); x:=x+0.1;

writeln(x,sin(x),cos(x));

end.

В программе table1 использована единственная переменная с именем x, кото- рая может принимать вещественные значения с удвоенной точностью (тип double). Первый оператор writeln предназначен для вывода заголовка таблицы. Его три аргумента представлены строковыми константами, которые, в принципе, можно было бы объединить в одну строку. Затем переменной x присваивается начальное значение. Операция присваивания, образованная двумя символами :=, унаследова- на Паскалем от своего предшественника — языка АЛГОЛ-60. После этого 10 раз повторяется пара операторов, которая выводит на экран значения x, sin(x) и cos(x) и увеличивает значение переменной x на 0.1.

В поле редактора FPC IDE эта программа выглядела бы следующим образом

(рис. 2.1).

Рис. 2.1. Внешний вид первого варианта программы

Попытка запустить эту программу (команда Run ® Run) будет приостановлена средой, предлагающей сначала сохранить текст, набранный в поле  редактора (рис. 2.2). Такое сохранение вновь набранного или только что модифицированного текста надо обязательно делать перед запуском программы, т. к. во время ее вы- полнения могут произойти непредвиденные события, и текст программы может пропасть.

Рис. 2.2. Окно для сохранения текста программы

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

<Alt>+<F5>. Однако, чаще всего перед заключительным end вставляют оператор

readln, который приостановит работу программы до нажатия клавиши <Enter>.

Результаты, выданные программой и приведенные на рис. 2.3, очень слабо на- поминают вид таблицы, указанной в задании. Во-первых, по умолчанию использо- ван так называемый "научный формат" записи вещественных чисел. Символ "E" означает, что число, расположенное слева, надо умножить на 10 в степени, распо- ложенной справа. Во-вторых, нам выдано слишком много значащих цифр.

Рис. 2.3. Выдача результатов программы table1.pas

С этим легко побороться — достаточно в операторе writeln после каждого вы- водимого значения указать его общую длину и количество цифр в дробной части:

writeln(x:4:1, sin(x):10:6, cos(x):10:6);

Однако самая большая нелепость в первом варианте программы заключается в десятикратном повторении однотипных операций. Любой алгоритмический язык, и Free Pascal в том числе, предусматривает возможность циклического повторения таких действий. Этих способов не один, мы воспользуемся оператором цикла for. В результате второй вариант нашей программы будет выглядеть так, как представ- лено в листинге 2.2.

   Листинг 2.2. Программа  table2                                               

program table2; var

x:double;

k:integer;        {целое, счетчик циклов} begin

writeln(‘x’,’   sin(x)’,’   cos(x)’);

x:=0;

for k:=1 to 10 do {тело цикла повторяется 10 раз}

begin           {начало тела цикла} writeln(x:4:1,sin(x):10:6,cos(x):10:6); x:=x+0.1;

end;            {конец тела цикла}

readln;           {задержка для просмотра результатов} end.

Второй вариант программы выводит результаты в соответствии с заданием. Единственная небрежность — заголовок таблицы немного смещен относительно столбцов соответствующих значений (рис. 2.4).

Рис. 2.4. Усовершенствованный вывод

Это легко исправить, добавив к оператору вывода заголовков указание о тре- буемой длине выводимого текста или нужное количество пробелов в соответст- вующих текстовых константах:

writeln(‘ x’,’   sin(x)’,’   cos(x)’);

Завершая работу над первой программой, мы можем включить в нее ввод таких данных, как начальное значение x и количество k выводимых строк таблицы (лис- тинг 2.3).

   Листинг 2.3. Программа  table3                                               

program table3; var

x:double;

j,k:integer;      {j – счетчик циклов} begin

readln(k,x);      {ввод исходных данных} writeln(‘ x’,’   sin(x)’,’   cos(x)’);

for j:=1 to k do  {тело цикла повторяется k раз} begin

writeln(x:4:1,sin(x):10:6,cos(x):10:6);

x:=x+0.1;

end; readln;

end.

Обратите внимание на ввод числовых данных по запросу программы — в на- шем примере программа остановит свою работу на первом же операторе тела про- граммы и будет ждать завершения ввода значений k и x с клавиатуры. Между на- бираемыми значениями должен быть хотя бы один пробел. Внутри чисел пробелы

недопустимы, ибо они рассматриваются как разделители числовых данных. При- знаком завершения набора является нажатие клавиши <Enter>.

ЗАДАЧА 2. 2

Натуральное число N называется простым, если оно имеет только два разных делите- ля — 1 и само себя. Примеры простых чисел — 2, 3, 5, 7, 11, 13, … Некоторые матема- тики считают, что 1 не является простым числом, т. к. имеет единственный делитель. Считать 1 составным числом тоже нет никакого резона. Задачей нашей следующей про- граммы является запрос у пользователя числа N и анализ его на простоту.

В математике известен достаточно сложный алгоритм такого анализа, требую- щий минимального числа операций. Но мы воспользуемся следующим алгоритмом, более затратным по времени, но более простым по реализации. Если число N — четное и не равно 2, то оно составное. Если N — нечетное, то будем делить его на последовательные нечетные числа (3, 5, 7, 9, 11, …,  M, где M не превосходит    N ) и анализировать остатки от деления. Первый же нулевой остаток свидетельствует о том, что N — составное число. Если все остатки будут отличны от 0, то N — про- стое.

Первый вариант программы, реализующий описанный алгоритм, может выглядеть так, как представлено в листинге 2.4.

   Листинг 2.4. Программа  prime1                                               

program prime1;

const

msg1=’ is prime'; msg2=’ is not prime';

label

m1;

var

d,N: word;                     {целое, без знака}

msg: string;                   {строка сообщения} begin

write(‘N = ‘);                 {вывод приглашения}

readln(N);                     {ввод N}

msg := msg1;                   {на случай, если N простое}

if N<4 then goto m1;            {при N<4 – простое}

msg := msg2;                   {на случай, если N составное} if not odd(N) then goto m1;     {при N четном – составное} d:=3;                          {первый делитель – 3}

while d*d<=N do                {пока делитель меньше корня из N}

begin

if (N mod d)=0 then goto m1; {если остаток = 0}

d:=d+2;                    {увеличение делителя на 2} end;

msg:=msg1;

m1:

writeln(N,msg);                {вывод сообщения } readln;

end.

В этой программе появились новые объекты и операторы. Во-первых, в разделе констант мы заготовили два сообщения — msg1 и msg2, одно из которых по резуль- татам анализа будет присвоено переменной строкового типа msg. Во-вторых, у нас появился раздел меток, в котором описана метка m1. Метка располагается перед оператором, на который планируется переход с помощью оператора goto, и отде- ляется от него двоеточием. В-третьих, мы воспользовались операцией mod, которая находит остаток от деления двух целочисленных операндов. Еще одна новая функция odd принимает значение "истина" (true), если ее аргумент нечетный. На- конец, в нашей программе активно используется условный оператор if, который в случае истинности заданного условия выполняет оператор, расположенный вслед за служебным словом then. Если заданное условие не выполнено, то срабатывает оператор, следующий за if.

Предположим, что для решения каких-то других задач нам потребуется не один

раз заниматься подобным анализом. В этом случае было бы полезно выделить фрагмент проверки на простоту в отдельную функцию, например, с именем prime, которая бы возвращала логическое значение true (истина), если ее аргумент — простое число. Тогда второй вариант программы мог бы выглядеть так, как пред- ставлено в листинге 2.5.

   Листинг 2.5. Программа  prime2                                               

prog prime2; var

N: Word;

function prime(N:Word):boolean; var

d: Word; begin

Result:=true;

if N<=3 then exit; Result:=false;

if not odd(N) then exit; d:=3;

while d*d<=N do

begin

if (N mod d)=0 then exit; d:=d+2;

end;

Result:=true; end;

begin

write(‘N = ‘); readln(N);

if N=0 then exit;

if prime(N) then writeln(N,’ is prime’) else writeln(N,’ is not prime’);

readln;

end.

Количество строк во втором варианте увеличилось незначительно, зато струк- тура основной программы стала предельно простой. Кроме того, здесь использован относительно новый для Паскаля способ формирования значения функции с помо- щью системной переменной Result. Он имеет некоторые преимущества перед тра- диционным для многих алгоритмических языков способом:

prime:=true;

или

prime:=false;

Впервые появившийся оператор exit завершает работу функции или основной программы. Но суть главного выигрыша вы поймете, оценив идею формирования следующей программы.

Пример работы программы prime2 приведен на рис. 2.5.

Рис. 2.5. Анализ простых чисел

ЗАДАЧА 2. 3

В 1742 г. Христиан Гольдбах высказал предположение, что любое четное число можно представить в виде суммы двух простых чисел, а любое нечетное — в виде суммы трех простых чисел. Если принять, что 1 является простым числом, то вторая часть гипотезы Гольдбаха автоматически вытекает из первой. В 2000 г. известный английский книгоиз- датель Фейбер даже объявил о награде в 000 000 тому, кто докажет или опровергнет эту гипотезу. Приз пока не востребован. Задача нашей следующей программы — запро- сить четное число N и найти хотя бы одно его разложение на сумму двух простых чисел (то, что задача имеет не единственное решение, вытекает из конкретных примеров: 4 = 2 + 2 и 4 = 1 + 3).

Идея реализуемого алгоритма предельно проста. Пусть, например, N=a+b и a<=b. Будем перебирать в цикле всевозможные слагаемые: a от 1 до N/2 и b=N-a. Если оба слагаемых окажутся простыми, то искомое разложение найдено. Естест- венно включить в нашу новую программу функцию анализа на простоту (лис- тинг 2.6), построенную в предыдущем примере.

Листинг 2.6. Программа Goldbach

program Goldbach; var

N,a: word;

function prime(N:Word):boolean;

…         {текст функции можно скопировать сюда}

end;

begin

write(‘N = ‘); readln(N);

if odd(N) then exit;     {выход, если N – нечетное} for a:=1 to N div 2 do

if prime(a) and prime(N-a) then begin

writeln(N,’=’,a,’+’,N-a);

end; readln;

end.

В новой программе впервые использована операция целочисленного деления div. Она позволяет найти целочисленное частное от деления двух целочисленных операндов. Использование обычной операции деления (/) в данном случае привело бы к ошибке — конечное значение управляющей переменной a в цикле for может быть только целочисленным. В Паскале обычная операция деления (/), даже цело- численных операндов, всегда приводит к вещественному результату. Это еще одно

принципиальное отличие языка Паскаль, например, от языка C. В последнем опе- раторе if записано составное логическое условие, которое принимает значение "истина" только при истинности обоих операндов, объединенных операцией "И" (and).

Программа  Goldbach находит все разложения четного числа на сумму двух

простых. Очень жаль, что за нее нельзя получить хотя бы часть вознаграждения, обещанного Фейбером. Примеры работы программы приведены на рис. 2.6.

Из этого примера вы должны усвоить один из важнейших приемов программи- рования: если вам удалось выделить некоторый типовой алгоритм в процедуру или функцию, то в последующем это поможет сократить время на разработку и отладку новых программ.

Рис. 2.6. Разложение четных чисел

ЗАДАЧА 2. 4

В четвертом задании мы продемонстрируем самый примитивный алгоритм сортировки элементов числового массива. Программа должна будет запросить количество N сорти- руемых целочисленных данных, ввести их с клавиатуры, отсортировать в порядке воз- растания и вывести отсортированный массив.

Алгоритм сортировки "в лоб" организован следующим образом. Сначала пер- вый элемент массива a[1] сравнивается со всеми последующими элементами. Как только обнаруживается элемент a[j], который меньше, чем a[1], их значения ме- няются местами. Добравшись до последнего элемента a[N], мы добились того, что на первом месте оказалось наименьшее число. Затем мы начинаем сравнивать эле- мент a[2] со всеми остальными. И так продолжается до тех пор, пока неотсортиро- ванными остаются a[N-1] и a[N]. Последнее сравнение либо оставляет все на сво- их местах, либо приводит к перестановке последней пары.

Описанный алгоритм реализуется с помощью программы из листинга 2.7.

Листинг 2.7. Программа sort_num

program sort_num; var

a: array [1..100] of integer;

N: byte;  i,j: byte; tmp: integer;

begin

write(‘N=’);            {приглашение ко вводу N}

readln(N);              {ввод N}

for i:=1 to N do         {цикл ввода элементов массива} begin

write(‘a[‘,i,’] = ‘); readln(a[i]);

end;

for i:=1 to N-1 do       {внешний цикл сортировки}

for j:=i+1 to N do     {внутренний цикл сортировки} if a[i]>a[j] then    {сравнение элементов}

begin             {блок перестановки пары a[i] и a[j]} tmp:=a[i];

a[i]:=a[j]; a[j]:=tmp;

end;

for i:=1 to N do         {цикл вывода отсортированного массива} writeln(a[i]);

readln; end.

В этой программе появились новые типы данных. Во-первых, массив a, объяв- ляемый с помощью служебного слова array (массив), вслед за которым указывает- ся диапазон изменения индексов элементов массива (от 1 до 100) и их тип (integer). Во-вторых, для переменных i, j, N выбран тип byte, обеспечивающий хранение данных в диапазоне от 0 до 255. Элемент a[i] сравнивается со всеми ос- тальными — a[j]. Поэтому в цикле по i появился вложенный цикл по j. Наконец, для перестановки пары a[i] и a[j] понадобилось использовать временную пере- менную tmp. Соответствующий блок перестановки данных — достаточно широко используемый программистский прием.

Результат работы программы сортировки приведен на рис. 2.7.

ЗАДАЧА 2. 5

Применим описанный выше алгоритм для сортировки фамилий. Два строковых значения в Паскале сравниваются побуквенно — сначала первая буква первого операнда с пер- вой буквой второго операнда, затем сравниваются вторые буквы и т. д.

Так как коды букв во внутренней кодировке компьютера упорядочены по алфа- виту, то сравнение строк ничем не отличается от сравнения чисел. Поэтому новая программа (листинг 2.8) получится из предыдущей путем мизерных переделок.

Рис. 2.7. Сортировка числового массива

   Листинг  2 .8 . Программа  sort_nam                                             

program sort_nam; var

a: array [1..100] of string [20];

N: byte; i,j: byte;

tmp: string [20];

begin

write(‘N=’);           {приглашение ко вводу N}

readln(N);             {ввод N}

for i:=1 to N do       {цикл ввода элементов массива} begin

write(‘a[‘,i,’] = ‘); readln(a[i]);

end;

for i:=1 to N-1 do     {внешний цикл сортировки}

for j:=i+1 to N do   {внутренний цикл сортировки} if a[i]>a[j] then  {сравнение элементов}

begin            {блок перестановки пары a[i] и a[j]} tmp:=a[i];

a[i]:=a[j]; a[j]:=tmp;

end;

for i:=1 to N do       {цикл вывода отсортированного массива} writeln(a[i]);

readln; end.

Теперь элементы массива a могут хранить строковые значения длиной до 20 сим- волов. Переменную tmp тоже пришлось объявить типа string [20].

Пример работы программы сортировки фамилий приведен на рис. 2.8.

Рис. 2.8. Сортировка фамилий

Построенная программа сортировки фамилий спасует, если вводимые фамилии содержат буквы "ѐ" или "Ё", т. к. их числовые коды не соответствуют порядку букв в русском алфавите. Если в обычных словарях между большими и малыми буквами разница не делается, то в компьютерных программах приходится учитывать, что коды малых букв больше, чем коды любой большой буквы. Поэтому при составле- нии программы, которая должна игнорировать это различие, приходится поступать следующим образом: во всех сортируемых словах коды букв приводятся к одному регистру, т. е. либо все заменяется только на большие буквы, либо только на ма- лые. В алгоритмических языках даже предусмотрены специальные функции такого рода, но в большинстве своем они правильно обрабатывают буквы латинского ал- фавита и обычно не изменяют все остальные символы. Не так уж и сложно напи- сать собственную программу, правильно обрабатывающую русские тексты. В по- следующих главах мы покажем, как это делается.

ЗАДАЧА 2. 6

Еще одна программа, связанная с обработкой символьной информации. Она должна

определить, является ли введенная фраза палиндромом. Один из наиболее цитируемых в литературе палиндромов — фраза "А роза упала на лапу Азора". Произношения ее при чтении слева направо и справа налево звучат одинаково. Естественно, что при этом не обращают внимания на разницу в больших и малых буквах и не учитывают располо- жение пробелов в строке и ее перевертыше.

Чтобы не усложнять алгоритм очередной программы, мы будем считать, что введенная фраза S1 набирается только малыми буквами. Первым нашим шагом должно стать удаление пробелов, мешающих решению задачи. Устранив пробелы и получив строку S2, мы сформируем строку S3, в которой символы следуют в об- ратном порядке. Если строки S2 и S3 окажутся равными, то введенная фраза явля- ется палиндромом.

Описанный выше алгоритм реализуется программой из листинга 2.9.

   Листинг 2.9. Программа  palindrome                                           

program palindrome; var

S1,S2,S3: string; j,n: byte;

begin

write(‘S1 = ‘);                   {приглашение ко вводу}

readln(S1);                       {ввод S1}

S2 := ”;                         {чистка S2}

for j:=1 to length(S1) do          {цикл удаления пробелов} begin

if S1[j] = ‘ ‘ then continue;

S2 := S2 + S1[j];            {присоединение не пробела} end;

S3 := S2;                        {для выравнивания длин S2 и S3}

n := length(S2);

for j:=1 to n do                 {цикл переворота S2} S3[j] := S2[n+1-j];

if S2=S3 then writeln(‘S1 – palindrome’)  else writeln(‘S1 – not palindrome’);

readln;

end.

В этой программе мы впервые использовали функцию length, которая позволя- ет определить длину строки, т. е. количество содержащихся в ней символов. Еще одна специфика этой программы — возможность выделить тот или иной символ

строки по его номеру, например, S1[j] или S3[j]. Символы в строке нумеруются с 1, их можно читать или присваивать им новые значения. В цикле удаления пробе- лов важную роль играет оператор continue (продолжить), после которого продол- жение тела цикла обходится, но сам цикл продолжается. В этом же цикле исполь- зована операция конкатенации (от англ. concatenation — сцепка), обозначаемая знаком +. Ее действие сводится к присоединению второго операнда вслед за по- следним символом первого операнда. Еще одна деталь, на которую следует обра- тить внимание, связана с использованием полной  формы  условного  оператора if… then… else (если… то… иначе). Оператор, расположенный справа от then, не должен завершаться точкой с запятой. Точка с запятой в Паскале считается при- знаком конца оператора, тогда как фрагмент else… является не самостоятельным оператором, а всего лишь продолжением предыдущего фрагмента.

Работа программы palindrome продемонстрирована на рис. 2.9.

Рис. 2.9. Анализ палиндромов

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

графические платы оснащаются десятками и сотнями графических сопроцессоров, обеспечивающих фантастическую производительность за счет параллельного вы- полнения типовых процедур в задачах визуализации игровых сцен. Эти средства начинают проникать не только в индустрию игрового "софта", но и в системы вир- туальной реальности, используемые в кино и на телевидении, в системы визуализа- ции результатов научных экспериментов и т. д.

ЗАДАЧА 2. 7

Задача нашей "игровой" программы существенно проще — она должна перетасовать колоду карт, которую предполагается использовать при реализации какой-нибудь кар- точной игры. В программах карточных игр предлагаются различные способы кодировки

карт. Мы остановимся на самом примитивном способе, когда каждой карте колоды при- своен порядковый номер, например, от 1 до 36 или от 1 до 52.

Идея алгоритма базируется на использовании датчика случайных чисел. Пред- ставим себе, что в нашем распоряжении имеется физический (типа лототрона) или программно реализованный датчик случайных чисел из диапазона [1, N], где N равно 36 или 52. Первоначально наша колода напоминает фабричную упаковку карт, в которой все разложено по мастям и внутри каждой масти по возрастающим номиналам — 2, 3, 4, …, 10, валет, дама, король, туз. Это соответствует тому, что коды карт образуют последовательность натуральных чисел — 1, 2, 3, …, N. Обра- щаемся к датчику случайных чисел и получаем число k, принадлежащее диапазону [1..N]. Меняем местами первый элемент массива A[1] с элементом A[k]. Затем повторяем аналогичную операцию достаточно много раз, например 10 000. После этого первоначальный массив A окажется достаточно хорошо перемешанным. И если последовательность случайных чисел, выдаваемых генератором, окажется непред- сказуемой, то такой алгоритм можно взять на вооружение.

В арсенале стандартных функций языка Паскаль имеется функция random(M), которая при каждом новом обращении выдает очередной элемент последователь- ности равномерно распределенных случайных целых чисел из диапазона [0, M-1]. Ею мы и воспользуемся в новой программе (листинг 2.10).

Листинг 2.10. Программа mixer

program mixer; const

Nmax=36;

var

A: array [1..Nmax] of byte; j,k,tmp: byte;

begin

for j:=1 to Nmax do

A[j]:=j;              {формируем фабричную "колоду"} for j:=1 to 10000 do

begin

k:=random(Nmax)+1;

tmp:=A[1]; A[1]:=A[k]; A[k]:=tmp;

end;

for j:=1 to Nmax do      {цикл вывода перетасованной колоды} write(A[j]:4);

readln;

end.

Обратите внимание на использование в программе константы Nmax. Если мы перейдем на колоду из 52 карт, то нам понадобится изменить единственную строч- ку в программе. Без константы Nmax такой переход потребовал бы изменения в че- тырех операторах.

Первый же запуск программы mixer приводит к вполне приличным результа- там (рис. 2.10). Каждое число из диапазона [1..36] представлено по одному разу (т. е. дублирующихся карт нет), да и об их порядке тоже ничего плохого сказать нельзя.

Рис. 2.10. Структура перетасованной колоды карт

Но второй запуск программы mixer приводит к тем же результатам. Такого по- втора в карточной игре терпеть нельзя. Игра с заранее известным порядком карт в колоде — это не игра. Причина кроется в работе системной функции random(). Ко- гда она вызывается в первый раз, то в ее теле присутствуют две начальные кон- станты, назовем их x и y. По вполне определенному алгоритму из них генерируется новое случайное число z. Перед тем как возвратить результат z, функция осущест- вляет пересылки y®x и z®y. Теперь становится понятным, что при повторном за- пуске программы функция random() начинает свою работу с тех же самых значе- ний x и y, и последовательность "случайных" чисел снова повторяется.

Для того чтобы "возмутить" начальное состояние программы random, использу-

ется процедура randomize, которая, применяя различные ухищрения, непредска- зуемым образом изменяет значения начальных констант x и y. Например, это мож- но сделать по текущему показанию системных часов, меняющих свое состояние каждую миллисекунду (листинг 2.11).

   Листинг 2 .1 1 .  М од иф ик а ция  програ ммы  mixer                                  

program mixer; const

Nmax=36; var

A: array [1..Nmax] of byte; k,tmp: byte;

j: integer; begin

randomize;              {возмущаем датчик случайных чисел} for j:=1 to Nmax do

A[j]:=j;              {формируем фабричную "колоду"}

for j:=1 to 10000 do

begin

k:=random(Nmax)+1;

tmp:=A[1]; A[1]:=A[k]; A[k]:=tmp;

end;

for j:=1 to Nmax do      {цикл вывода перетасованной колоды} write(A[j]:4);

readln; end.

На рис. 2.11 приведены результаты пяти последовательных запусков модифи- цированной программы mixer. Теперь ее можно использовать при разработке кар- точных игр.

Рис. 2.11. Результаты работы модифицированной программы mixer

Источник: Кетков, Ю. Л., Свободное программное обеспечение. FREE PASCAL для студентов и школьников, Ю. Л. Кетков, А. Ю. Кетков. — СПб.: БХВ-Петербург, 2011. — 384 с.: ил. + CD-ROM — (ИиИКТ)

По теме:

  • Комментарии