Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Самоучитель игры на Паскале. АВС и немного Турбо

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
end; end;
Не хватает только того, что внутри цикла – самого главного, правда. Начнем с малого и простого – выведем самую первую строку, ту в которой числа 1,2,3…9. Цикл от одного до девяти у нас уже есть, значение того, что надо вывести, удивительным образом совпадает со значением переменной цикла. Поскольку все числа выводятся в одн строке, подойдёт оператор Write(i); не переходящий посл новую строку. Чтобы все числа не склеились в одно длинное слово, укажем количество выводимых знаков – у нас это будет четыре – одна/две цифры и три/два пробела спереди. А поскольку на следующую строку перейти всё-таки когда-то надо, добавим после завершения внутреннего цикла оператор Writeln; без параметров.
for i:=1 to 9 do begin {цик for j:=1 to 9 do begin {цикл по столбцам} Write(j:4); end; Writeln; end;
В результате получили повторенную девять раз одну и ту же строку
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
и т.д.
Логично, ведь от переменной I, управляющей выводом по строкам, наш
ератор Write(i:4); ну никак не зависит. А как он должен зависеть?
оп Элементарно – число на пересечении I-й строки и J-го столбц представляет собой их произведение. Делаем вот так - Write(i*j:4); Гораздо лучше –
1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18
л по строкам}
е вывода на
ой
а
121
3 6 9 12 15 18 21 24 27
Собственно, то, что и хотели получить. Добавить строчку сверху труда не составляет, надо только позаботиться добавить соответствующее число пробелов перед ней и пустую строку после неё.
Write(‘ ‘); for j:=1 to 9 do Write(j:4); Writeln; Writeln;
Переменная цикла J использована из принципиальных соображений – раз она у нас в основном цикле отвечает за перемещение по горизонтали – так путь отвечает за это везде. begin и end отсутств можно и так. Почему Writeln в двух экземплярах, думайте сами. Теперь добавим вертикальную строчку. Вывести её в отдельном мысль не очень хорошая. Можно конечно теоретически использовать GoToXY, но зачем нам лишние приключения? Рассуждаем так. Где должна стоять цифра? Перед строкой с результатами. Одна строка – одн цифра. Перед строкой – значит перед циклом, выводящим строку. Цифра соответствует номеру строки, который соответствует значени переменной цикла I. И вот, наконец, программа:
Write(‘ ‘); for j:=1 to 9 do Write(j:4); Writeln; Writeln;
for i:=1 to 9 do begin {цикл по строкам} Write(i:4); for j:=1 to 9 do begin {цикл по столбцам} Write((i*j):4); end; Writeln;
уют, напоминая, что
цикле
ю
а
122
end;
А теперь, самостоятельно, бодро-весело, рисуем шахматную доску. И подумайте, как посимпатичнее выбирать, в какой цвет какой квадрат покрасить. Посимпатичнее, не в смысле, чтобы красный и зеленый, а чтобы соответствующий условный оператор был бы не слишком страшен.
Всё сразу и побольше
Циклы и массивы созданы друг для друга. Двумерные массивы и
женные циклы – вообще, наверное, символ мировой гарм
вло без друга им просто не жить. Сначала несколько простых примеров, из серии “это должен знать каждый”. Массив предполагается объявленным как
var a : array[1..N,1..M] of integer;
То есть, массив вовсе даже не квадратный.
Задача номер раз. Заполнить массив нулями:
for i:=1 to N do for j:=1 to M do a[i,j]:=0;
Номер два. Посчитать сумму эл
sum:=0; for i:=1 to N do for j:=1 to M do sum:=sum + a[i,j];
Три. Найти минимальный элемент массива:
min:=a[1,1];
ементов массива:
онии. Друг
123
for i:=1 to N do for j:=1 to M do if a[i,j] < min min:=a[i,j];
Наверное, Вам уже всё понятно. Вообще, двумерные массивы очень хорошо проецируются на математические реалии. Двумерный массив – это матрица, а количество математических манипуляций с матрицами воистину безгранично. Но это напоминает мне о трудной юности и курсе высшей алгебры и, вообще, не будем об этом!
м две задачки для самостоятельной работы.
А Ва Первая. Повернуть квадратный масс
1 2 3 4 5 6 9 8 9
Должно получиться:
9 4 1 8 5 2 9 6 3
Вторая задачка посложнее. Заполнить квадратный массив “змейкой”, начиная с левого нижнего угла. Для массива размерностью 5x5 на выходе будет:
11 19 20 24 25 10 12 18 21 23 4 9 13 17 22 3 5 8 14 16 1 2 6 7 15
Разумеется, Ваша программа должна работать с квадратным массивом любой размерности. Как это технически бу сказано, в языках в этом месте может быть и переменная, но у нас допустима только
Паскале размерность массива – константа. В некоторых других
ив набок. То есть, было:
дет реализовано? Как уже
124
константа. Что делать? Например, объявить большой-большой массив, сто на сто, например, и передать в процедуру в качестве параметра его фактическую размерность, то есть какую часть из него заполнять. Некрасиво? Учите Фортран!
Другие циклы
Циклы, с которыми мы встречались до сих пор, в одном отношении были совершенно одинаковы. Они мо тысячу или сто тысяч миллионов раз, выполняться от единицы до миллиона или от миллиона до единицы, но число выполнений цикла нам было известно зара миллион.
Упрощаю, конечно. Число выполнений цикла могло и не быть константой. Могло быть и переменной. Но с мат зрения
– какая разница? Всё равно значение переменной этой известно до начала выполнения цикла. Прощу прощения у чистых математиков за вольную трактовку понятий переменной и константы. Конечно, если они, чистые математики, их вообще понимают…
А если число выполнений заранее неизвестно? А почему? Самый частый случай – когда есть живой пользователь. Например, запрограммировали мы игрушку. И пользователь наш радостно долбит по клавишам, устанавливая справедливость в одном отдельно взятом подвале. И когда он, зараза, утом нам не дано. Вот тут и нужен цикл, который выполняется столько раз, сколько не знаем заранее. К монстрам, по попытаемся придумать бол применение для такого рода циклов. К сожалению, на ум идёт исключительно математика, причем не простая, а всё как-то высшая. Постараемся, однако, обойтись без жертв. Без лишних. Напишем цикл (обычный):
for i:=1 to 5 do Writeln((1/i):5:3);
нее, ещё при написании программы. Миллион – так
двалам и сп
гли выполняться пять раз, десять раз, сто,
ематической точки
ится долбить по клавишам, предугадать
раведливости вернемся позже, а пока
ее мирное, без живого пользователя,
125
На выходе получим
1.000
0.500
0.333
0.250
0.200
Если бы мы вывели эти значения в виде не десятичных дробей, а натуральных, то получили бы следующее:
1
/3, ¼, 1/
1, ½,
5
Эта последовательность называется гармоническим рядом. Как её продолжить дальше, вопросов не вызывает –
1
/6, 1/7, 1/8…У неё есть одна
особенность – если сложить достаточное количество его членов, то в сумме можно получить любое заранее заказанное число.
Это значит, что ряд расходится. Полюбуйтесь на ряд 1, ½, 1/4, 1/8, 1/16… Он сходится. Это не просто значит, что он не расходится. Это значит, что его сумма бесконечно и беспечально приближается к некоему числу. Осознание (и даже доказательство) этого факта лежит в пределах понимания любого не совсем деградировавшей особи. Слово “особь” использовано исключительно для исключения возможности какой-либо гендерной сегрегации. Не поняли – завидую вашей неиспор Cм. выше про неиспорченность.
ченности. Кстати, ряды бывают ещ
ё не расходящимися и не сходящимися одновременно. Не поняли?
Поставим себе такую задачу (вовсе не искусственную, а вполне себе встречающуюся в реальной жизни) – вначале ввести какую-то значение (сумму), а затем определить, сколько элементов ряда нам надо просуммировать, чтобы его (её) достичь. Начинаем с простого – объявляем необходимые переменные, вводим ввод и выводим вывод:
program series; uses Crt; var sum : real; {сколько надо получить в сумме} factS
um : real;
{сколько фактически имеем в сумме}
126
x : real; {текущий член ряда} howMany : integer; {ответ - сколько членов просуммировали} i : integer; {а это переменная цикла, которая нам } {вообще не понадобится}
begin
ClrScr; Write(‘Sum = ‘); Readln(sum);
{а вот тут получаем ответ}
Writeln(‘how many = ’ howMany); end.
Если выразить человеческим языком то, что от нас требуется, получим примерно следующее: вначале ответ равен нулю. Затем, пока сумма меньше требуемой, вычисляем очередной чле отв
ет. Так до тех пор, пока фактическая сумма не превысит сумму
требуемую. Теперь запишем это на Паскале, и будем разбираться.
howMany:=0; factSum:=0; while (factSum < sum) do begin howMany:=howMany + 1; x:=1/howMany; factSum:=factSum + x; end;
Внимательно рассматриваем и извлекаем самое существенное.
while (условие) do begin {чего-то делаем} end;
Условие здесь – самое обычн операторе. То, что внутр
н ряда, прибавляем его к сумме, увеличиваем
ое условие, такое же, как и в условном
и цикла (там, где сейчас комментарий), будет
127
выполняться до тех пор, пока условие истинно. В нашем случае – пока фактическая сумма не достигла требуемой величины. То есть – проверили условие, выполнили цикл, проверили условие, выполнили цикл, и так пока условие вдруг не окажется ложным. Обратите внимание – сначала проверили условие, затем выполнили цикл. Утром деньги, вечером стулья. А если нет денег, в смысле усл выполняется? Не будет и выполнения цикла. Может быть такая ситуация, когда цикл не выполнится ни раз набрать нулевую или, того лучше, отрицательную сумму. Зачем что-то суммировать – ноль у нас и так уже с самого начала есть. А можно утром стулья? Можно. Разработчики Паскаля, исходя из высших педагогических соображений, предусмотрели и этот вариант.
На мой взгляд, можно было бы и обойтись. Лучше бы они предусмотрели оператор в
Цикл, который сначала выполняется, а потом думает – а стоило ли оно того. Выглядит он попричудливее. Перепишем нашу программу с его применением.
howMany:=0; factS
repeat
howMany:=howMany + 1; x:=1/howM factSum:=factSum + x; until (factSum >= sum);
Исполняемая часть цикла теперь заключена между repeat и until. Условие поменялось на противоположное. Цикл теперь выполняется не до тех пор, пока условие выполняется, а до тех, пока оно ложно. Как только условие выполнится – исполнение цикла прекращается. Зато цикл выполнится как минимум один раз. Обратите внимание, во выполняться вечно:
while true do begin
озведения в степень. Но это я так, к слову…
um:=0;
any;
зможно пригод
у. В нашем примере – если захотеть
ится. Вот такой цикл while будет
овие не
128
end;
А вот такой цикл вообще ни разу:
while false do begin end;
Вариант repeat-until и его вечно выполняющийся цикл
repeat until false;
Для цикла repeat-until вариант, не выполняющийся ни разу, по понятным причинам невозможен. А теперь скрестим… Кого мы ещё не скрещивали? Ну, например двумерные массивы и только что ос Есть такая игра – пятнашки. Напоминаю – такая коробочка, рассчитанная на шестнадцать фишек, четыре на четыре. Но фишек не шестнадцать, а пятнадцать, одн от единицы до пятнадцати. Фишки, тщательно перетасовав, помещают в коробочку. Задача – не вынимая фишек из коробки, только передвигая, пользуясь при этом для мане нормальный порядок вещей - расставить фишки по рядам от первой до пятнадцатой. Ну если непонятно объяснил, извините. Показываю на примере.
До того:
12 13 1 4 3 15 6 9 14 2 5 6 7 8 10
После того:
1 2 3 4 5 6 7 8
о место в коробочке остаётся пустым. На фишках числа –
военные другие циклы.
вра свободной клеткой, восстановить
129
9 10 11 12 13 14 15
На данный момент, наша задача – перетасовать. То есть, случайным образом расставить в коробочке пятнадцать фишек. Какие варианты? Вариантов, как часто случается, ровно два. Или перебираем все первые пятнадцать свободных посадочных мест в коробке. Случайным образом определяем на первое свободное место одну из фишек, вначале – одну из пятнадцати. Определив фиш вычёркиваем её из числа доступных к расстановке, и, в следующий раз, уже выбираем одну из четырнадцати оставшихся. Ну и так дале Вариант номер два. Берём фишку, от первой до пятнадцатой, пытаемся её поставить в коробочку, совершенно куда попало. Если место свободно, то уже хорошо. Если занято, пытаемся снова. Когда-нибудь, да повезёт. Мне больше нравится второй вариа и помнить, какая фишка уже поставлена, а какая ещё нет. Во втором случае у нас цикл по фишкам от первой до пятнадцатой – и помнить нечего. Нет, конечно, надо помнить, где какая фишка уже стоит, но это ведь надо помнить в любом случае? Излагаем словесно:
Цикл по количеству фишек
Цикл пока не найдём свободного места дл Попытаться фишку пристроить
Просто и ясно. Первый цикл, как уже много раз было сказано, от единицы до пятнадцати. Для второго цикла очень даже подойдёт repeatuntil. Ведь как минимум одну по Не совсем хорошая особенность нашего алгоритма – мы не можем гарантировать, что он завершится. Ну бывает же так, что каждый раз - и мимо! Конечно, вероятность незавершения нашего алгоритма за сколько­то заметное время сопоставима с вероятностью одномоментного выхода всех молекул кислорода из комнаты. С одной стороны, это вряд ли. С другой стороны, если бы мы программирование я лично поотрывал бы все ручки. Но у нас не ракета, сойдёт. В результате:
пытку расстановки предпринять мы долж
нт. В первом случае надо отслеживать
я фишки
программировали ракету на Марс, за такое
ку на место,
е.
ны.
130
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]