Speccy
#06
31 августа 1996 |
|
Стиль - программирование: о внутренней структуре программы, то есть займемся основой алгоритмизации.
╒══════════════════════════════╕ │░░░░░░░ НОВАЯ РУБРИКА ░░░░░░░│ ╘══════════════════════════════╛ Уважаемые читатели журнала,раз- решите представить вам нового сотрудника редакции журнала "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 ; Настоя- ;щая таблица. На этом позвольте закончить сее повествование. Рад, если ко- му-то эта информация поможет. * * *
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября