Speccy #06
31 августа 1996

Стиль - программирование: о внутренней структуре программы, то есть займемся основой алгоритмизации.

<b>Стиль</b> - программирование: о внутренней структуре программы, то есть займемся основой алгоритмизации.
╒══════════════════════════════╕
│░░░░░░░ НОВАЯ  РУБРИКА ░░░░░░░│
╘══════════════════════════════╛

 Уважаемые читатели журнала,раз-
решите  представить  вам  нового
сотрудника   редакции    журнала
"SPECCY", жителя города  Абакан,
хорошо известного многим синкле-
ристам,Феськова Кузьму  Владими-
ровича. После  непродолжительных
переговоров, на абсолютно добро-
вольной основе, он дал  согласие
участвовать в  создании журнала.
 Немного  истории:  В   редакцию
журнала уже неоднократно  посту-
пали просьбы по открытию рубрики
в которой бы поэтапно,шаг за ша-
гом, совместно с читателями соз-
давалась бы игровая программа.
 С  челябинскими  программистами
были разговоры на  эту  тему, но
дальше разговоров дело не двига-
лось. Пока....(см. выше).

 Кузьма Владимирович  решил  на-
чать с  самого  начала. Рубрику,
которую он открывает будет назы-
ваться "стиль".Просьба  ко всем,
кого заинтересует данный раздел,
письма направляйте по ниже  ука-
занному  адресу.

      662613 г.Абакан,
 ул. Ленинского Комсомола,
         д.3, кв.16
        Феськову К.В.

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






(С) 1996 Феськов Кузьма
───────────────────────

    Не путайте моду со стилем...
                    ТВ-6 "Стиль"

   Позвольте представиться,  ме-
ня зовут  Феськов  Кузьма.  И  я
предлагаю Вам сегодня новую руб-
рику - СТИЛЬ.  СТИЛЬ,  это    не
стиль в моде, а стиль в програм-
мировании. Тем более, что сегод-
ня это не роскошь, а главное от-
личие программистов друг от дру-
га. Например  KSA  известен  нам
стилем "быстрых" программ,  всем
известный  Николай  Родионов   -
стилем оформления  его  программ
(стрелочный интерфейс), хотя  на
сегодняшний день его стиль  стал
стилем  для  множества    других
программистов. Я думаю, что  по-
копавшись в  памяти  Вы  найдете
еще множество примеров "стильно-
го" программирования. Можно дол-
го рассуждать на тему  необходи-
мости стиля в  программировании,
но если Вы непременно хотите ос-
таться в анналах  истории  Спек-
трума, стиль именно то, что  Вам
нужно!
             * * *

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

             * * *

   Сегодня мы поговорим с Вами о
внутренней структуре  программы,
то есть займемся  основой  алго-
ритмизации.
   Что  же  представляет   собой
программа?  Попробуйте  предста-
вить себе ее в виде живого орга-
низма  (что , кстати ,  довольно
близко к действительности).  Го-
ды разбора чужих программ и  на-
писания своих,позволили мне выя-
вить некоторые особенности  жиз-
ни такого организма,  как  прог-
рамма, о которых надо знать.
   Заглядывая в чужие  программы
(особенно отечественных авторов)
мне было  крайне  сложно  разоб-
раться в том, где-что. И все по-
тому, что процедуры находятся  и
переплетаются с  телом  основной
программы.  Это  конечно   может
служить своего рода защитой,  но
сдается мне, что сия защита спо-
собна хорошенько защититься и от
самого автора, так как  найти  в
таком "адском узле" ошибку край-
не сложно.  Посмотрите  на  свои
ранние программы, я  думаю,  что
Вы теперь уже с трудом сможете в
них разобраться.
   И так, я предлагаю  Вам  сле-
дующий план действий при написа-
нии программы:
   1.Прикиньте на  листочке  не-
