Главная / Информатика / Самоучитель игры на Паскале. ABC и немного Турбо

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

Документы в архиве:

37 КБ TP Бинарные файлы.doc
35 КБ TP Вся правда об указателях.doc
29 КБ TP И ещё кое.doc
29 КБ TP Как настроить.doc
33 КБ TP Как установить.doc
58.5 КБ TP Клавиатура и скан-коды.doc
36.5 КБ TP Модули - как оно на самом деле.doc
59 КБ TP Основы графики.doc
1.96 МБ TP Отладка.doc
25.5 КБ TP Поиск файлов.doc
3.94 МБ TP Просто программа - русификация - среда разработки.doc
22.5 КБ А о чём вообще речь.doc
2.15 КБ Clock.pas
8.68 КБ Tic.pas
6.12 КБ ATT.BGI
14.33 КБ BOLD.CHR
6.1 КБ CGA.BGI
2.09 КБ CLOCK.PAS
5.4 КБ EGAVGA.BGI
8.24 КБ EURO.CHR
17.64 КБ GOTH.CHR
5.98 КБ HERC.BGI
9.69 КБ IBM8514.BGI
11.8 КБ LCOM.CHR
5.01 КБ LITT.CHR
6.11 КБ NOTES.TPU
4.56 КБ Notes.pas
5.9 КБ PC3270.BGI
13.28 КБ SANS.CHR
3.52 КБ SCAN.PAS
3.39 КБ SCAN2.PAS
3.13 КБ SCAN2.TPU
10.73 КБ SCRI.CHR
8.24 КБ SIMP.CHR
5 КБ SONG.PAS
8.47 КБ TIC.PAS
16.29 КБ TRIP.CHR
16.95 КБ TSCR.CHR
6.2 КБ VESA16.BGI
47 КБ Опись вложения.doc
20 КБ Что тут лежит.doc

Название документа TP Бинарные файлы.doc

Бинарные

Бинарные файлы бывают типизированные и нетипизированные. Типизированные – для слабых духом. Для нас – только нетипизированные файлы.


Объявляем, открываем, записываем, закрываем.


var

f : file;

int : integer;

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


{открыть файл}

Assign( f, ‘a.bin’);

ReWrite( f, 1);


{записать что-то в файл}

BlockWrite( f, int, 2);


{закрыть файл}

Close(Txt);


Открытие бинарного файла очень похоже на таковое текстового. Только заметьте волшебную единицу в ReWrite. Так надо, поверьте!

Закрытие файла ничуть не изменилось.

А вот на записи остановимся подробнее.

Первый параметр – имя файла. Это понятно.

Второй параметр – имя переменной, значение которой мы хотим записать в файл.


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


Третий параметр это размер записываемой переменной, или, точнее, количество записываемых в файл байтов.


На самом деле и это не так. Циферка 1 в открытии файла означает размер блока в байтах, то есть минимального количества данных, которое можно записать в файл и, соответственно, прочитать из него. Третий параметр в BlockWrite означает на самом деле количество записываемых блоков. Кстати, если Вы забудете задать второй параметр в ReWrite, то размер блока будет по умолчанию установлен в 128.


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


Вместо

BlockWrite( f, int, 2);

пишем

BlockWrite( f, int, SizeOf(int));


Незатейливая, но очень полезная функция SizeOf возвращает количество байтов, занимаемых переменной.

Если мы хотим записать в файл весь массив A, то напишем следующее:


BlockWrite( f, a, SizeOf(a));

или

BlockWrite( f, int, 20);


Но если мы напишем


BlockWrite( f, int, 10);


то в файл попадут только первые пять элементов массива. Ещё раз – BlockWrite игнорирует, где кончается одна переменная, и где начинается другая.


А теперь чтение:


Assign( f, ‘a.bin’);

ReSet( f, 1);


BlockRead( f, int, 2);


Close(Txt);


Вроде бы всё понятно. ReWrite поменяли на ReSet, BlockWrite на BlockRead.

Маленькая разница между ReSet и ReWrite.

ReWrite. Если файл есть, то он его перепишет, как его и не было – уничтожив всё содержимое. Если файла нет, то он его создаст.

ReSet. Если файл есть, то он его откроет на чтение. Если файла нет – всё кончится очень плохо. Так что проверьте существование файла перед открытием с помощью FindFirst.

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

С бинарным файлом не так. Чтобы прочитать его содержимое, мы должны абсолютно точно знать, что же именно в этот файл было записано. Какие переменные, каких типов, какого размера, в каком порядке. Малейшая ошибка – и на выходе куча мусора.

Так в чём преимущество бинарных файлов? А в них можно записать всё. Нет, не так – ВСЁ! И вы это ещё оцените.


Бинарные файлы. Задачка

Задачка простенькая. Перекопировать существующий файл под другим именем. Если бы в модуле Dos была соответствующая процедура, то это было бы делом одной строчки. Но процедуры нет. Будем делать собственными ручками.

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


Ввести имя входного файла

Ввести имя выходного файла

Если входной файл существует

Цикл по количеству кусков

Прочитать кусок из входного файла

Записать кусок в выходной файл


Куски, безусловно, должны быть одинакового размера. Было бы хорошо, чтобы файл делился на куски без остатка. А на какое числа делится всё на свете без остатка? Правильно, на единицу! Следовательно, куски будут по одному байту. Цикл – по количеству байт в файле. А размер файла узнаем из записи SearchRec, он, размер, там есть.

Проверку на наличие файла выполним через единственный, без продолжения, FindFirst. Ну и не забыть – объявить файлы, открыть файлы, закрыть файлы.


program filecopy;

uses

Dos;

var

inname, outname : string;

infile,outfile : file;

SR : SearchRec;

b : byte;

i : integer;

begin

write('in name = ');

readln(inname);

write('out name = ');

readln(outname);

FindFirst( inname, AnyFile, SR);


if DosError = 0 then begin

Assign( infile, inname);

ReSet(infile,1);

Assign( outfile, outname);

ReWrite(outfile,1);


for i:=1 to SR.size do begin

BlockRead( infile, b, 1);

BlockWrite( outfile, b, 1);

end;


Close(outfile);

Close(infile);

end;

end.


И небольшой комментарий. Читаем из файла мы в переменную типа byte. С тем же успехом могли бы использовать char. Главное, что переменная занимает ровно один байт, ведь используем мы её, переменную, исключительно как временный буфер для хранения этого самого байта.


Название документа TP Вся правда об указателях.doc

Указатели

Как и обещано – самое-самое важное и самое-самое ужасное. Не то, что бы оно было тут очень нужно. Многие учебники начального уровня обходятся без указателей. Трудности видны сразу, а польза неочевидна. Но мне кажется, надо представлять, с чем придётся встретиться в реальной жизни. Дальше будет много непонятных слов и загадочных телодвижений. Смотрите и наслаждайтесь.

Как и файлы, указатели бывают типизированные и нетипизированные. И, как и в случае с фалами, нас интересуют только нетипизированные.

Как объявить указатель? Очень просто.


var

p : pointer;


А присвоить указателю значение? Это сложнее. Надо всё же объяснить сначала, что такое указатель.

Указатель, как и следует из своего имени, указывает. На что указывает? На область памяти. Понятно? Нет? Неважно, продолжаем. Вернее, возвращаемся к вопросу присваивания указателю значения.

Целой переменной можно присвоить другую целую переменную, вернее значение другой целой переменной, строке можно присвоить другую строку. Указатель не исключение. Объявляем:


var

p1,p2 : pointer;


Тогда можем написать


p1:=p2;


А смысл? Смысл в том, что указатель p1 имеет теперь тоже значение, что и p2 и указывает на ту же область памяти. А на что указывает p2?

Первый способ присвоить значение указателю (сначала добавим объявлений):


var

p1,p2 : pointer;

int1,int2,int3 : integer;

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


p1:=@int1;

p1:=Addr(int1);


Способ я пообещал один, но операторов написал два. Причина в том, что это синонимы. Оба выражения дают один и тот же результат – указатель p1 указывает на переменную int1. Разумеется, это не означает, что указатель имеет тоже значение, что и int1. Значение указателя вообще имеет мало отношения к значению переменной, на которую он указывает. Указатель – это адрес переменной.


p1:=@a;

p2:=@a[1];


На что указывают указатели? Первый – на массив A, второй – на первый элемент этого массива A[1]. В результате, значения этих двух указателей одинаковы, ведь массив начинается с первого элемента. Непонятно? Продолжаем.

Второй способ проинициализировать указатель – выделить память.

Выделение памяти – операция симметричная, в смысле, если память выделили, то её надо будет освободить. И ответственный за это Вы.

Выделяем:


GetMem( p1, 10);


Мы запросили (и получили) десять байтов. На эти десять байтов теперь указывает указатель p1. А что находится в этих десяти байтах? Да ничего.

Напоминаю – если память выделили, надо и освободить! Вот так:


FreeMem( p1, 10);


Тот же указатель, и тот же размер памяти. Никакого контроля нет! Отвечаете за всё Вы! Вы должны помнить, сколько байтов и для какого указателя были выделены. Постарайтесь не перепутать.

Еще раз – в переменной типа указатель хранится вовсе не значение переменной, на которую этот указатель указывает. Там хранится адрес этой переменной. А если написать вот так: P^ - то это будет уже область памяти, на которую указатель указывает. Использовать это обозначение (P^) “как есть” можно только в очень небольшом количестве случаев, в частности в BlockWrite и BlockRead.

Ещё одна новость. Для целых и дробных переменных есть нулевое значение. Для строки есть пустая строка. Указатель ничем не хуже. Для него существует специальный как бы указатель, который никуда не указывает. Выглядит присвоение пустого указателя вот так:


p:=nil;


nil – заранее определённая в Паскале константа. Это указатель, который никуда не указывает. Внутри у него банальный ноль. В случае обращения к памяти, на которую как бы указывает этот указатель, всё кончается очень и очень печально.

Для того, чтобы хоть что-то стало понятно, запрограммируем небольшую задачу. Задача уже была поставлена и решена – скопировать файл (небольшой) под другим именем. Решим её немного по-другому, избавившись от цикла. Зачем вообще здесь нужен цикл? Зная размер файла, мы читаем один байт из входного файла и записываем этот один байт в выходной файл. Наверное, было бы лучше прочитать весь входной файл сразу целиком, и сразу записать всё в выходной файл. Прочитать целиком – это хорошо, только куда? Указатель тут приходится как нельзя более кстати.

Вот этот текст из первой версии программы изымается:


for i:=1 to SR.size do begin

BlockRead( infile, b, 1);

BlockWrite( outfile, b, 1);

end;


И заменяется на такой:


