Комбинация операторов цикла и ветвления.

В теле цикла могут присутствовать любые операторы, в том числе и конструкция ветвления if. В этом случае вся конструкция ветвления должна «целиком» находиться внутри тела цикла. При движении по ветке ветвления также может выполняться цикл. Кроме того, циклы и ветвления могут следовать друг за другом.

Пример 1. Вывести на экран линию из 50 звездочек. Цвета звездочек должны чередоваться.

Решение. Будем использовать цикл for со счетчиком i. Если i четное, будем рисовать звездочку цветом 2, иначе цветом 3. i четное, если i mod 2=0.

var i:integer;

begin

for i:=1 to 50 do

begin

if i mod 2=0 then textcolor(2)

else textcolor(3);

write(‘*’);

end;

end.

Из программы видно, что на каждом шаге цикла проверяется условие. Оператор if находится внутри тела цикла. Элементы конструкции цикла изображены синим цветом, а конструкция if  – красным.

Пример 2. Прочитать с клавиатуры число n и нарисовать линию из n звездочек, если она помещается в экран. В противном случае сообщить об этом.

В этом примере после ввода n нужно проверить условие. Если оно истинно, то выполняется цикл, иначе выводится на экран сообщение. Получается цикл внутри конструкции if.

Решение

var i,n:integer;

begin

readln(n);

if n<=80 then

begin

gotoxy(1,1);

for i:=1 to n do

begin

textcolor(i);

write(‘*’);

end;

end

else

writeln(‘невозможно’);

end.

 

Задачи.

  1. Прочитать с клавиатуры x, y, n и вывести на экран вертикальную линию из синих нулей и зеленых единиц, начинающуюся в клетке (x,y).
  2. В предыдущей задаче линию выводить только если она помещается в экран.
  3. По диагонали, начиная с клетки (1,1) выводить последовательность 1,2,3,1,2,3,1,2…
  4. Вокруг экрана нарисовать следующий орнамент. Сначала, отступив от края экрана 3 клетки, нарисовать рамку из единичек так, чтобы их цвета чередовались – красный, синий, красный, синий. Затем, отступив 4 клетки, нарисовать рамку из нуликов так, чтобы их цвета чередовались - желтый, зеленый, желтый, зеленый.

 

Движущиеся объекты

Эта тема уже «веселенькая», она очевидно приблажает нас к игрушкам. Как запрограммировать «летящую» по экрану звездочку?

Принцип общий – как в любых фильмах. Нарисуем картинку, немного подождем, чтобы глаза успели на нее среагировать, затем поверх этой картинки нарисуем новую, потом опять подождем и так далее. Нужен цикл. В данном случае перерисовка картинки сводится к удалению звездочки на старом месте и рисованию на новом. Для того, чтобы приостановить выполнение программы на короткий срок, служит процедура delay из модуля crt. У нее один параметр – сколько миллисекунд нужно подождать. Если уменьшать этот параметр, звездочка будет двигаться быстрей. Его следует подобрать экспериментально – запуская программу несколько раз. Пусть звездочка бежит по первой строке экрана. Ее координату x будем хранить в переменной x. Звездочку будем перемещать и изменять x на 1 до тех пор, пока не она не добежит до правого края экрана, то есть x<79.

uses crt;

var x:integer;

begin

x:=1;

while x<80 do

begin

write(‘ ‘);

x:=x+1;

gotoxy(x,1);

write(‘*’);

delay(500);

end;

end.

Здесь оператор write(‘ ‘) удаляет звездочку на старом месте.

Задачи.

  1. Пусть теперь звездочка движется по диагонали до конца экрана.
  2. А теперь пусть звездочка движется по границе экрана один круг, после чего программа прекращает свою работу.
  3. Заставьте звездочку двигаться по диагонали до границы экрана.
  4. Пусть теперь звездочка движется по горизонтали и отражается от левой и правой границ. Подсказка. В примере мы на каждом шаге цикла прибавляли к x единицу. После отражения от правой стенки единицу придется вычитать. Поэтому оператор x:=x+1 следует заменить на x:=x+v. Сначала v=1. Если x=79, то есть мы добрались до правого края, то в переменную v нужно записать -1. Если мы добрались до левого края, то в переменную v запишем 1. Задача будет решена. На каждом шаге цикла нужно два раза проверять условие. Теперь цикл может выполняться вечно. Например, в условие после слова while можно записать 2>1. Запрограммируйте и запустите программу. Зациклилась? Аварийный выход из зациклившейся программы CTRL+PAUSE.
  5. Теперь пусть звездочка движется из центра экрана по диагонали, отражаясь от стенок. Подсказка. До сих пор нас интересовало изменение лишь одно координаты звездочки. В этой задаче необходимо изменять обе координаты. То есть вместо одного оператора x:=x+v нужна пара операторов x:=x+vx; y:=y+vy; Переменные vx и vy сначала равны 1, а затем изменяются при каждом отражении от стенок. На каждом шаге цикла нужно проверять 4 условия, так как стенок 4.
  6. Теперь пусть по горизонтали в первой строке экрана движется «0», а во второй строке движется «1». Здесь у каждой цифры должна быть своя координата и своя скорость. Например x0, x1, v0, v1. На каждом шаге цикла нужно стирать и 0, и 1, проверки достижения края экрана выполнять и для 0, и для 1 и рисовать нужно обе цифры. Внимание: delay будет только один – нарисовали обе цифры, подождали, стрели об цифры.
  7. Сделать так, чтобы 0 и 1 из задачи 6 двигались с разными скоростями. Это можно сделать несколькими способами. Видимо, оптимальный способ заключается в следующем. Пусть нужно сделать так, чтобы 1 двигалась в два раза быстрее, чем 0. Заведем счетчик шагов цикла. На каждом шаге цикла будем к нему прибавлять 1. Операции с 0 нужно проводить лишь в том случае, если счетчик четный. То есть понадобится еще проверка условий.