большую схему  Вашей  программы.
Во-первых это поможет Вам  скон-
центрироваться на  отдельных  ее
участках, а не принимать ее  це-
ликом,  что    крайне    сложно.
Во-вторых, Вы никогда  не  запу-
таетесь в том, как  части  прог-
раммы будут между собой  взаимо-
действовать.
--------------------------------
ПРИМЕР. Возьмем для примера  не-
большую    програмку,    которая
только и будет, что печатать  на
экране спрайт. Посмотрите на  ее
схему:
┌──────────────────────────────┐
│            Данные            │
├─────────┬───────────┬────────┤
│координа-│адрес  дан-│размеры │
│ты печати│ных спрайта│спрайта │
└───┬─────┴─────┬─────┴───┬────┘
┌───┴────┐      │         │
│расчет  │      │         │
│адреса  │      │         │
│в экране│      │         │
└───┬────┘      │         │
┌───┴───────────┴─────────┴──┐
│прорисовка спрайта          │
└────────────────────────────┘
   Как видите, глядя на эту схе-
му,легко можно спланировать свою
работу, не надо  распылять  свое
внимание  на  какие-то  несущес-
твенные моменты. Это, так  назы-
ваемый   принцип    СТРУКТУРНОГО
программирования.  Мы  переходим
от крупного к частному, достигая
при этом  минимальной  НЕДЕЛИМОЙ
части. Заметьте,  неделимой,   в
данный момент, несмотря  на  то,
что при делении программы  легче
ее осмыслить, не стоит этим  ув-
лекаться, так как  в  погоне  за
структурностью  вы  можете  сде-
лать  настолько  сложную  схему,
что не сможете проследить  взаи-
мосвязи между процедурами и вер-
нетесь к исходной точке. Есть ли
выход из  этой  ситуации?  Разу-
меется есть! Что мешает Вам  вы-
делить  конкретную  процедуру и,
взяв ее за программу, структури-
ровать. Давайте вернемся к наше-
му примеру. Совершенно очевидно,
что  блок  "прорисовка  спрайта"
представляет   собой    довольно
объемную процедуру, которая  мо-
жет быть выделена и структуриро-
вана:
┌──────────────────┐
│Прорисовка спрайта│
└─────────┬────────┘
┌─────────┴─┐┌───────────┐
│цикл печати││цикл печати│
│в высоту   ├┤в длину    │
└───────────┘└───────────┘
   Как видите,  подобный  подход
позволяет Вам  очень  эффективно
строить свою работу.
--------------------------------
   2.Напишите сначала все проце-
дуры, а уж потом головную  прог-
рамму,  которая  должна  лишь  в
нужное  время  вызывать   нужную
подпрограмму.   НЕ    ЗАГРУЖАЙТЕ
главную программу частями, кото-
рые можно выделить в подпрограм-
мы, за исключением тех моментов,
которые требуют быстродействия.

             * * *

   Давайте на этом закончим  наш
сегодняшний разговор.  Загрузите
ассемблер  и  просмотрите   свои
программы, которые наверняка уже
есть в Вашей копилке,  попробуй-
те сделать их структурными.
   В качестве примера, а так  же
в целях формирования Вашего сти-
ля предлагаю сегодня Вашему вни-
манию программу СТРЕЛОЧНОГО  ин-
терфейса.
   Все пожелания и предложения к
новой рубрике направляйте мне по
адресу 662613  г.Абакан,  ул.Ле-
нинского  Комсомола,   дом    3,
кв.16. Вы можете так  же  присы-
лать небольшие программки, кото-
рые бы сделали свой вклад в фор-
мирование  стиля   отечественных
программистов,  Вашего    стиля!
Если Вас заинтересовал рассказ о
видах программирования, пишите и
я расскажу о других видах. Все в
Ваших руках.
             * * *
   Программа стрелочного  интер-