GetMem( p, SR.size);

BlockRead( infile, p^, SR.size);

BlockWrite( outfile, p^, SR.size);

FreeMem( p, SR.size);


Переводим с паскалевского на русский:


Первая строка – выделена память в количестве SR.size байт. Адрес выделенной памяти содержится в указателе P.

Вторая строка – прочитано такое же количество байтов из входного файла. Прочитано по адресу, на который указывает указатель P, то есть P^.

Третья строка – аналогично, но теперь данные записаны в выходной файл.

Четвёртая, и последняя – память освобождена.


О технике безопасности.

Выделенная память должна быть освобождена, и в точности в том же количестве.

Сначала выделить, потом освободить. Не перепутайте.

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

Нельзя два раза освобождать память по одному указателю.

Вот здесь - BlockRead( infile, p^, SR.size); - должно быть именно P^. Если написать просто P, транслятор скушает. BlockRead отработает, ему всё равно. О последствиях даже говорить не буду, настолько они будут ужасны.

А почему я оговорился, что копировать мы будем небольшой файл? А потому, что в Турбо Паскале одному указателю можно выделить не более 64K памяти, точнее чуть меньше.


Итак, трудности и непонятности стоят во весь рост, польза где-то прячется. Но это так только кажется с первого взгляда.


Название документа TP И ещё кое.doc

И ещё кое-что

Если нажать Alt/F1, то мы попадём в оглавление справочной системы. Более того, если встать курсором на какое-нибудь умное слово, например integer и нажать Ctrl/F1 то мы получим справку по существу вопроса – в данном случае – справку по типу integer (точнее, справку по всем целым типам).

И всё бы хорошо, но справка на английском. Лично моё мнение, что ничего плохого в этом нет, а есть только полезное. Программист без знания технического английского языка в режиме чтения, подлежит немедленной утилизации в целях прекращения бесполезных страданий и освобождения занимаемых квадратных метров. Но некоторые стонут и плачут. Становится жалко.

Но есть, есть справка и по-русски! Необходима для этого подмена файла turbo.tph. Где искать? В Интернете, вестимо… Но лучше, конечно, оставить по-английски.

Ну и ещё кое-что. Не забывайте про волшебное сочетание клавиш Alt/Enter. Оно сделает Ваше маленькое ДОСовское окошко большим и симпатичным.


Теперь два схожих на лицо монстрика из другой экологической ниши.

Первый - FillChar. Задумка совершенно безобидная. Заполнить строку одним и тем же символом. Использоваться (по-хорошему) должно вот так:


FillChar( s[1], Length(s), ‘A’);


Обратите внимание на s[1] – это не спроста. Функция Length тоже не случайна. Заполнить можно только уже ранее заполненную ранее чем-то строку – длина строки хранится в её нулевом символе, а он в процессе не меняется. Встроенная справка Турбо Паскаля предлагает примерно вот такой вариант заполнения строки с изменением её длины:


FillChar( s[1], 80, ‘A’);

S[0]:=#80;


Щупальца за такое пообрывать! Кстати, не помню, встречалось ли нам уже использование решётки перед числом. Так вот, решётка перед числом переводит его в константу типа char, которая константа содержит символ с кодом равным этому самому числу. Трудно? То есть, #65 во всех отношениях абсолютно эквивалентно ‘A’. Для чего этот полёт фантазии? Только для того, чтобы обойти принципы строгого типизирования данных, изначально заложенные в Паскаль. В данном случае – загнать в определённый байт строки конкретное числовое значение.


Разумеется, FillChar абсолютно безразлично относится к вопросу, что и чем он заполняет. Первый параметр – просто адрес, начиная с которого производится заполнение. Границы переменных игнорируются. Третий параметр вообще может быть переменной символьного или байтового типа или константой со значением в пределах байта.

На практике, никто с помощью FillChar строки не заполняет, а используют его совсем по-другому. Например, имеется двумерный массив (array[1..N,1..M] of integer), и надо его обнулить. По-хорошему, делается это так:


for i:=1 to N do

for j:=1 to M do

a[i,j]:=0;


А по-плохому вот так:


FillChar( a, SizeOf(a), 0);


Это очень-очень плохо. Я тоже так делаю, но меня хоть совесть мучает.


Последний номер нашей программы – Move. Самое убойное, что есть в Турбо Паскале. С ним можно сломать что угодно.

Происхождение процедуры тянется вглубь веков, куда-то к динозаврикам. Происходит она от одноимённой ассемблерной команды. Три параметра. Первый параметр – адрес откуда. Второй параметр – адрес куда. Третий параметр сколько слать, в байтах. Процедура берёт указанное количество байтов начиная с первого адреса и копирует их по второму адресу. Адрес – имя переменной или указатель на память. Проверок никаких. Следующие четыре варианта абсолютно законны (p1,p2 объявлены как pointer).


Move (p1^,p2^,1024);

Move (p1^,p2, 1024);

Move (p1, p2^,1024);

Move (p1, p2, 1024);


Смысл имеет только первый. По крайней мере, я так думаю.

В норме Move используется только совместно с указателями. Любое другое применение чревато и заставляет задуматься, всё ли в порядке в программе.

А в сочетании с указателями вещь чрезвычайно полезная и даже необходимая.

Примеров не будет. Вам ещё рано.




Название документа TP Как настроить.doc

Как настроить Турбо Паскаль, чтобы было приятно и удобно

В принципе, у нас уже всё хорошо – то есть Турбо Паскаль запускается и как-то даже трепыхается. Но, естественно, хочется ещё лучше. А, чтобы было ещё лучше, надо слегка подкрутить настройки Паскаля – те, что идут по умолчанию, как всегда, не совсем соответствуют.

В принципе, конечно, можно ничего не трогать. Но лучше всё-таки постараться.

Как до настроек добраться? Нажимаем F10 – активизируется главное меню. Шлёпаем стрелочкой направо, пока не доберёмся до пункта главного меню под названием <Options> и нажимаем Enter. Разворачивается меню (ну или - подменю). Мышкой всё это сделать тоже можно, но неспортивно. Мышка – оружие дельфиста, паскалисты шлёпают по клавишам.

Теперь наша задача – чтобы внесённые нами изменения в настройки действовали всегда и везде. Отправляемся в пункт меню <Save as…> Можно побороться с не очень хитрой системой навигации по каталогам, но мне так кажется, что оно нам в дальнейшем не понадобится. Так что трудолюбиво в верхней строке (Options file name) набираем c:\bpascal\bin\turbo.tp и нажимаем Enter. На всякий случай прогуляйтесь в этот самый каталог – там должен присутствовать файл turbo.exe с текущей датой и свеженьким временем.

Снова войдите в меню <Options>. В пункте меню <Save> (не <Save as…>!) появилось имя и путь сохранённого файла, возможно в сокращённом виде – что-то типа c:turbo.tp. Это нормально.

Теперь мы будем менять настройки, как нам больше нравится, а для сохранения нажимать на <Options\Save>.

А теперь в путь по закоулкам меню. Движемся сверху вниз.


<Compiler options>. Ставим птички.


Runtime Errors – все.

Debugging – все.

Numeric Processing – все.

Syntax Options – помечаем Strict var Strings и Extended Syntax


Больше птичек нам не надо. Скорее всего, в этом разделе и так всё было хорошо. Извините, что не объясняю, какая птичка зачем – все птички совершенно одноразовые. То есть поставили её, и вряд ли менять когда-нибудь придётся.


<Memory sizes> - игнорируем. Всё пока хорошо.


<Linker> - Всё равно.


<Debugger>. Пропускаем, всё должно быть уже хорошо. На всякий случай – Integrated, Smart.


. Тут важнее. В пункте Unit directories вписываем c:\bpascal\units. Вы, конечно, понимаете, что все эти каталоги, возможно, придётся скорректировать с учётом того, как они называются конкретно у Вас?


<Tools>. Безусловно, пропускаем.


<Environment>. Тут работы будет побольше.


. Screen sizes у устанавливаем в 25 Lines. Desktop file – Current directory. В разделе Auto Save помечаем всё.


<Environment\Editor>. Расставьте галочки по вкусу, большого вреда не будет. Только обязательно отметьте Syntax highlight – чтобы было красиво. И подумайте, нужны ли Вам мусорные файлы. Если нет, выключите Create Backup Files.


<Environment\Mouse>. Здесь вроде бы изначально всё хорошо.


. Аналогично.


. Обратите внимание на раздел Syntax. Покрасьте по вкусу. Лично я всегда крашу числа в голубой, а строки в зелёный. Но своё мнение никому не навязываю.


Очень важно. При запуске программы из среды Турбо Паскаля у Вас всё будет хорошо. Ну, или всё будет нехорошо, но хоть как-то будет. Когда Вы вернётесь во внешний мир, то обнаружите, что от Вашей бурной деятельности не осталось никаких следов. Нет исполняемого файла! А почему?

F10\Compile\Destination. Видим текст Destination Memory. То есть программа наша компилируется и компонуется как положено, но результат находится только в оперативной памяти. А после выхода из Турбо Паскаля – всё… Выберите этот пункт – и всё. Когда Вы посмотрите на него следующий раз, там будет стоять Destination Disk. То есть, программа изготовляется на диске, и у Вас остаётся весомый, грубый, зримый exe-файл.


Вот, собственно и всё. Не забудьте сохранить настройки - <Options\Save>.


Название документа TP Как установить.doc

Как установить Турбо Паскаль

Прежде, чем установить Турбо Паскаль, надо его где-нибудь взять. Где взять? Помните великого ирландско-английского драматурга Оскара Уайльда (Oscar Wilde) и его пьесу “Как важно быть серьёзным” (The Importance of Being Earnest)?

Джентльмен посылает слугу купить огурцов, тот возвращается без них, и отвечает:


- Сэр, сегодня на рынке не было огурцов. Даже за деньги!


Некоторые вещи купить нельзя даже за деньги, например DOS 5.0 или Турбо Паскаль.

Как быть? Как в анекдоте – Где взял, где взял?! Нашёл!

Настоятельно рекомендуется найти Turbo Pascal 7.0. Если это будет Borland Pascal 7.0 – всё равно. В нудные разъяснения об их отличиях вдаваться не будем. Если версия окажется 7.01 – не страшно, а даже лучше.


На самом деле, такой версии нет, это творение местных умельцев.


Короче, нашли Вы где-то Турбо Паскаль. Теперь надо установить. Нашли Вы или дистрибутив, или готовый образ. Готовый образ – это значит - у приятеля уже установлен и даже работает. Тут, конечно, даже думать нечего – хватаем и тащим.

Если дистрибутив – установить его традиционным образом, со времён DOS’а тут мало что изменилось.