Тип данных char.

Переменные типа char предназначены для хранения символов – букв, цифр и различных специальных символов. Пример описания в разделе var

var a,b,c:char;

В теле программы переменной типа char можно присвоить занчение в операторе присваивания

a:=’e’;

Значение переменной можно прочитать с клавиатуры readln(a); и вывести на экран writeln(a).

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

В компьютере каждому символу сопоставлено некоторое число от 0 до 255. Это число называется кодом символа. Функция ord позволяет по символу определить его код. Пример

var

x:integer;

c:char;

begin

readln(c);

x:=ord(c);

writeln(x);

end.

Программа читает с клавиатуры символ. Затем записывает в переменную x код этого символа. Заметим, что x имеет тип integer, так как код – число. В конце программы x выводится на экран. Например, если ввести с клавитуры английскую букву a, программа выведет ее код 97.

Функция chr возвращает символ, код которого указан в скобках.

Пример. Прочитать с клавиатуры символ. Вывести на экран символ, код которого равен 1.

Решение.

var

a,b:char;

x:integer;

begin

readln(a);

x:=ord(a);

b:=chr(x+1);

writeln(b);

end.

Последнее важное замечание. Символы можно сравнивать в условиях. При этом сравниваются их коды, например

if x<>’e’ then…

Условие истинно, если в символьной переменной x записан символ, отличный от ‘e’.

Задачи

  1. Вывести на экран все символы и их коды. Для этого организуем цикл, в котором некоторая переменная меняется от 0 до 255. На экран выводить занчение переменной и символ (функция chr).
  2. Подобрать подходящие символы для рисования рамки вокруг экрана и для рисования движущего ся предмета. Предмет отражать от рамки. При ударе издавать звук. Для этого в модуле CRT имеется процедура sound с одним параметром – частотой звука в герцах. При выполнении процедуры sound(40); компьютер запускает звуковой динамик с частотой звука 40 герц. Для того, чтобы его отключить, должна быть выполнена процедура nosound; Параметров у этой процедуры нет.
  3. Сформировать из двух подходящих символов составной объект и организовать его движение как целого с отражением от стенок. В этом случае скорости у обоих символов будут всегда одинаковы.

Управление движущимися объектами. Цикл игры.

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

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

Во-первых, нужно проверить, была ли нажата какая-нибудь клавиша, то есть пуст или не пуст буфер. Для этого существует функция keypressed без параметров, которая возвращает значение «истина», если буфер не пуст. Эту функцию можно использовать в качестве условия if keypressed then…

Если клавиша была нажата, нужно выяснить, какая и, в зависимости от этого, выполнять те или иные действия. Функция readkey без параметров возвращает символ, код которого находится в буфере клавиатуры удаляет его из буфера. После оператора

c:=readkey;

в переменную c будет записан символ из буфера.

Если символа в буфере нет, то readkey ждет, пока его введут. При этом движение всех объектов в вашей игрушке остановится. Поэтому имеет смысл вызывать readkey только если keypressed возвратила значение «истина».

Приведем еще несколько полезных процедур. Процедура halt без параметров прекращает работу програмы. Процедура break без параметров прекращает цикл. Процедура continue без параметров пропускает все действия до конца тела цикла.

Пример. Звездочка движется по горизонтали. Движение начинается в цетре экрана. При нажатии кнопки ‘b’ она разворачивается. При достижении границ экрана или при нажатии клавиши ‘e’ программа заканчивает работу.

Решение

var

x,v:integer;

c:char;

begin

v:=1;

x:=40;

while 2>1 do

begin

if keypressed then

begin

c:=readkey;

if c=’e’ then halt;

if c=’b’ then v:=-v;

end;

if (x>79) or (x<2) then halt;

write(‘ ‘);

x:=x+v;

gotoxy(x,12);

write(‘*’);