фейса. Вы наверное ни раз  виде-
ли бойко бегающую стрелку на эк-
ране, которая, подбегая к  опции
меню, зажигала ее.  Вам  предла-
гается сегодня подобная програм-
ма. Сразу  скажу  (во  избежании
кривотолков), что за основу взя-
та программа Риккера В.В., опуб-
ликованная в  книге  ZX-Форум'1.
Я приведу здесь  всю  программу,
но если вы  ранее  уже  набирали
эту программу, то загрузите ее и
перепишите   заново    программу
START, так как изменения  косну-
лись только ее. А так же добави-
лось 3 новых процедуры.
 Но перед тем, как дать эту про-
грамму, я приведу Вам ее схему.
┌────────────────────┐
│Стрелочный интерфейс│
└──────────┬─────────┘
┌──────────┴──────────────┐
│START: головная программа│
└───┬──────┬──┬────────┬┬─┘
┌───┴─────┐│┌─┴───────┐││
│рисование│││выделение│││
│стрелки  │││меню     │││
└─────────┘│└─────────┘││
       ┌───┘     ┌─────┘└─┐
┌──────┴──┐ ┌────┴───┐ ┌──┴──┐
│проверка │ │стирание│ │опрос│
│попадания│ │стрелки │ │клав.│
└─────────┘ └────────┘ └─────┘
   Разумеется  для  каждой  под-
программы можно  нарисовать  от-
дельную схему,  попробуйте  сде-
лать это самостоятельно.
START   LD HL,(CRDS)  ;Берем
        ;координаты вывода
        ;стрелки.
        LD A,255      ;Заносим
        ;число 255 в номер оп-
        ;ции, что говорит о том,
        LD (OPC1),A   ;что стре-
        ;лка на опцию не попала.
        PUSH IX       ;Далее все
        ;так, как в программе.
QO      CALL SCRBF
        CALL FORM
        HALT
        IN A,(31)
        PUSH AF
        CALL BFSCR
        POP AF
        LD C,A
        LD E,STEP
        LD D,254
        LD HL,CRDS+1
        BIT 0,C
        CALL NZ,PL
        BIT 1,C
        CALL NZ,MIN
        LD D,190
        DEC HL
        BIT 2,C
        CALL NZ,PL
        BIT 3,C
        CALL NZ,MIN
        BIT 4,C
        RET NZ
        CALL COND     ; Вызываем
        ;процедуру проверки по-
        ;падания стрелки.
        CALL BAR      ; Вызываем
        ;процедуру закрашивания-
        ;стирания опции.
        JR QO
;
;ПРОВЕРКА ПОПАДАНИЯ СТРЕЛКИ
;
COND    LD IX,(TABLE) ; В IX за-
        ;носим адрес данных.
        LD A,1        ; Заносим
        ;номер первой опции в
        ;вспомогательную
        LD (OPC),A    ; перемен-
        ;ную.
        LD HL,(CRDS)  ; В HL те-
        ;кущие координаты стрел-
        ;ки.
        SRL H         ; Так как
        ;координаты стрелки в
        ;пикселях, а программа
        SRL H         ; работает
        ;с знакоместами мы делим
        ;координаты на 8.
        SRL H
        SRL L
        SRL L
        SRL L
COND1   LD A,(IX+0)   ; В A
        ;координата X меню.
        CP 255        ; Если
        ;255, то данные кончи-
        ;лись и стрелка не на
        ;опции.
        RET Z         ; Выход.
        LD D,A        ; Проверя-
        ;ем попадание по X.
        LD A,H
        CP D
        JR C,PROPOPC  ; Если ле-
        ;вее опции, пропускаем
        ;ее.
        LD A,D
        LD B,(IX+2)   ; В регис-
        ;тре B длина опции в
        ;знакоместах.
        DEC B
        ADD A,B
        CP H
        JR C,PROPOPC  ; Если
        ;правее опции, пропуска-
        ;ем ее.
        LD A,(IX+1)   ; В А
        ;координата Y.
        CP L
        JR NZ, PROPORC; Если не
        ;совпадает с текущей
        ;координатой Y, пропус-
        ;каем
        LD A,(OPC)    ; Если все
        ;проверки прошли, значит
        ;мы нашли номер опции
        RET           ; загружа-
        ;ем его в A и выходим.