Если образ – скопировать его к себе на жёсткий диск. В любом случае для установки рекомендуется каталог с именем типа “с:\bpascal”. Всяческие Program Files не рекомендуются категорически – установить, конечно, можно, и, даже, работать будет, но в дальнейшем возможно возникновение мелких и не очень проблем. Дальше я буду предполагать, что Турбо Паскаль установлен именно в каталог c:\bpascal\.


Причина – Турбо Паскаль разработан для DOS, а не для Windows, соответственно родные имена каталогов и файлов для него состоят не более чем из восьми символов без пробелов с возможным расширением до трех символов.


Если всё хорошо, то в каталоге c:\bpascal найдутся подкаталоги с именами


c:\bpascal\bin

c:\bpascal\units

c:\bpascal\bgi


Это как минимум, вполне возможно, что подкаталогов будет больше.

Наш самый главный файл turbo.exe находится в каталоге c:\bpascal\bin. Если его запустить – получим готовую к работе среду Турбо Паскаля.

А как запустить? Для повседневного употребления – создать иконку. Или, что лучше, создать пункт пользовательского меню в, например, FAR’е или добавить вызов в панель инструментов в Total Commander.

На скорую руку обычно просто вызывают тот самый turbo.exe из его родного каталога c:\bpascal\bin\. Но это не совсем хороший вариант – файлы с исходными текстами программ, если не напрягаться, валятся в тот же каталог, откуда вызвали, туда же отправляются полученные в результате исполняемые файлы и, даже, о ужас! – объектные файлы. Хуже всего то, что всё валится в один каталог, где образуется гигантская помойка.


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

Мы запустили интегрированную среду разработки Turbo Pascal – тот самый turbo.exe. Набрали исходный текст нашей программы и сохранили его. Если специально не озаботиться местом его сохранения, то сохранится он в каталоге, откуда этот turbo.exe запущен – то есть c:\bpascal\bin. Например, исходный текст сохранили в файле song.pas – ну не программа у нас, а просто песня! Затем программу мы транслируем и получаем исполняемый файл song.exe – в том же каталоге. Попутно, в зависимости от настроек, могут образоваться и другие файлы – song.bak, song.map и ещё кто-нибудь. Если наша программа состоит из нескольких модулей – то есть содержит несколько файлов исходных текстов – то образуются файлы с именами типа song.tpu. У всех образовавшихся файлов одно и то же имя, но разные расширения.

Ещё появится файл с именем turbo.tp – обратите внимание, что его имя не связано с именем нашей программы.

Всё это вместе называется проект. На самом деле она так не называется, вернее, именно так оно и называется, но только в Borland Delphi. Поскольку термин удачный и востребованный, будем применять его и по отношению к Турбо Паскалю. Проект – совокупность всех файлов, относящихся к одной программе. Из одного проекта получаем один исполняемый файл. Как всегда, всё не совсем так, но в первом приближении сойдёт

.

А как всё сделать правильно? По-хорошему, все файлы, относящиеся к одному проекту (программе) должны находиться в одном отдельном каталоге. Они и только они. Один проект – один каталог.

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

Проиллюстрируем на примере FAR’а. В нём надо создать пользовательское меню (user menu). F9, , Main, Insert command – а кто говорил, что легко будет? Хотя чего трудного, собственно? Hot key и Label по вкусу, в Command пишем наше уже знакомое c:\bpascal\bin\turbo.exe.

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


Теперь об очень-очень печальном. Турбо Паскаль работать на современных быстрых процессорах не может. Ну, вообще. Ну, почти. То есть, он делает вид, что работает. Пока мы не впишем в секцию uses модуль Crt – а мы его очень скоро туда впишем. После этого при запуске любой программы получаем совершенно неуместное сообщение о делении на ноль.

Как бороться?

Если у Вас уже упомянутая версия 7.01, то повезло. Borland, ясное дело, такой версии не выпускал, это дело рук отечественных Кулибиных. Если не повезло, то будете сам себе Кулибин.

Идёте в Яндекс и набираете “turbo.tpl исправленный”. Должно повезти.


Название документа TP Клавиатура и скан-коды.doc

В Турбо Паскале есть две функции:


function KeyPressed : boolean;

function ReadKey : char;


Попутно знакомимся с новым типом данных. Даже с двумя, но второй новый тип явится попозже. А пока первый новый тип – Char. Тип новый, хотя и очень простой, и даже, в каком-то смысле, уже знакомый. Char – это один символ. Строковый тип представляет собой, в некотором упрощении, массив элементов типа Char. По-русски договоримся называть его (Char) символьным типом, ил просто символом. То есть, если есть S, которое строка (string), то какое-нибудь s[3] как раз и есть символ. Если объявлено ch : char;, то можно написать ch:=s[3]; или s[3]:=ch;, но, разумеется, нельзя написать ch:=s; или s:=ch;.

Договоримся, что если в дальнейшем попадётся переменная по имени ch, то объявлена она как ch : char;.

Что всё это значит применительно к нашей задаче чтения с клавиатуры? Мы можем написать такой текст:


repeat

if KeyPressed

then ch:=ReadKey;

if ch = ‘w’

then writeln(‘w key pressed’);

until ch = ‘q’;


Код вполне рабочий и даже почти полезный. Если нажата клавиша W мы, всего-навсего, выводим сообщение об этом факте. А могли бы отреагировать по-другому, повелев нашему мымрику попрыгать.


Для любознательно-дотошных есть ещё возможность объявить что-то вроде as : array[1..N] of char; Потом долго думать (и проводит эксперименты) на тему совместимости этого типа с типом string.


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

А теперь программа чуть сложнее, но и универсальнее:


program Key;

uses

Crt;

var

ch : char;

begin

ClrScr;


repeat

if KeyPressed then begin

ch:=ReadKey;

writeln( Ord(ch));

end;

until ch = ‘q’;

end.


Программа проверяет, не нажали ли что. Если нажали, читает нажатый символ. А мы выводим символ на экран. Точнее, не символ, а его код. О функции Ord, как уже обещано, поговорим отдельно. Каждому символу однозначно соответствует код – число в диапазоне от нуля до 255.

Выполнение программ прекращается при нажатии символа ‘q’. Это от слова Quit – в старых программах часто использовалось такое сокращение.

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


Подводим итоги.

В целом всё хорошо, но, как обычно, присутствуют нюансы. Нюанс мелкий – в текстах программ не случайно написано w и q, а не W и Q. Наши программы будет реагировать только на маленькие буквы. Сочетание клавиш w/Shift не будет распознано как нажатие клавиши w. Это даже нюансом назвать трудно – функция ведёт себя в точном соответствии со своим названием. Сказано прочитать символ – вот она и читает. Буква большая и та же буква, но маленькая – это ведь разные символы. Возможно, это именно то поведение функции, которое нас лучше всего устраивает, но всё же – помнить об этом надо.


Теперь нюанс несравнимо серьёзнее. Есть клавиши хорошие – те, которые с буковками и циферками. Нажал на буковку – и функция ReadKey вернула нам нажатый символ, готовый для дальнейшего использования. А есть клавиши нехорошие, но, по странному совпадению, как раз самые нужные. Те же стрелочки в первую очередь. При нажатии на такую клавишу ReadKey сообщит, что прочитана какая-то странная клавиша, вернувшая символ, кодируемый нулём. И если мы прочитали такой нулевой символ, то должны повторить чтение с помощью ReadKey ещё раз, и вот только тогда мы узнаем, что же такое было нажато. Вот это двукратное считывание кажется мне как-то не очень правильным. Сразу возникает желание написать свою, улучшенную функцию ReadKey, или как мы её назовём. Предлагается другой, более раз-и-навсегда, способ.


DOS позволяет узнать нам, какой символ был нажат на клавиатуре. Но ещё DOS позволяет узнать, какая клавиша была нажата. А это, как говорят в определённых кругах, две большие разницы. Одна и та же клавиша при разных условиях может одарить нас разными одиночными символами, и наоборот – одна клавиша может сгенерировать два символа за одно нажатие – как мы видели чуть раньше. А вот с собственно клавишами всё железобетонно просто. Каждая клавиша генерирует свой скан-код. Только она и только его. Скан-код – это, опять-таки, по-научному. Когда-то, в совершенно неправдоподобно далёкие времена, кто-то незатейливо пронумеровал всю клавиатуру. Как положено – сверху вниз и слева направо. В левом верхнем углу оказался Esc, он и стал номером первым. Следующей, при тогдашней конструкции клавиатуры, оказалась клавиша с единицей. Она стала номером вторым. Ну и так далее. Вот эти номера клавиш и называются скан-кодами.

Соответственно, я предполагаю читать именно эти скан-коды, по-простому – номера. К сожалению, Турбо Паскаль не предоставляет простого способа прочитать скан-коды. Но Турбо Паскаль даёт возможность сделать почти всё, что мы хотим. Хотим читать скан-коды, значит, будем читать скан-коды. Только придётся немного потрудится.

Как всегда есть два варианта – для ленивых и для трудолюбивых. Трудолюбивые – это такие же ленивые, только они чуть-чуть поумнее ленивых и согласны сегодня поработать немного больше, чтобы всю следующую неделю работать немного меньше.

В целом варианты весьма похожи. Первый. Добавляем в секцию uses имя Dos. Затем включаем в программу описание двух функций:


{-------------------------------------------------------------------}

function OurKeyPressed : boolean;

var

R : Registers;

begin

R.ah:=1;

Intr( $16, R);

if (R.flags and fZero) <> 0

then OurKeyPressed:=false

else OurKeyPressed:=true;

end;

{-------------------------------------------------------------------}

function OurReadKey : byte;

var

R : Registers;

ch : char;

sc : byte;

begin

R.ah:=0;

Intr( $16, R);

ch:=Chr(R.al); sc:=R.ah;

OurReadKey:=sc;

end;

{-------------------------------------------------------------------}


Что мы получили и как этим пользоваться? Первая функция заменяет стандартную турбопаскалевскую KeyPressed. Вторая функция заменяет, соответственно, стандартный ReadKey, с поправкой на то, что наш OurReadKey читает не символы, а скан-коды.

И попутно - второй новый тип – byte. Он ещё проще, чем char. Это такая половинка от integer, точнее от word. Занимает он не два байта, а один, и вмещается в него диапазон от нуля до 255. В большинстве случаев (и в нашем случае) вместо byte можно использовать обычный integer. То есть, можно писать k:=OurReadKey, где K объявлено как integer. Так зачем мы используем byte? Зачем, зачем, ну, получается что исключительно из принципа. На самом деле скан-код – это один байт, вот мы и используем переменную, которая ровно один байт занимает. Если Вы нежадный, можете в предыдущем коде заменить sc : byte; на sc : integer;. Главное, запомните общий принцип – переменной типа integer можно сколько угодно присваивать переменные типа byte, обратное весьма нежелательно. Как обычно, думать над этим три минуты.