delay(200);

end;

end.

Сделаем выводы по пройденным темам. Бесконечный цикл while называется циклом игры. Тело цикла всегда состоит из трех основных частей:

обработка сигналов от игроков

проверка особых ситуаций (в данном случае это достижение границ экрана)

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

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

Задачи

  1. Пусть теперь управляемый символ движется в любом из четырех направлений и отражается от стенок экрана. По нажатию клавиши ‘c’ символ меняет цвет.

Составные коды. Управление стрелками.

Хочется управлять объектами при помощи стрелок? Здесь есть одна проблема. При нажатии стрелки в буфер клавиатуры заносятся сразу два числа – 0 и код стрелки. Поэтому сначала при помощи Readkey вы прочитаете символ с кодом 0. Затем нужно еще раз выполнить readkey, чтобы достать из буфера код стрелки. Вторым будет прочитано следующее число:

стрелка вправо 77

стрелка влево 75

стрелка вниз 80

стрелка вверх 72

Заметим, что этим кодам соответсвтуют и обычные символы – заглавные английские буквы

77 M

75 K

80 P

72 H

При работе с обычными символами мы могли написать, например

if c=’e’…

У стрелки нет такого изображения, как у буквы ‘e’. Можно записать так

if ord(c)=72… или if c=’M’… или if c=chr(72)…

У последнего способа есть сокращенный вариант if c=#72…, который будем использовать ниже.

Таким образом, фрагмент программы, обрабатывающий нажатие стрелок приобретает следующий вид

if keypressed then

begin

c:=readkey;

if c=#0 then

begin

c:=readkey;

if c=#72 then….

if c=#75 then..

end

else

begin

if c=’e’ then halt;

end;

end;

Задачи.

  1. Реализовать управление стрелками движением звездочки.

Оператор выбора case.

Если нажатая клавиша может принимать очень много различных значений, то программа будет содержать много операторов if и значительно усложнится. Структуру программы можно значительно упростить, если использовать оператор выбора case, который оформляется так

case выражение of

значение1: begin операторы1 end;

значение2: begin операторы2 end;

значение3: begin операторы3 end;

значение4: begin операторы4 end;

else begin операторы end;

end;

После слова case следует записать любое выражение. Оно равно значение1, то будут выполняться операторы1, если значение2, то операторы2 и так далее. Если значение выражения не совпадает ни с одним из значений списка, то выполняются операторы, записанные после слова else. Вся конструкция case заканчивается словом end. Варианты отделяются от операторов двоеточием. Все ключевые слова конструкции показаны синим цветом. Вместо выражения можно поставить имя любой переменной. Если при некотором значении нужно выполнить только один оператор, то begin и end можно не ставить. На место значений можно записать как конкретные числа или символы, например 12, 6, ‘a’, так и перчислить сразу несколько возможных вариантов, например

case c of

‘a’: writeln(1);

‘b’,’e’,’g’:writeln(2);

‘1’..’9’:writeln(3);

‘n’..’k’,’f’:writeln(4);

else halt;

end;

В данном случае для всех цифр от ‘1’ до ‘9’ будет выведено число 3.

Задачи

  1. Запрограммировать управляемое движение звездочки с использованием case.
  2. Запрограммировать движение двух независимых управляемых объектов.
  3. «Догонялки». К предыдущей задаче добавить выход из программы, если объекты окажутся в одной точке.
  4. «Стрелялка». По небу с постоянной скоростью летит самолет. На земле стоит ракетный комплекс. По нажатию кнопки происходит пуск ракеты. Ракета летит вдвое быстрей самолета. Если произошло попадание, смаолет уничтожен. Детали продумать самостоятельно.
  5. К предыдущей игре добавить возможность перемещения ракетного комплекса по горизонтали на один шаг влево при нажатии клавиши ‘a’ и на один шаг вправо принажатии ‘d’.
  6. «Теннис». Мячик летает и отражается от стенок экрана. Теннисная ракетка движется по горизонтали внизу экрана аналогично комплексу из предыдущей задачи. От нижней границы мячик отражается только при попадании на ракетку.
  7. Теннис на двух игроков. Ракетка первого игрока перемещается винзу экрана, второго – вверху. Остальные детали продумать. Возможно регулирование скорости полета, начисление очков и прочее.
  8. Придумать свою динамическую игру.

Вложенные циклы.

В теле цикла может располагаться другой цикл, как показано на рисунке.

 

Пример. Заполнить звездочками весь экран.

Решение.

Внутренний цикл рисует звездочки на текущей строке. Внешний цикл перебирает строки.

var i,j:integer;

begin

for i:=1 to 24 do

begin

for j:=1 to 80 do write(‘*’);

writeln;

end;

end.

Задачи

Заполнить весь экран узорами вида:

 27. Из подходящих символов нарисовать во весь экран щахматную доску.

28. Красиво вывести на экран  таблицу умножения.