PROPOPC LD DE,3       ; Перехо-
        ;дим к данным следующей
        ;опции.
        ADD IX,DE
        LD A,(OPC)    ; Номер
        ;текущей опции увеличи-
        ;ваем на 1.
        INC A
        LD (OPC),A
        JR COND1      ; Снова
        ;проверяем.
;
;ЗАКРАШИВАЕМ/СТИРАЕМ ОПЦИЮ
;
BAR     LD L,A        ; После
        ;выхода из процедуры
        ;COND в регистре A номер
        ; опции или 255, если
        ;стрелка не попала.
        LD A,(OPC1)   ; Помести-
        ;ли в A номер предыдущей
        ;опции, сравниваем его
        CP L          ; с новым
        ;и если они равны, то
        ;закрашивать не надо.
        RET Z         ; Выходим.
        CP 255        ; Если
        ;стрелка ушла с опции,то
        ;красить новую не надо,
        JR Z,BAR5     ; а надо
        ;погасить старую, что и
        ;делает BAR5.
        PUSH AF
        LD A,L        ; Заносим
        ;новый номер на место
        ;старого.
        LD (OPC1),A
        POP AF
        CALL BAR1     ; Стираем
        ;старую опцию.
BAR6    LD A,(OPC1)   ; В A но-
        ;мер новой опции.
        CP 255        ; Если это
        ;не опция, то красить не
        ;надо.
        RET Z         ; Выходим.
BAR1    DEC A         ; Подгото-
        ;вка к закраске новой
        ;опции.
        LD H,0
        LD L,A
        PUSH HL
        POP DE
        ADD HL,HL
        ADD HL,DE
        EX DE,HL
        LD IX,(TABLE)
        ADD IX,DE
BAR3    LD H,(IX+0)
        LD L,(IX+1)
        CALL FILL     ; Процеду-
        ;ра FILL закрашивает,
        ;либо стирает опцию.
        RET
BAR5    LD A,L
        LD (OPC1),A
        JR BAR6
FILL    LD A,L        ; Следую-
        ;щие строки высчитывают
        ;адрес опции в атрибутах
        AND 7
        RRCA
        RRCA
        RRCA
        ADD A,H
        AND #18
        RRCA
        RRCA
        RRCA
        OR #58
        LD H,A
LOL     LD A,(HL)     ; Берем
        ;байт атрибута.
        PUSH AF       ; Следую-
        ;щие строки инвертируют
        ;опцию меняя местами
        AND 7         ; INK и
        ;PAPER. BRIGHT не учи-
        ;тывается.
        SLA A
        SLA A
        SLA A
        LD D,A
        POP AF
        AND 56
        SRA A
        SRA A
        SRA A
        OR D
        LD B,(IX+2)   ; В регис-
        ;тре B длина опции в
        ;знакоместах.
FILL1   LD (HL),A     ; Если оп-
        ;ция напечатана на мно-
        ;гоцветном фоне, то в
        ;цикл
        INC HL        ; следует
        ;включить строки, начи-
        ;ная с метки LOL.
        DJNZ FILL1
        RET
BUFFS   DEFS 30
STS     DEFW 0
CRDS    DEFW 0
ORSH    DEFB #C0,#E0,#F0
        DEFB #F8,#FC,#FE
        DEFB #FF,#FE,#FC
        DEFB #1C,#0E,#0E
        DEFB #07,#07,#03
XORSH   DEFB #C0,#A0,#90
        DEFB #88,#84,#82
        DEFB #81,#86,#B4
        DEFB #14,#0A,#0A
        DEFB #05,#05,#03
STEP    EQU 2
SCRBF   LD HL,(CRDS)
        LD C,H
        LD B,L
        LD A,B
        CALL #22B1
        LD (STS),HL
        LD DE,BUFFS