Как этим пользоваться? Следующий код проверяет, нажата ли клавиша. Если какая-то клавиша нажата, выводит её скан-код. Если нажали Esc, прекращаем работу. Sc объявлено как byte или как integer, что Вам больше нравится.


repeat

if OurKeyPressed

then sc:=OurReadKey;

writeln(‘scan = ‘, sc);

until sc = 1;


Теперь немного о том, а что мы, собственно, такое написали. Всё это можно было написать на ассемблере – Турбо Паскаль разрешает ассемблерные вставки. Такой псевдопаскалевский/псевдоассемблерный стиль – следствие моих личных предпочтений. В смысле, мне так больше нравится.

Тип Registers – это запись (смотри далее) обеспечивающая доступ к регистрам процессора. Поля записи – отдельные регистры. Разумеется, обращение к записи не означает непосредственного обращения к регистрам процессора. Обращение происходит при вызове процедуры Intr. Она вызывает так называемое 21-е прерывание DOS, которое на самом деле никакое не прерывание. Первый параметр – номер функции прерывания, второй параметр – состояние регистров. Если регистры меняются во время вызова прерывания, изменённые состояния мы получим в этом же параметре. Подробнее об этом можно прочитать в П.Нортон, Р.Уилтон “IBM PC и PS/2 Руководство по программированию”. Питера Нортона программисты старой школы по традиции уважают, но ещё лучше прочитать об этом в... В чём? Как обычно, книжку только что украли, а Интернет расходится во мнениях. И как его только не называли… Жорден, Жордэн, Джурден, Жордейн, Джордейн. А потом оказалось, что это вовсе и не он, а такая специальная очень умная тётенька, и зовут его вовсе и не Роберт, а Роберта. Название приблизительно – Справочник программиста PC XT и AT. Когда я был молодым, а всё вокруг зелёное и цвело и кустилось… Короче, в те времена ни один серьёзный программист не мог обойтись без этой книги.


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

Итак – <F10>, <File\New>. Появляется новое, абсолютно пустое окно редактирования без заголовка. Точнее, с заголовком noname00.pas, что, в целом, ничем не лучше, чем без заголовка вообще. Набираем в этом пустом окне вот такой текст:


unit Scan;

{-------------------------------------------------------------------}

interface

{--------------------------- Scan Codes ------------------------}

const

ArrowLeft = 75; ArrowRight = 77;

ArrowDown = 80; ArrowUp = 72;

Esc = 1;

{-------------------------------------------------------------------}

function OurKeyPressed : boolean;

function OurReadKey : byte;

{-------------------------------------------------------------------}

implementation

uses

Dos;

{-------------------------------------------------------------------}

function OurKeyPressed : boolean;

var

R : Registers;

begin

R.ah:=1;

Intr( $16, R);

if (R.flags and fZero) <> 0

then OurKeyPressed:=false

else OurKeyPressed:=true;

end;

{-------------------------------------------------------------------}

function OurReadKey : byte;

var

R : Registers;

ch : char;

sc : byte;

begin

R.ah:=0;

Intr( $16, R);

ch:=Chr(R.al); sc:=R.ah;

OurReadKey:=sc;

end;

{-------------------------------------------------------------------}

end.


Всё почти так же, как и в ранее набранных функциях, включенных в тест нашей программы. Только добавились волшебные слова unit, interface, implementation. С волшебными словами подробно разберёмся в следующей главе. Ещё у нас появилась секция const, а в ней объявления нескольких констант. Всё это в целом называется модуль.

Теперь нажимаем F2 и сохраняем наш модуль под именем Scan.pas. Обратите внимание, тот же подход, что и с программой. Имя модуля (то, что после unit), совпадает с именем файла, в котором этот модуль сохранён.

И как всем этим богатством воспользоваться? В разделе uses основной программы кроме Graph и Crt (если они нам нужны) дописываем наш Scan.


Теперь, как всегда нюанс. А могли бы мы назвать функцию не OurReadKey, а просто ReadKey, как и стандартную? Могли бы.

Но в этом случае мы были бы должны аккуратно вписать его в uses ПЕРЕД Crt. Причина? А подумать? Понимаю, что сложно, но гипотезу высказать можно? В Crt уже есть и KeyPressed и ReadKey, и, вписав наш модуль раньше, мы занимаем для себя эти имена. Кто первый встал, того и тапки.

Я понимаю, что это кажется очень простым. А в жизни пишут после Crt, и долго чешут репу. Ну и зачем нам лишние хлопоты? Проще переименовать.


Описания функций из основной программы выкидываем. Получается так:


uses

Scan, Graph, Crt;

repeat

if OurKeyPressed

then sc:=OurReadKey;

writeln(‘scan = ‘, sc);

until sc = Esc;


И что мы от этого имеем?

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


На самом деле, это не совсем так строго. Модуль может лежать и в другом каталоге, но имя этого каталога должно быть указано в <Options\Directories\Unit directories>.

И, обратите внимание, Dos в секции uses основной программы уже не обязателен. На него ссылается непосредственно наш модуль Scan.


Польза вспомогательная – нам не надо помнить, что скан-код Esc равен единице. Оно у нас теперь константа. Там же, в разделе констант, определены и скан-коды стрелок на все четыре стороны. В Дополнении имеется полный текст модуля Scan. Можете вытаскивать оттуда скан-коды нужных клавиш по мере надобности, или набрать весь модуль сразу.

Кстати, что характерно, для применения в основной программе доступны только имена, описанные в модуле в секции interface. Это неспроста.


Название документа TP Модули - как оно на самом деле.doc

Ещё одна очень важная вещь. Модули

Модуль – по-английски unit. Осваивать будем по той же схеме – сначала модуль, ничего не содержащий. Затем модуль хоть что-то делающий и как его применить. А затем я постараюсь объяснить, а Вы постараетесь понять, зачем они, модули, нужны.

Модуль, в отличие, от, например, процедуры, вещь реальная. Модуль можно потрогать руками. Один модуль – один файл.

А теперь – абсолютно пустой модуль. Что, разумеется, не означает абсолютно пустой файл

<F10>, <File\New> - получаем новое окно редактирования. Набираем:


unit SomeUnit;

interface

implementation

end.


Нажимаем F2, как обычно, и сохраняем модуль под именем SomeUnit.pas. Имя модуля, разумеется, должно быть уникальным, как и все имена в программе. Модуль можно оттранслировать, как обычно нажав F9. Ошибок быть не должно. Запустить на выполнение, правда, не удастся. Модуль, подобно процедуре, сам по себе ничего не делает. Процедуру надо вызвать. Модуль надо подключить. То есть, главная ничего не делающая программа должна выглядеть вот так:


program Nothing;

uses

SomeUnit;

begin

end.


Обращаем внимание на определённое сходство структуры модуля и структуры программы. Сходство, как увидим в дальнейшем, ещё значительнее – модуль, как и программа, может иметь свои собственные секции uses, const, type, var.

А теперь добавляем нашему модулю хотя бы минимальную функциональность. На самом деле даже не совсем минимальную – постараемся продемонстрировать, хотя бы и по чуть-чуть, весь, что называется, спектр возможностей.


unit SomeUnit;

interface

uses

Dos;

const

Esc = 1;

type

TColor = integer;

var

x,y : integer;

procedure DoSomething;

{--------------------------------------------------------------------}

implementation

uses

Crt;

const

e = 2.718;

var

z : integer;

{--------------------------------------------------------------------}

procedure DoNothing;

begin

end;

{--------------------------------------------------------------------}

procedure DoSomething;

begin

z:=0;

DoNothing;

end;

{--------------------------------------------------------------------}


end.


Программа, использующая наш модульвсё та же – Nothing. На наш модуль мы сослались в секции uses.

В программе можно использовать константу Esc. Это хорошо.

В программе можно объявить переменную типа TColor. Это тоже хорошо.

В программе можно вызвать процедуру DoSomething. Это даже не то, что хорошо – это нормально. Как правило, модули как раз и содержат различные процедуры и функции. По крайней мере, все модули Турбо Паскаля именно таковы.

В программе мы можем обратиться к переменным X и Y. Это плохо. Это те же глобальные переменные, только хуже. Когда-то это было распространённой практикой. Создавался специальный модуль, где объявлялись все глобальные переменные и только они. На этот модуль ссылались все остальные модули и головная программа. Это я вам подробно объяснил, как не надо себя вести. С появлением объектов (Турбо Паскаль версии 5.5) такое поведение стало аморальным и местами даже преступным. Об объектах мы здесь говорить не будем, но, тем не менее, к вам это тоже относится.

(Обратите внимание, что “вы” – с маленькой буквы. Имеется в виду всё множество потенциальных читателей (и нечитателей) этой книги).

Впрочем, об объектах, если повезёт, ещё напишем.

Это всё было о том, что можно. Теперь о том, что нельзя

Нельзя из программы обратиться к переменной Z и константе E.

Нельзя из программы обратиться к процедуре DoNothing.

К кому обращаться можно, а к кому нельзя, определяют волшебные слова interface и implementation. Технически это секции. Секция интерфейса (кто бы подумал) и секция реализации.


Всё, что от слова interface до слова implementation видно снаружи. Любая программа или модуль, указавшая SomeUnit в секции uses, может получить доступ ко всему нашему барахлу, упомянутому здесь.

Всё, что между implementation и концом модуля, видно только из секции implementation этого модуля.

И ещё. Если в программе есть ссылка на SomeUnit, это вовсе не значит, что в программе есть ссылка на модуль Dos. Её, ссылки, там нет. И это несмотря на то, что ссылка есть в секции интерфейса нашего модуля. О ссылке на Crt в секции реализации даже не говорю. Как там на истории учили – вассал моего вассала не мой вассал. Так и здесь. Хотите Dos – ссылайтесь явно.


А теперь о главном – зачем это надо?

Первый ответ банальный – чтобы программа не была слишком большой. Чтобы можно было попилить программу на части. А когда модуль станет слишком большим – его тоже попилить. Это не пустяк. Это важно. Поверьте. А каков максимальный размер программы или модуля? Лично мне кажется, что тысяча строк. В крайнем случае, две тысячи, если никак не пилится на части. Две тысячи – это для моего старого, измученного жизнью программистского интеллекта. Для Вас и пятисот хватит.

Попутно. А каков максимально рекомендуемый размер процедуры? Есть такое мнение, что процедура должна умещаться на одной странице. Страницы, конечно, разные бывают, но в целом я согласен. Идея правильная.


А ещё зачем? В смысле, зачем надо? Говоря по-умному, для сокрытия реализации. Ещё раз – модуль состоит из двух секций - секция интерфейса (interface) и секция реализации (implementation). В секции интерфейса – только объявления и заголовки. В секции реализации – как оно на самом деле внутри устроено. Из секции реализации наружу дороги нет, как из чёрной дыры. Всё что там объявлено – константы, переменные, типы – всё там и останется. И это правильно. Программист слаб. Не может он думать обо всём сразу. А здесь мы ему жизнь облегчаем. Когда он пишет модуль – думать надо о секции реализации. Когда он модуль использует – думать только о секции интерфейса.

До совершенства эта концепция дошла с появлением объектно-ориентированного программирования.


Некоторые потаенные технические детали. Если в uses перечислено несколько модулей, а в их секциях интерфейса присутствуют одинаковые имена, проблема решаема. Перед именем надо через точку указать имя модуля - Graph.Green.

Если модуль A ссылается на модуль B, а модуль B ссылается на модуль A, то так нельзя и вообще, это страшное преступление, именуемое circular reference. Однако, модуль A может ссылаться на секцию интерфейса модуля B, а модуль B может ссылаться на секцию реализации модуля A. Ничего не поняли? Учиться, учиться и учиться.

Практический совет. Есть программа, есть модуль. Редактируете программу, хотите запустить - нет проблем. Редактируете модуль, хотите запустить, или даже оттранслировать всю программу сразу - никак. Неудобно. Лечится просто - , . Выбираем имя нашей программы. А чтобы не на один раз - идём . Только убедитесь, что сохранено будет в текущем каталоге, тот, который с проектом.


Название документа TP Основы графики.doc

Немного графики

Начальные заклинания

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

Чуть-чуть теории – монитор отображает данные в или в текстовом режиме, или в графическом.


Текстовый режим на самом деле, конечно, тоже в глубине души графический, но для нас это совершенно неважно.


Давным-давно назад мы написали программу, которая ничего не делала. Не делала она ничего в текстовом режиме. А теперь пишем программу, ничего не делающую в графическом режиме.


program Gr;

uses

Graph;

var

driver, mode : integer;

begin

driver:=VGA;

mode:=VGAHi;

InitGraph( driver, mode, ‘c:\bpascal\bgi’);

{ а вот тут что-нибудь потом нарисуем}


readln;

CloseGraph;

end.


Особое внимание вот этой строке:


InitGraph( driver, mode, ‘c:\bpascal\bgi’);.


А точнее, тому, что в кавычках - ‘c:\bpascal\bgi’.

Строка эта может быть другой в зависимости от места, куда установили Турбо Паскаль. Здесь должен быть прописан полный путь до подкаталога bgi, находящегося в каталоге, в который Вы установили Турбо Паскаль – Вы же помните, куда его установили? В подкаталоге bgi должен находиться файл egavga.bgi – его наша программа будет искать при запуске и, если не найдёт, выдаст соответствующее страшное сообщение.


Есть вариант – берём файл egavga.bgi и кидаем его в тот каталог, где размещается наша программа – её исходные тексты и, главное, исполняемый файл. А соответствующую строку программы меняем вот так:


InitGraph( driver, mode, ‘’);


Если Вы захотите передать кому-то программу, работающую в графическом режиме, то вместе с исполняемым файлом надо в тот же каталог поместить и файл egavga.bgi. Вызов InitGraph в этом случае должен быть таким, как написано выше – с пустой строкой.



Вообще-то при большом желании можно не таскать с программой файл egavga.bgi, а вкрутить его внутрь исполняемого файла. Но о таких подвигах где-нибудь в самом конце книги. Или в другой.


InitGraph переводит вывод из текстового режима в графический режим. После этого можно рисовать.

CloseGraph возвращает нас в текстовый режим. Всё с трудом нарисованное при этом пропадает.

readln выполняет привычную функцию – ждёт нажатия Enter, чтобы мы могли наглядеться на нашу картинку.


Точки, линии и окружности

Как положено в геометрии, начнём с точек. В данном программистском случае – занятие малопродуктивное с прикладной точки зрения и малополезное с точки зрения педагогической. Перевожу – в жизни рисовать точки вряд ли придётся, а рисуются они совершенно непохожим на всё остальное способом, так что ничему полезному не научимся. Но надо, так надо.


Но сначала о главном. Размер экрана у нас – 640 по горизонтали, 480 по вертикали. Точки нумеруются от 0 до 639 и от 0 то 479 соответственно. По горизонтали нумерация слева направо, по вертикали сверху вниз. Одна экранная точка, зажжённая или нет, часто называется пиксел (или пиксель).


Рисуем зелёную точку где-то посредине экрана:


PutPixel(320,240, Green);


Первое число – координата по X, второе – координата по Y. Далее цвет. С цветами всё так же, как и в текстовом режиме. Вот, собственно, и всё о точках.


Переходим к линиям. Если точка (на плоскости) задаётся двумя числами, то линия, как известно, четырьмя.


Line (100,100, 200,200);


Получили линию, идущую направо вниз под сорок пять градусов. Первые два числа – координаты начала линии, вторые два – координаты конца линии. Если написать


Line(200,200, 100,100) – получим абсолютно тот же результат - какая разница, с какого конца линию начинать рисовать.

А теперь квадрат, с левым верхним углом в точке (100,100) и стороной 100.

Сначала верхняя сторона – горизонтальная. Раз линия горизонтальная, то координата Y неизменна, меняется только X.


Line(100,100, 200,100);


Теперь правая – вертикальная. Теперь наоборот – X неизменна, Y меняется. А начинается она там, где кончается верхняя сторона – в точке (200,100).


Line(200,100, 200,200);


Продолжаем в то же духе и в итоге имеем искомый квадрат:


Line(100,100, 200,100);

Line(200,100, 200,200);

Line(200,200, 100,200);

Line(100,200, 100,100);


Квадрат у нас белый. Хотелось бы чего-нибудь поживее. Вспоминаем текстовый режим и команду TextColor. Всё аналогично, только команда называется SetColor. Цвета, естественно, всё те же. И точно так же, заданный цвет действует только на то, что рисуется после задания цвета, не до.


Зелёный квадрат:


SetColor(Green);

Line(100,100, 200,100);

Line(200,100, 200,200);

Line(200,200, 100,200);

Line(100,200, 100,100);


Задание – самостоятельно нарисовать треугольник.


Теперь обещанная в заголовке окружность. На всякий случай вспоминаем, чем окружность отличается от круга. Рисуем окружность в центре экрана радиусом 100.


Circle(320,240, 100);


Первые два числа – координаты центра, третье число – радиус.


А теперь голубенькую:


SetColor(Blue);

Circle(320,240, 100);


В общем, всё очень просто.


Прямоугольнички и кружочки


Помните, с чего мы начали при выводе текста? Сначала что-то вывели, намусорили, потом решили почистить экран. Сейчас то же самое – только попутно освоим ещё кое-что полезное.


Пишем:


Bar(200,200, 400,300);


Получили заполненный белым цветом прямоугольник размером 200 по горизонтали и 100 по вертикали с верхним левым углом в точке (200,200).

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

Теперь будем красить. К сожалению, SetColor(Green) нам не поможет. Чтобы закрасить прямоугольник, придётся написать оператор посложнее:


SetFillStyle(SolidFill, Green);


Второй параметр задаёт цвет, а первый? Первый это стиль заполнения – в крапинку, в горошек, в данном случае – без затей, сплошным зелёным цветом.

А чтобы почистить весь экран до исходного черного цвета, пишем:


SetFillStyle( SolidFill, Black);

Bar( 0,0, 639,479);


Можно очистить экран и более научным способом, но так как-то нагляднее и понятнее. Мне так, по крайне мере, кажется. SolidFill, как и следует ожидать, константа. Её значение – 1. Некоторые ленивые товарищи так и пишут SolidFill(1, Black). Есть ещё и суперленивые, которым и Black тяжело написать, но таких мы безусловно осуждаем.


Обещанных в заголовке кружочков не будет. В этом месте Турбо Паскаль несколько ассиметричен, и, вместо кружочков, предлагает эллипсы. Если очень хочется именно кружочков, вспоминаем – круг, это такой эллипс, у которого обе оси равны. Рисуем:

FillEllipse(100,100, 500,200) – большой такой эллипс, вытянутый по горизонтали.

FillEllipse(100,100, 300,300) – частный случай эллипса – круг.

Приятная глазу расцветка придаётся эллипсу совершенно тем же способом, что и прямоугольнику, то есть вызовом процедур SetPenColor и SEtBrushColor.


В Delphi в таких случаях говорят о метафорах пера и кисти. Перо отвечает за проведение линий, а кисть закрашивает поверхности.


Красивые буковки

Чтобы не мучаться, технологию вывода текста излагаем сразу.


SetColor(Green)

SetTextStyle( 0, HorizDir, 1);

OutTextXY( 100,100, ‘Lala’);


Первая строка очень даже знакомая – именно таким способом задаётся цвет текста.

Вторая посложнее. Первый параметр – номер шрифта - от нуля до пяти. На самом деле, есть, конечно, уже заранее определённые константы, и выбранный шрифт можно задать словами. Например:


DefaultFont = 0;

TriplexFont = 1;

SmallFont = 2;

SansSerifFont = 3;

GothicFont = 4;


Второй параметр объясняет, что именно сегодня мы захотели вывести текст слева направо, а не сверху вниз. Если всё же сверху вниз, то второй параметр будет VertDir.

Третий параметр – размер шрифта. Диапазон изменения для каждого шрифта свой. Эффект влияния для каждого шрифта – тоже свой, то есть первый шрифт второго размера запросто может оказаться больше второго шрифта пятого размера.

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

Текст только по-английски.


Конечно, если очень хочется, то можно и по-русски. Но процедура несколько сложнее, нежели для вывода по-русски текста в текстовом режиме. Точнее, если мы согласны на шрифт номер ноль(DefaultFont), то ничего дополнительно делать не надо. Достаточно, чтобы был загружен keyrus.com. Далее всё как обычно, просто в OutTextXY пишем по-русски. В чем засада? – буковки уж очень страшные получаются, особенно если размер задать побольше.


Для того чтобы было красиво, надо раздобыть файлы с русскими шрифтами. Раздобыть их можно, понятное дело, в Интернете. Наберите в Яндексе или в Гугле что-то вроде ‘Turbo Pascal шрифты русские’ и тщательно изучите результаты. По нахождению искомых файла, всё что требуется – просто заменить имеющиеся на найденные. Найденных может оказаться больше, чем исходных. Это ничего.