RB0     LD B,15
RB1     PUSH HL
        LD C,2
RB2     LD A,(HL)
        LD (DE),A
        INC L
        INC DE
        DEC C
        JR NZ,RB2
        POP HL
        CALL DAD1
        DJNZ RB1
        RET
DAD1    INC H
        LD A,H
        AND 7
        RET NZ
        LD A,H
        SUB 8
        LD H,A
        LD A,L
        ADD A,32
        LD L,A
        RET NC
        LD A,H
        ADD A,8
        LD H,A
        RET
BFSCR   LD HL,#771A
        LD (RB2),HL
        CALL SCRBF
        LD HL,#127E
        LD (RB2),HL
        RET
FORM    LD A,(CRDS+1)
        AND 7
        EX AF,AF'
        LD IX,ORSH
        CALL FORMS
        LD IX,MS3
        LD (IX+0),#AA
        LD (IX+9),#AB
        PUSH IX
        LD IX,XORSH
        CALL FORMS
        POP IX
        LD (IX+0),#B2
        LD (IX+9),#B3
        RET
FORMS   LD C,15
        LD HL,(STS)
MS1     LD D,B
        LD E,B
        EX AF,AF'
        LD B,A
        EX AF,AF'
        DEC B
        INC B
        LD D,(IX+0)
        JR Z,MS21
MS2     SRL D
        RR E
        DJNZ MS2
MS21    LD A,(HL)
MS3     OR D
        LD (HL),A
        INC L
        LD A,L
        AND #1F
        JR Z,MS4
        LD A,(HL)
        OR E
        LD (HL),A
MS4     DEC L
        INC IX
        CALL DAD1
        LD A,H
        CP #58
        RET NC
        DEC C
        JR NZ,MS1
        RET
PL      LD A,(HL)
        LD B,E
L0      CP D
        JR Z,END
        INC A
        DJNZ L0
END     LD (HL),A
        RET
MIN     LD A,(HL)
        LD B,E
INP     AND A
        JR Z,END
        DEC A
        DJNZ INP
        LD (HL),A
        RET
;
;ИНИЦИАЛИЗАЦИЯ
;
START1  LD (TABLE),HL ; Эта от-
        ;дельная процедура, ко-
        ;торая задает координаты
        LD A,(HL)     ; стрелки
        ;так, чтобы она попадала
        ;на первую опцию.
        ADD A,A
        ADD A,A
        ADD A,A
        LD D,A
        INC HL
        LD A,(HL)
        ADD A,A
        ADD A,A
        ADD A,A
        LD E,A
        INC HL
        LD A,(HL)
        ADD A,A
        ADD A,A
        ADD A,A
        SUB 4
        LD D,A
        LD (CRDS),DE
        RET
TABLE   DEFW 0        ; Здесь
        ;будет адрес таблицы.
OPC     NOP           ; Номер
        ;новой опции.
OPC1    NOP           ; Номер
        ;старой опции.
TABLE1 X,Y,L,X1,Y1,L1, ... ,255
        ; Данные меню.

   Для успешной работы  требует-
ся:
   Составьте  таблицу   описания
опций меню  в  таком  порядке  -
сначала координата X,  затем  Y,
затем длина опции в знакоместах.
X и Y задаются в знакоместах.
   Как практически  использовать
процедуру:

PROGRAM LD HL,TEXT    ; Печатаем
        ;текст меню.
        CALL PRINT
        LD HL,TABLE1  ; В HL
        ;адрес таблицы данных
        ;меню.
        CALL START1   ; Заносим
        ;его в переменную TABLE
        ;и центрируем стрелку.