Вы уже знаете, что если хочется отдать кому-то свою программу для исполнения, то в случае программы, работающей в текстовом режиме достаточно передать исполняемый файл. Если программа работает в графическом режиме, надо в комплект добавить файл egavga.bgi. Но это как минимум. Если программа ещё и выводит текст в графическом режиме, надо будет добавить файлы шрифтов. Шрифт DefaultFont файла не требует, а для каждого из остальных шрифтов требуется соответствующий ему файл со шрифтом. Можно не мучаться, а просто скопировать все файлы с расширением .chr из каталога c:\bpascal\bgi\.

Теперь о русском языке. Если используется опять-таки шрифт DefaultFont, то предварительно должен быть загружен русификатор. Для остальных шрифтов русификатор не нужен, но, как это не банально, шрифты должны быть русскими.


Ну и опять-таки, если очень хочется, то файлы шрифтов, как и файл egavga.bgi можно вкрутить внутрь исполняемого файла.


Что там ещё осталось?

Ещё кое-что полезное вдогонку ранее освоенному.

Линию уже выводили. И цвет её задавали. А теперь толщина линии и стиль.


SetLineStyle( SolidLn, 0, NormWidth);


Первый параметр – стиль линии – сплошная, пунктирная…Вместо SolidLn(сплошная) можно написать 0. Возможный диапазон – от нуля до трёх (ну до четырёх, но четверка нам не нужна). Второй параметр сейчас и в ближайшем будущем строго равен нулю. Третий параметр – толщина линии. Или NormWidth – тонкая, или ThickWidth – толстая. Занудства ради – стиль линии учитывается, только если линия тонкая. Если линия толстая – без баловства, только сплошная.

И ещё о цвете. Зелёный прямоугольник – освоили. Зелёный эллипс – освоили. А зелёный треугольник? С треугольником сложнее. Зато, освоив треугольник, освоим и всё остальное, сколь угодно многоугольное и без углов вообще. Знакомьтесь – FloodFill. Возвращаемся к когда-то нарисованному нами треугольнику (мы ведь его нарисовали, правда?):


SetColor(Green);

Line(100,100, 300,100);

Line(300,100, 100,200);

Line(100,200, 100,100);


А теперь:


SetFillStyle(SolidFill, Green);

FloodFill( 105,105, Green);


FloodFill закрашивает (заливает) всё, начиная с заданной точки (первые два параметра – (105,105)) пока не встретит границу заданного цвета (третий параметр - Green). Каким цветом красить, задаёт SetFillStyle. У нас цвет границы и цвет заливки совпадают – всё зелёненькое – но это необязательно.

А что будет, если промахнёмся и не попадём в треугольник? А он, FloodFill, всё равно будет красить, пока не встретит зелёную границу, только не внутри границы, а снаружи. Попробуйте.


Название документа TP Отладка.doc

Отладка. Давно пора

Программы, которые мы до сих пор писали, были простыми. Ну, выражаясь мягче, не очень сложными. Если что-то сочинялось не так, по нашему ли неразумению, или по простой описке-опечатке, выловить ошибку удавалось (наверное) упорным (тупым) изучением (разглядыванием) текста программы. И ошибка быстро обнаруживалась – я в этом уверен, честное слово!

Эта программа будет посложнее. И ошибки будут посложнее. И справиться с этими ошибками будет куда сложнее. Некоторые гиблые места известны заранее – соответствие строк и столбцов поля, координат расположения курсора и элементов двумерного массива, описывающего текущее состояние игры. Ошибаются все, проверено.

Поэтому для отлова и отстрела ошибок придётся задействовать тяжёлую артиллерию – отладочный режим.

Тренироваться будем, как всегда, на кошках. В роли кошки – вот такая, совершенно бессмысленная программка. Циферки слева, ясное дело, к тексту программы не относятся, это номера строк, для удобства ссылки на них. Набирайте текст:


01 program debug;

02 var

03 x,y : integer;

04 i : integer;

05 {-----------------------------------------------------}

06 procedure Incr( var x : integer);

07 begin

08 x:=x + 1;

09 end;

10 {-----------------------------------------------------}

11 begin

12 x:=1;

13 write('y = ');

14 readln(y);

15 Incr(x);

16 for i:=1 to 1000 do begin

17 if y > 0 then begin

18 x:=x + 1;

19 end

20 else begin

21 x:= x - 1;

22 end;

23 end;

24 end.


Как всегда F9. А дальше не как всегда. Вместо Ctrl/F9 нажимаем F7. Образовался зелёный курсорище во всю ширину экрана и установился на строке 11, то есть на первом begin’е. Снова нажимаем F7. Курсор переместился на следующую строку. Мы находимся в режиме пошагового выполнения программы, он же отладочный режим. Зелёный курсор показывает строку, которая сейчас будет выполняться. Внимание: эта строка ещё не выполнена, она будет выполнена только при следующем нажатии F7.

Одно нажатие F7 – одна выполненная строка. И снова внимание – выполняется одна строка, а не один оператор. То есть, если в строке несколько операторов, выполнены будут все сразу, что не есть хорошо. Так что не жалейте заварку, в смысле пишите по одному оператору на строке.

Добрались до строки 14. Нажали F7. Оказались на чёрном экране с приглашением ввести Y. В принципе естественно, никто за нас Y вводить не будет.

А теперь (остановившись на строке 15) опять жмём F7. И попадаем в процедуру Incr. Затем тем же способом, через F7, из неё выбираемся. Вроде бы всё понятно и разъяснений не требует.

Нажимаем Ctrl/F2. Зелёный курсор пропал – мы вышли из режима отладки.

Начинаем всё сначала, только вместо F7 будем нажимать F8. Всё происходит абсолютно так же, пока мы не доберёмся до строки 15. Теперь по нажатию F8 мы не входим в процедуру Incr, а перемещаемся на следующую строку 16. Смысл клавиши F8 должен быть понятен – такое же пошаговое выполнение, но без захода в процедуры и функции.

Теперь главный вопрос – а зачем, собственно? Зачем это надо, и какие блага мы, собственно, от этого получаем? Некоторая польза обнаруживается на строке 17. В зависимости от введённого значения Y, вы видим, по какой из веток условного оператора движется наша программа. Это уже очень полезно. В нашем случае всё и так очевидно, но ведь условие может быть гораздо сложнее и, что важнее, Y мог быть не введён нами только что, а рассчитан где-то давным-давно.

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

Начинаем отслеживать выполнение программы в пошаговом режиме. То есть, нажимаем F7, потом ещё, пока наш большой зелёный курсор не окажется на строке 14. Теперь приступаем к действиям.

Пусть, к примеру, нас интересует судьба переменной X. Подкрадываемся курсором и устанавливаем его точно на переменной (мы можем выбрать любое вхождение переменной X в программе). Нажимаем Ctrl/F7.


Появляется вот такое окно:


hello_html_5dc4f543.png


Вместо X мы можем ввести имя другой переменной, но, скорее всего, X это именно то, что нам и надо. Нажимаем Enter и получаем вот такое:


hello_html_m22d8b5ca.png


Мы видим значение переменной. Это хорошо. Но активным является окно со значением переменной. Это, всё-таки, плохо. Нам бы хотелось продолжать движение по программе, а для этого надо вернуться в окно с текстом программы. Нажимаем F6. Эта клавиша, если помните, поочерёдно перебирает все открытые окна. Даже картинку приводить не буду. Осталось только окно редактирования. Окно с переменными тоже осталось, конечно, но где-то сзади и нам недоступное и невидимое.


Теперь выберите в меню <F10>, <Window\Cascade>. Или Alt/W, A. Все окошки выстроились и мы получили вот такой образцовый порядок:

hello_html_m50969265.png


А что ещё есть в запасе? Нажав Ctrl/F4 можно не только посмотреть значение переменной, но и его, значение, изменить. Мучительно пытаюсь припомнить, когда мне это понадобилось, и не могу.


А теперь, предмет гораздо более существенный, чем изменение значений переменных. Встали на строку 21 и нажали Ctrl/F8. Строка выделилась жирным красным цветом. Что это значит? И как это называется? А называется это – точка останова. Не остановки, а останова! А кто говорил “остановки”, тех мои первые учителя программирования хватали за волосы и возили мордой по столу, приговаривая “А знаешь, как Ваньку Жукова учили?!”. Если попадался гуманный учитель, то просто гуманно бил линейкой по рукам.

Извините, расчувствовался.

Точка останова нужна, когда мы точно знаем, где хотим оказаться – в данном случае на строке 21, но при этом не хотим шлёпать туда пошагово, долбя по клавише F7. Запускаем программу на выполнение как обычно – через Ctrl/F9. Вводим отрицательное значение Y. Попадаем на точку останова – зелёный курсор на строке 21. Дальше можно двигаться в пошаговом режиме.

Отменить точку останова можно, остановившись курсором на ней и снова нажав Ctrl/F8.

И помните – когда вам всё это надоест – просто нажмите Ctrl/F2.

Да, и ещё. Если программа работает в графическом режиме, то при переходе из окна редактирования в экран с графикой и обратно, графический экран будет выглядеть как-то так… Грязновато… Это нормально и совершенно не страшно.


Название документа TP Поиск файлов.doc

Найти и снова найти

Но начнём мы не с того, что у файлов внутри а, так сказать, с виду сверху. Файл, как уже сказано, вещь реальная. Или он есть, или его нет. Или он есть, но их много. Отсюда вопрос – как узнать - есть он, или его нет, или их много? Ещё более другими словами – как узнать, какие файлы существуют?

На этот вопрос немедленно возникает вопрос встречный – а где существуют? Упрощаем вопрос - как узнать, какие файлы существуют в каталоге, из которого запущена наша программа?

Узнать несложно, но, как это помягче выразиться – методом немного корявым.

Сначала объявляем переменную типа SearchRec.


var

SR : SearchRec;


SearchRec – запись, а записи у нас по плану в следующей главе. Так что не обращаем внимания и делаем вид, что всё понимаем. На самом деле, записи - это очень просто. Вот только доберёмся до следующей главы…

А вот и сама программа:


FindFirst( ‘*.*’, AnyFile, SR);


while DosError = 0 do begin

writeln( SR.name);

FindNext(SR);

end;


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


Два странных файла с именами в виде одной и двух точек соответственно – особенность DOS’а. Если в каталоге присутствуют подкаталоги, то в списке окажутся и они. Управляет этим второй параметр процедуры. AnyFile означает, что будут найдены все файлы, включая каталоги (с точки зрения DOS’а, каталог – это такой специальный файл). Почитайте в справочной системе на эту тему, в частности, как искать только файлы.

Первый параметр, самый важный, - маска поиска. Почитайте что-нибудь про DOS, в частности о команде dir. Если нас интересует какой-то конкретный файл, то в качестве первого параметра надо указать его имя.

И почитайте в справочной системе описание структуры SearchRec. В ней присутствует и другая полезная информация.


Обратите внимание, что команда поиска файлов используется в двух вариантах. Первый раз – в полной – FindFirst. Второй и следующий в сокращённой – FindNext. Подразумевается, что первые два параметра из FindFirst незримо присутствуют в FindNext с теми же значениями.

И ещё загадочный DosError. Это такая переменная, не нами объявленная. Пока очередной искомый файл находится (и вообще всё хорошо), переменная эта равна нулю. Как только что-то становится не так, значение становится ненулевым.

Ну и ещё обратите внимание на организацию цикла while. У нас есть некоторое действие (Find), в зависимости от результата которого выполнение цикла может быть прекращено. И есть обработка результатов этого действия (вывод имени файла, в данном случае).

Первый Find производится перед циклом. А в цикле всё идёт в обратном порядке – сначала обработка, затем действие. Это типично.


Название документа TP Просто программа - русификация - среда разработки.doc

Просто программа

Самая простая программа, которая ничего не делает

Пишем в редакторе


program kuku;

begin

end.


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


Это так называемые зарезервированные слова. Зарезервированность их в том, что эти слова нельзя использовать в качестве идентификаторов. Идентификатор – то же самое, что имя, но звучит научно. Имена бывают у переменных, процедур, функций, конствнт, у самой программы, в конце концов. Сейчас мы к этому перейдём.


Вместо kuku можно написать любое слово, главное английскими буквами. Kuku – это имя нашей программы.


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

Большие буквы, или маленькие – это никакой роли не играет (кстати, немцам о рентгене - это в сторону программистов на языке C). Точно так же, все остальные маленькие буквы по желанию могут быть заменены на большие, от этого ничего для компилятора не изменится.

На самом деле всё вышесказанное имеет гораздо большее значение - эти правила распространяются на все идентификаторы языка Pascal. Идентификаторами являются все имена в программе. В данном случае имя только одно: kuku – имя программы.


Остальное должно быть в точности как написано. Ну, почти – так где стоит один пробел, можно поставить сколько угодно, это общее правило. Но лучше не увлекаться. Но там, где стоит хотя бы один пробел – хотя бы один пробел и должен быть.


Сокровенный смысл написанной выше программы.

То, что находится между строчками program <её имя>; и begin является частью не выполняющейся, а декларативной. Говоря по другому, эта часть ничего не делает, а объясняет, как понимать написанное далее (понимать не программисту - компьютеру). А вот то, что написано между begin и end. как раз что-то делает. Даже если какая-то строка не делает (как будто) ничего, на самом деле это не так - она указывает как, в каком порядке, при каких условиях должны выполняться остальные строки.

Да, впервые упомянуто новое слово - оператор. Что это такое?

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

Как ни печально, про оператор все понимают, но никто объяснить не может. И Вы поймёте. Наверное.


Экран сейчас должен выглядеть вот так:


hello_html_21577d2d.png

Теперь нажимаем клавишу F2. Да, конечно, можно и мышью. Но ещё раз, Паскаль создавался в древние безмышовые времена и без мыши, как ни странно, действительно будет проще. Привыкайте.

Зачем F2? Сохранить текст нашей программы

Появится вот такое окошко:


hello_html_m5c69d616.png


Остаётся только указать имя файла, в котором будет сохранена наша программа, и нажать клавишу Enter.


В каталоге, откуда мы запускали Турбо Паскаль, появился файл kuku.pas.

Для упрощения жизни настоятельно рекомендую давать файлу то же имя, что и программе, то есть тот идентификатор, что стоит после слова program. И не забывать, что по техническим причинам (смотри выше примечание для любознательных) имя должно быть не длиннее восьми символов, не содержать пробелов, и т.д. и т.п.

Теперь клавиша F9. Это трансляция нашей программы – перевод её из исходного текста в исполняемый машинный код. И, что на данном этапе даже важнее, проверка исходного текста на правильность и отсутствие в нём ошибок.

Экран должен теперь выглядеть вот так:

hello_html_m371de7ba.png


Нам сообщают, что пока всё идёт хорошо.

Теперь нажимаем (как нас собственно и просят) любую клавишу.

Итак, в программе ошибок нет – да и откуда им взяться – программа-то ма-аа-аленькая.

А теперь программу – запускаем!!!


Жмём Ctrl/F9. Происходит быстрое мелькание экрана – и всё. Что случилось? Да ничего, собственно. Программа наша маленькая, ничего не делает. Соответственно при запуске она ничего и не сделала.


Сейчас в каталоге, где находится исходный текст нашей программы, появился файл kuku.exe. Точнее, появился чуть раньше, после нажатия F9. Его (kuku.exe) можно запустить на исполнение обычным способом, через проводник, например. Результат его исполнения, будет в точности тот же, что и после запуска через Ctrl/F9.


А теперь мы завершили работу, и вышли из Турбо Паскаля. Выйти, кстати, можно или через меню, или нажав Alt/X. При выходе нас, естественно, спросят, не забыли ли мы сохранить наш текст – если мы забыли. Обратите внимание на звёздочку слева внизу. Если она есть, значит, сохраниться забыли.

А теперь мы запустили Турбо Паскаль снова. Если всё настроено правильно, у нас автоматически загрузится та самая программа, с которой мы работали, и на том самом месте, где мы с ней работу прекратили. А если нет? Или если программ у нас уже много и нам надо загрузить совсем другую?

Очень просто. Нажимаем F3 и выбираем то, что нам надо.

Каждая новая открытая программа занимает в окне редактирования чуть меньшее пространство – чтобы были видны заголовки всех открытых программ. Если окошко стало уж очень маленьким, нажмите F5 – текущая программа займёт всё доступное место.

Ранее открытые программы никуда не делись – они где-то там, только сзади. Вывести их на передний план можно клавишей F6 – она переберёт поочерёдно все загруженные программы.


Очень простая программа, которая делает хоть что-то

Как уже раньше упоминалось, если мы хотим, чтобы программа что-то делала, это что-то должно быть выражено в тесте, находящемся в исполняемой части программы – между begin и end.

Например:


program kuku;

begin

write(‘Au!’);

end.


Вместо Au!, естественно, можно написать всё, что угодно, но по-английски. И ещё одно ограничение – текст не должен содержать кавычек.


Если хочется писать по-русски. Придётся постараться. Сначала надо раздобыть русификатор для DOS. Рекомендую keyrus Дмитрия Гуртяка. Как найти? Наберите в Яндексе keyrus и выбирайте подходящий источник. Возможно, в скачанном архиве будет несколько файлов, нам понадобится только один – keyrus.com. Скопируем его в c:\bpascal\bin\. Можно в другое место, только не забудьте куда. Как написано в дополнении, хотя Вы, возможно, обошлись без него, мы предполагаем, что Турбо Паскаль установлен в каталог c:\bpascal.

Теперь нам надо, чтобы перед запуском Турбо Паскаля (то есть turbo.exe) запускался keyrus.com. Будем писать командный файл, известный также как пакетный. Заходим в notepad.exe, или что-нибудь аналогично текстовое и набираем:


c:\bpascal\bin\keyrus.com

c:\bpascal\bin\turbo.exe


Сохраняем то, что набрали под именем r.bat. Можно не r, но расширение .bat обязательно.

Теперь там, где у нас вызывался turbo.exe, меняем его вызов на вызов r.bat. Пробуем. Всё должно заработать.

Внешне всё выглядит так же. Нажимаем правый Shift и пишем – теперь пишется по-русски. Снова правый Shift – пишется по-английски. При нажатом Shift’е в полноэкранном режиме вокруг экрана появляется тонкая синяя рамочка. Обратите внимание – переключение на русский язык с помощью Shift’а необходимо только для набора текста по-русски, отображаться по-русски текст будет и без этого, достаточно загруженного русификатора.


Если очень хочется кавычек.

Очень просто - дайте две! В смысле вместо одной кавычки поставьте две. Не двойную кавычку вместо одинарной, а именно две. Видно в тексте программы будет две, но восприняты они будут не как две, а как одна. При подсчете символов в строке (об этом дальше) обе они будут восприняты как один символ. При выводе такой строки на экран видно будет тоже только одну кавычку.


Далее снова то же самое:

F2 – сохранить.

F9 – скомпилировать.

Ctrl/F9 – выполнить.

Опять на экране что-то промелькнуло и исчезло. Обидно, да?

Учим новое слово, в смысле сочетание клавиш – Alt/F5. Нажимаем и видим приблизительно вот такую картинку:


hello_html_m12d89936.png


Много всего непонятного, и среди этого непонятного наше Au!

Нажимаем любую клавишу и возвращаемся в привычный (уже) редактор Турбо Паскаля.

Вывод из произошедшего – оператор write выводит текст на экран. Текст в кавычках, кавычки в скобках. Кавычки и скобки всегда ходят парами – если есть открывающая (кавычка/скобка), где-то неподалёку должна быть и закрывающая.


Улучшаем программу. Много новых слов

Лично мне нажимать Alt/F5 как-то не очень нравится. Хотелось бы автоматизировать процесс. Ну, или хотя бы полуавтоматизировать.

Добавим в программу ещё одну строчку. Вот так:


program kuku;

begin

write(‘Au!’);

readln;

end.


Опять - F2, F9, Ctrl/F9.

И сразу, безо всяких Alt/F5 видим знакомую уже картинку. Или, скорее всего, вот такую:


hello_html_m2b4eab59.png


Но теперь чтобы вернуться в редактор Турбо Паскаля надо нажать клавишу Enter.

Вывод – оператор readln занимается тем, что ничего не делает, ожидая нажатия клавиши Enter (внимание – не любой клавиши, а именно клавиши Enter).

И ещё вывод – каждый оператор заканчивается точкой с запятой.


Ведутся глубокие философские дискуссии, ставится ли точка с запятой после оператора, или она является его неотъемлемой частью. Вообще-то, что совой об пень, что пнём об сову.


Тем не менее, полного удовлетворения как-то нет. На экране кроме нашего Au! куча какого-то левого мусора. Мало того, Au! от предыдущего запуска тоже висит на экране. А если запустим программу на выполнение ещё раз-другой, Au! размножатся в соответствующем количестве.

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

В результате программа приобретает такой вид:


program kuku;

uses

Crt;

begin

ClrScr;

write(‘Au!’);

readln;