L1      CALL START    ; Вызов
        ;процедуры стрелки.
        LD A,(OPC1)   ; В A по-
        ;мещаем номер опции, на
        ;которой до нажатия
        ;выстрела стояла стрел-
        ;ка.
        CP 255        ; Если в A
        ;255, то стрелка на меню
        ;не попала и мы вновь
        JR Z,L1       ; рисуем
        ;стрелку (можно реагиро-
        ;вать по другому).
        CP 1          ; Далее
        ;проверяем на какой оп-
        ;ции стояла стрелка и
        CALL Z,PROG1  ; делаем
        ;переход на нужную подп-
        ;рограмму.
        CP 2          ; Номер НЕ
        ;ЗАВИСИТ от того как на-
        ;печатаны опции на
        JR Z,PROG     ; экране,
        ;а зависит от составлен-
        ;ной таблицы.
        и т.д.

   После нажатия выстрела  опция
остается гореть, но это не всег-
да приемлемо. Для принудительно-
го гашения опции  после  команды
CALL START надо  подать  команду
CALL BAR6.
   Не редка такая ситуация, ког-
да нам не надо  зажигать  опцию,
но необходимо  знать  попала  ли
стрелка туда, куда нам надо, для
этого:

PROGRAM LD HL,TABLE1  ; В HL ад-
        ;рес таблицы, которая
        ;состоит только из кода
        ;255
        LD (TABLE),HL ; заносим
        ;в переменную.
        CALL START    ; Вызываем
        ;подпрограмму стрелки.
        LD HL,TABLE2  ; В HL ад-
        ;рес настоящей таблицы
        ;описания.
        LD (TABLE),HL ; Заносим
        ;его в переменную.
        CALL COND     ; Ищем но-
        ;мер опции. После выхода
        ;номер будет в A, а не
        CP 255        ; в пере-
        ;менной OPC1!!!
        JR Z,PROGRAM  ; Далее
        ;обрабатываем номер
        ;как угодно.
        CP 1
        CALL Z,PROG
        и т.д.
TABLE1  DEFB 255      ; Пустая
        ;таблица.
TABLE2  X,Y,L,255     ; Настоя-
        ;щая таблица.

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

             *  *  *



Другие статьи номера:

От редакции - вступительное слово от редакции, авторы журнала.

Авторская программа - описание программы "Универсальный редактор спрайтов".

Программирование - эффект перелистывания страниц текста по синусу.

Тусовка - письма читалей: ICE'DI GRIZ о том как отмечала годовщину Челябиснкая группа Omega HC, Аншуков Владимир о снижении интереса к Спектруму в России.

Стиль - программирование: о внутренней структуре программы, то есть займемся основой алгоритмизации.

Игроскоп - краткий обзор игровых программ, появившихся в Челябинске: Freddy Kruger Live, Mortal Kombat, Zybex Remix, Gorodki, Atomic Robo Kid, Turbo Skate Fighter, Gremlins 2, Robot, Mercs, The Big Slease, UFO 2, Twin, Клятва Ночи, Trinia, Randex, Hunter, Talisman, Killed Until Dead, Supertetris, Miner, Tarzan, Final Fight, Go Bear Go, Rings Wars, 48 Утюгов, Prince of Persia и т.д.

Игроскоп - компьютерный супербоевик c великолепной графикой "Midnight Resistance"

Железо - сканирующие устройство для ZX Spectrum.

Мультролик - итоги конкурса на лучший мультролик.

Музобоз - обзор 8 музыкальных демонстраций: Fable Dream Demo, Black Galaxy, Opium Demo, Miles Mix, Chess Board, Mr.Key Gift, Rave Time Xtasy и т.д.

Музообоз - небольшое интервью Антона Шумакова/Ironman.

Музобоз - интервью Musicmaker'a Величутиной Татьяны.

Реклама - бесплатные обьявления.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Железо - Схема звуковой карты COVOX.
Interview with Pheel - интервью с известным спектрумовским художником.
Rave by Spy - Жизьтянка (Как всегда немного бреда от Spy'я).
Программирование - Вывод спрайта на экран. Вывод на виртуальный экран.
Планета шелезяка - схема RS-232 интерфейса.

В этот день...   19 апреля