end.


Запускаем программу – и имеем чистенькую картинку с одной только нашей надписью, как и хотелось.


hello_html_76369e17.png


Волшебное слово ClrScr очищает экран, а чтобы оно заработало, надо написать ещё два волшебных слова – uses Crt.

Если написать ClrScr, но забыть про uses Crt, то получим вот такое несимпатичное сообщение об ошибке:


Error 3: Unknown identifier


Означает оно, что Паскаль не знает и даже не догадывается, кто такой ClrScr и где его искать (искать надо в Crt).


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

Для расширения кругозора.

Невразумительное словцо ClrScr – сокращение от Clear Screen, очистить экран.

Внешние процедуры содержатся в модулях (об этом тоже позже). Имя модуля – Crt. Переводится ЭЛТ – электронно-лучевая трубка. В этом модуле содержатся подпрограммы для работы с экраном в текстовом режиме.

Используемые модули перечисляются через запятую после слова uses. Трудолюбивые это слово переведут сами.


А теперь очень важное! Если кому-то это покажется само собой очевидным, заранее извиняюсь – как показывает опыт, очень даже многим это далеко не очевидно.


Вот так работает:


ClrScr;

write(‘Au!’);


Имеем чистый экран и надпись на нём. Что и требовалось.


Вот так нет:


write(‘Au!’);

ClrScr;


Чистый экран имеем, но, собственно, и всё.


Операторы выполняются по порядку. Сверху вниз. В порядке написания. Сначала первый, потом второй. Как ещё объяснить?


Ещё раз приношу извинения, если кому-то кажется это тривиальным. До многих почему-то не доходит.

А теперь вместо


write(‘Au!’);

напишем


write(‘Au!’);

write(‘Au!’);


После запуска программы получим:


Au!Au!


А теперь слегка изменим программу


writeln(‘Au!’);

write(‘Au!’);


Картинка после запуска изменится на вот такую –


Au!

Au!


После недолгого размышления приходим к выводу, что отличие оператора writeln от оператора write заключается в том, что writeln ещё и переходит на новую строку после вывода текста.

А если написать вот так:


writeln(‘Au!’);

writeln;

write(‘Au!’);


то между нашими Au! появится пустая строка.

Запомним на всякий случай – оператор writeln без параметров (параметрами здесь называется то, что в скобках) обеспечивает переход на новую строку.

А теперь ещё раз – каждый оператор заканчивается точкой с запятой. Или – операторы между собой разделяются точкой с запятой. Это уж как Вам больше нравится. Естественно, начинающие программисты регулярно эти точки с запятой пропускают. Программисты продвинутые тоже, хотя и не так регулярно. Компилятор это замечает и выдает тревожное сообщение “Error 85: “;”expected”. Сообщение в целом понятное, но вот курсор при этом указывает не на то место, где пропущена точка с запятой, а на начало следующего оператора. То есть, если у нас вот такой текст


writeln(‘a’);

writeln(‘b’)

writeln(‘c’);


то курсор будет мигать в начале третьей строки:


writeln(‘a’);

writeln(‘b’)

_writeln(‘c’);


Будьте внимательны.


Весёленько, в цветочек

А теперь несколько дополнительных возможностей и несколько новых слов.

Вот такая программа


TextColor(Green);

Writeln(‘Au!’);


Получили текст зелёного цвета. Пустяк, а приятно.

Обратите внимание, что Green пишется без кавычек.

Можно задать и другие цвета. Вот полный список. Ну, почти полный.


Black

Blue

Green

Cyan

Red

Magenta

Brown

LightGray

DarkGray

LightBlue

LightGreen

LightCyan

LightRed

LightMagenta

Yellow

White


Запомните на всякий случай. Ещё пригодится. Попозже, в процессе освоения графики, научимся красить и в более экзотические цвета.


А если сделать вот так:

TextColor(Green+Blink);

Writeln(‘Au!’);


то оно будет ещё и моргать.


Вот так тоже неплохо:


GoToXY(10,10);

Writeln(‘Au!’);


Надпись переехала.

Первая десятка – номер строки, на которую мы отправились. Всего строк 24. Вторая десятка – номер столбца, или, говоря по-другому, номер символа в строке. Всего их 80.

Поэкспериментируйте.

Строки нумеруются сверху вниз. Это, конечно, естественно – пока мы не доберемся до графики. Там нумерующиеся сверху вниз строки пикселов вызывают некоторое неудобство у обладающих начальными математическими познаниями.


И ещё

Текст, заключённый в фигурные скобки, - это комментарии. Компилятор этот текст игнорирует, как будто его нет вовсе. То есть пишется он не для компьютера, а для человека – для Вас, когда завтра Вы забудете, что насочиняли вчера или для того неизвестного программиста, которому достанется сопровождение Вашей программы.

Например:


{ Переходим в центр экрана}

GoToXY(40,12);

Writeln(‘Au!’);


Название документа А о чём вообще речь.doc

Зачем вообще это каталог и выложенные здесь тексты? К тому же местами разделы эти подозрительно похожи на разделы из основной книги.


Смысл двоякий. Или даже троякий.


Установить Турбо Паскаль труднее, чем ABC. Русифицировать Турбо Паскаль ещё труднее, в смысле, что гарантировать стопроцентно работающую конфигурацию невозможно. Всё это, безусловно, говорит ни в коей степени не в пользу Турбо Паскалю, а только и исключительно против него.


А вот дальше начинается, говоря по старому, диалектика. А говоря по новому «Вот такая загогулина». Настройка Турбо Паскаля включает в себя несколько десятков пунктов. А Паскаля АБЦ – нет. Это не потому, что он хороший, а потому что он не дает в себе настраивать вообще ничего. По буквам – Николай, Иван, Харитон, Ульяна… И это уже не хорошо, потому что это плохо. И среди главных отсутствующих настроек отсутствует главная – будем создавать исполняемый файл или нет. И это финиш. Для разнообразия запустите Delphi или какой-нибудь Visual C++ и полюбуйтесь на тамошний вагон и маленькую тележку настроечных функций.


Графика и Отладка - они просто в TP немного другие. Это как раз неважно.


А вот отличия в работе с указателями и бинарными файлами важны очень. Это то что, делает Турбо Паскаль живым языком. Устаревшим, но живым.


А учиться языку в Pascal ABC безусловно легче.


У меня пока всё.



Название документа Опись вложения.doc

Возведение числа в квадрат

Square

Площадь круга

Circle

Расчёт процентов

Money

Определение знака числа

Plus

Делимость на семь

Divis

Плохая проверка знания арифметики

TArBad

Хорошая проверка знания арифметики

TArGood

Графика, которая не рисует

Gr

Самая простая программа с массивом

Arr

Самая простая программа с циклом

Cycle

Хитрый расчёт процентов

Procent

Очень хорошая проверка знания арифметики

TArVGood

Массив - ввод и вывод

Arr_2

Пузырьковая сортировка *

Bubble

Разбор на слова *

Words

Таблица Пифагора *

Pif

Пятнашки, заполнение *

P15

Просто процедура

Proc

Глобальные переменные

Global

Крестики-нолики Процедура записи результатов

Finale

Побайтовое копирование файла

FileCopy

Работа с Val *

PVal

Множества

PSet



Clock

Часы с циферблатом

Debug

Подопытная программа для отладки

Factor

Два факториала для сравнения

FC

Копирование файла - побайтово

KEY

Работа с клавиатурой - ESC-последовательности

MUSIC

Вдоль да по речке. Подключить uses Notes

Notes

Всё, что Вам надо для музыки. Ну или почти всё

ODELAY

Наша личная процедура задержки

SCAN

Самый главный модуль для работы с клавиатурой - SCAN-коды

SEARCH

Сканирование фалов с выводом на экран и пометкой каталогов

SONG.PAS

УСТАРЕЛО. Эту программу я написал под TP 3.0. Пятьдесят лет назад. Или сорок. Ну, в крайнем случае, тридцать. Короче, давно. Реанимируйте и запустите.

TARA

Таракан - страшно? То тоже! Исправьте

TEST

Звёздочки моргают

TIC

Крестики-нолики

TSET

Работа с множеством


Со всеми этими программами есть одна маленькая проблема – чем дальше мы движемся по пути развития видеокарт, тем хуже они что-то рисуют на экране. Особенно если эта видеокарта – встроенная. Но что делать? Когда вы смотрите мутную, грязную и расплывчатую экранку, вы утешаете себя тем, что, зато фильм - ого-го!. Нут так и здесь абсолютно то же самое.


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


Страшные комментарии (а может быть и не очень страшные, зависит от конфигурации вашего Windows) объясняются тем, что сначала они были написаны в кодировке DOS, затем для включения в текст книги переведены в кодировку Windows, а потом через пятые руки получилось то, что получилось.


Файлы, помеченные звёздочкой, представляют собой почти готовые программы – готовые, но почти. Только приделать голову и хвост – program впереди и end. сзади. Вы справитесь.

Название документа Что тут лежит.doc

Информация, здесь содержащаяся, в основном относится к Турбо Паскалю.


Почему? Потому, что заявленный в названии книги как «немного», он ровно в таком количестве там и присутствует. А хотелось бы, побольше.


С другой стороны, половина текстов программ, выложенных в каталоге для TP, ровно с тем же успехом могут быть запущены из под ABC, а другая половина потребует только небольшой доработки напильником.


Желаю успеха!

Самоучитель игры на Паскале. ABC и немного Турбо
  • Информатика
Описание:

Издательство: СОЛОН-ПРЕСС

 С абсолютного нуля до полного овладения языком. Популярный в школах Pascal ABC и вечно живой Turbo Pascal. Весь Паскаль, среда программирования, технология разработки и отладки. Примеры программ — простых и не очень. Для младших студентов, старших школьников и всех, кто хочет программировать.

Виртуальный диск в помощь читателям книги с текстами  всех программ длиннее десяти строк в двух версиях – для Pascal ABC и Turbo Pascal.

Специально для Turbo Pascal (TP): установка, настройка, русификация, процесс отладки в Turbo Pascal, особенности работы с графикой, работа с клавиатурой в TP на уровне скан-кодов, полезные советы. 

http://www.solon-press.ru/katalog/biblioteka-studenta/samouchitel-igryi-na-paskale.-abc-i-nemnogo-turbo

Автор Епифанцев Сергей Владимирович
Дата добавления 09.01.2015
Раздел Информатика
Подраздел
Просмотров 1935
Номер материала 48805
Скачать свидетельство о публикации

Оставьте свой комментарий:

Введите символы, которые изображены на картинке:

Получить новый код
* Обязательные для заполнения.


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

↓ Показать еще коментарии ↓