Как сделать часы в qbasic

Добавил пользователь Alex
Обновлено: 18.09.2024

0. Часть Нулевая. Предисловие
День Добрый. Данная писанина предназначена для тех, кто хочет начать заниматься программированием, но не знает на чем и не знает как. Поэтому я постараюсь все объяснять доступно, по рабоче-крестьянски. И, в отличие от всяких там книжек, если у вас в голове возникли каке-либо мысли вроде: "Ни чего не понял, чего этот тип написал" вы можете без проблем написать мне о своей проблеме на мыло: m_rechkov@yourline.ru, или, как вариант, набрать в поле ввода адреса своего браузера (или броузера) http://quitbasic.narod.ru (если кто не знает - один из лучших сайтов в Рунете по QBasic'у) и зайти на форум. Там я или оные лица попробуют ответить и помочь (но не деньгами). Итак, здесь будут объясняться ОСНОВЫ и некоторые ПРОСТЫЕ РЕШЕНИЯ сложных проблем без вникания в их суть. После изучения энного количества килобайт текста вы сможете более-менее ориентироваться в QBasic'e. Если этого не случится, значит либо я плохо поработал (чего не может быть! Однозначно!), либо ваш отец Папа Карло. Начнем.
1. Часть Первая - А где его взять, этот Бейсик?
Здесь и далее будет идти речь о QuickBasic'e 4.5 А где ж его взять-то? Вариант первый - зайти на вышеупомянутый сайт, кликнуть на [Архив] -> [Компиляторы] и скачать себе нужную версию. Весит она около мегабайта. Вариант второй - берите где хотите.
2. Часть Вторая - Как запустить этот Бейсик?
Ну, допустим, скачали вы себе архив, разархивировали куда-нибудь в c:\qb. "А че дальше-то?" - хотите вы сказать. А мы заходим в папку с Бейсиком и запускаем файл QB.EXE. Видим примерно такой пейзаж:

На этой картинке я накалякал немного пояснений. Большинство из пунктов меню нам нахрен не нужно, а вот некоторые из пунктов мы сейчас рассмотрим
3. Часть Третья - Интерфейс или че-куда тыкать
Начнем с меню File (для того чтобы открыть это меню нужно щелкнуть на нем мышкой или, по-пацански, нажать ALT а потом на F). В нем есть пункты New Program - создать новую программу; Open Program. - открыть программу; Save и Save As. - сохранить и сохранить как, и Exit - остальные нам не понадобятся. В меню Edit: Undo - отменить последний ввод; Cut - вырезать в буфер; Copy - копировать туда же; Paste - вставить оттуда; Clear - удалить все нахрен. А теперь слушайте внимательно: посмотрите на клавиатурные комбинации рядом с командами - быстро выучите их и не вздумайте лазить в это меню для редактирования! Все делайте только с клавиатуры! Этим вы продлите себе жизнь лет на 10-15. Меню Search: Find - найти какие-нибудь символы, а Change - найти что-нибудь, а потом заменить (иногда довольно полезная вещь). Run: Start- запуск написанного вами кода с начала; Continue - продолжение выполнения программы после прерывания ее. Make EXE File. - позволяет сделать из *.bas файла настоящую EXE-версию вашего кода, чтобы ее можно было запускать на машине без Бейсика. Подробнее мы рассмотрим ее позднее. Ну и хватит - остальное посмотрите сами, если понадобится. Внимание! Запомните это: чтобы переключиться на рус. язык надо зажать правый контрл и правый альт, а чтобы на англ. язык, то на те же клавиши, только слева. И еще - если вы запустили программу, а выхода из нее не предусмотрели, то зажмите Ctrl+Break и все будет хорошо. И еще, чтобы при наборе кода перейти на новую строку нажмите на [ENTER]. А теперь постарайтесь выучить самое важное, покурите (но не шмаль! Шмаль будете курить, когда дело дойдет до программирования. Иногда, чтобы найти решение, бывает нужно погрузиться в Нирвану)
4. Часть Четвертая - Начинаем программировать
Тушим папиросу, запускаем Бейсик и вводим следующий код
CLS
PRINT "Hello World!"
END
И запускаем полученную программу ("А как это сделать?" - скажете вы. Или не скажите? А если скажите, то - ЧИТАЙТЕ Часть №3) SHIFT+F5
И чего мы видим? А видим мы на пустом и черном фоне надпись белыми буквами : Hello World! Ага, а теперь можете налить себе стакан красного - вы написали свою первую прогу! Только вы сами ни хрена не поняли, чего написали. Так? Но сейчас мы все разберем. Вверху у нас стоит команда CLS . Это команда очистки экрана, т.е. после этой команды экран напрочь очищается и предстает перед нами в девственном виде. А дальше идет оператор PRINT . Он позволяет выводить символы на экран. В нашем случае мы выводим ТЕКСТ, поэтому текст мы заключаем в кавычки, а если бы мы захотели вывести на экран число, то кавычки бы мы не ставили, а писали просто PRINT 999 или PRINT 7.5 (заметьте, в Бейсике дробную часть отделяет точка, а не запятая). Попробуете теперь вывести на экран надписи: Rock - лучшая музыка в мире! и Аквариум, Калинов Мост, The Doors, а также числа: 75, 0.55, 1234567890. Получается? Хорошо. А сейчас попробуйте убрать CLS и несколько раз подряд запустить программу - вы наглядно убедитесь для чего это самое CLS нужно. А теперь сделайте так, чтобы под надписью Hello World! шла цифра 777. Надеюсь, ума у вас хватит.
5. Часть Пятая. Переменные - или САМОЕ ВАЖНОЕ
Теперь о самом важном. Вам необходимо уяснить понятия о переменных и операторе присваивания. Итак, переменная, это - область данных, имеющая имя. По простому, мы можем присваивать разное значение одинаковым именам. Исполните эту программу:
CLS
a=100
text$="РОК"
PRINT a
PRINT text$
END
Ага, что у нас получилось. Получилось то, что на экране вывелось число 100, а под ним надпись РОК. Почему так получилось? Разберем все по проядку. Что означает строка a=100 . Она означает то, что переменной под именем [a] присвоили значение [100], а знак [=] и есть оператор присваивания, т.е. он присваивает переменной определенное значение. Строка text$="РОК" означает то же самое, что и предыдущая,только тут не число, а текст и на конце переменной стоит символ $, и значение переменной будет текстовое, а раз текстовое, то мы его заключаем в кавычки. Такая переменная называется строковой. А после команд PRINT мы просто подставляем имя нужной нам переменной и эта самая переменная выводится на экран. Теперь о том, какие имена могут быть у переменных. Запомним, имена должны состоять только из латинских букв и они не должны начинаться с цифры, большие и маленькие буквы Бейсиком не различаются. Т.е. возможны такие имена файлов: a, abc$, nom1, LaLa, а нельзя вводить так: Ш, 1a, abГ. Переменную можно приравнять к другой переменной. К примеру, введем такой код:
N1=200
N2=N1
PRINT N2
Все, с этим разобрались. Вся эта часть очень важна. Если не поняли ее содержания, то купите себе веревку, мыло и табуретку.
6. Часть Шестая. Все об операторе PRINT и математика в Бейсике
Переменной можно присвоить не только какое-либо значение, но также и математическую формулу, например a=100*2-10, или b=(a+150)*2.75 А теперь о том ,как в Бейсике записывать эти самые формулы правильно. Ну, во-первых, как и в математике сначала выполняются действия в скобках, потом умножения и т.д. Знак умножения выглядит так: [*], деления: [/], ну [+] и [-] это понятно, степени: ^ n(зажми шестерку при нажатом шифте), где n - сама степень, SQR(n) - квадратный корень (т.е. вместо n в скобки подставляем нужное), SIN(n)- это синус, такого же вида и COS, TAN и т.д. INT(n) - что-то вроде округления. Остальные математические штуки можно всегда посмотреть во встроенное справке Бейсика. И еще, запомните одну вещь: нельзя, как в математике, писать слитно цифру и переменную, т.е. забудте про 2a, писать надо 2*a. Все, с математикой покончено.
Теперь разберемся с PRINT'oм. В передыдущих примерах мы писали подряд два оператора PRINT и притом , что должен был вывести второй оператор он выводил на другой строке. А что делать, если надо на той же? Смотрим:
CLS
a=5^2
PRINT "5 во второй степени будет равно ";a; " и это правда"
Посмотрим, что у нас получилось. В одну строку все вместилось, правда ведь? Разберем все последовательно: сначала идет текст, послне него идет [;], после этой точки с запятой можно писать еще что-нибудь в том же операторе и это что-нибудь будет выводится на той же строке; а у нас здесь стоит переменная a, которой мы присвоили нужное нам значение, после переменной опять [;] и завершающая фраза. Вместо [;] можно поставить [,], тогда текст будет выводится через определенное кол-во символов. Это бывает полезно для создания вякого рода таблиц. Еще одно примечание: в PRINT можно подставлять не переменные а сразу формулы, например можно записать и так: PRINT "5 во второй степени будет равно ";5^2; " и это правда".
7. Часть Седьмая. Первая игра
Готовтесь, дети мои. Сейчас мы создадим первое подобие игры. Пишем код:
CLS
PRINT "Игра: Крутой Математик"
PRINT "Решите пример: (500-100)*2"
Nach:
INPUT a
IF colO = 5 THEN PRINT "Тебе ничто уже не поможет": END
IF a = (500 - 100) * 2 THEN PRINT "Ты умный тип, однако!": END
IF a <> (500 - 100) * 2 THEN PRINT "Учи математику, идиот. Попробуй снова:": colO = colO + 1: GOTO Nach
Итак, запустите эту писанину и посмотрите, что она делает. А она делает вот что: сначала выводится название игры и задание - вычислить то-то то-то. А затем идет знак вопроса, после которого вы вводите нужное число и жмете на [ENTER]. Если число равно (500-100)*2, т.е. 800, то выводится надпись [Ты умный тип, однако!] и прогамма завершает работу, а если ответ неправильный, то пишется [Учи математику, идиот. Попробуй снова:] и все повторяется заново, но если вы настолько умалишенны, что за пять попыток не подсчитаете нужное число, то программа выводит [Тебе ничто уже не поможет] и завершает свою работу.
Сейчас разберем новые команды. Ну, сначала определим, что означает знак [:], а он просто-напросто позваляет выполнить другую команду в той же строке, для экономии, так сказать, экранного места. Оператор INPUT позволяет вам вводить нужные данные с клавиатуры. В нашем случае с помощью него мы вводим значение числовой переменной a. То что мы введем, то и будет новым значением переменной. А теперь о операторе IF THEN, дословно он означает [ЕСЛИ] . [ТО] . Т.е. в строке IF a = (500 - 100) * 2 THEN PRINT "Ты умный тип, однако!": END происходит следующее: ЕСЛИ a=столько-то, TO пишем такой-то текст и завершаем программу. Понятно, да? А теперь о том, что мы делаем, для того чтобы после пяти неправильных попыток программа писала о вас, то что она думает. За счетчик попыток мы взяли переменную colO, по умолчанию все переменные равны нулю. Теперь разберем строку IF a <> (500 - 100) * 2 THEN PRINT "Учи математику, идиот. Попробуй снова:": colO = colO + 1: GOTO Nach Получается: ЕСЛИ a не равно (знак <> означает не равно) нужному числу ТО пишем текст и добавляем к переменной colO единицу, т.е. она будет равна своему предыдущему значению плюс единица (очень важно это понять!). И когда у нас эта переменная будет равна пяти, то мы с помощью стоки IF colO = 5 THEN PRINT "Тебе ничто уже не поможет": END напишем нужное нам и завершим программу. А как нам сделать так, чтобы программа возвращалась к вводу переменной a, если ответ неправилен. Смотрим на предыдущую строку и видим: GOTO Nach . Оператор GOTO - это безусловный переход. Т.е. при обращении к этому оператору программа переходит к указанной в операторе метке, в нашем случае метка носит название Nach . Теперь посмотрите на 4-ю строчку кода: Nach: После метки в программе всегда ставится двоеточие, чтобы Бейсик понял, что это метка. Следовательно, после нашей команды GOTO программа переходит к этой метке и снова начинает выполнять строку INPUT a. Теперь вам все должно быть понятно. Главное во всем разобраться. Попробуйте видоизменить программу, добавить в нее что-нибудь. Изменить формулу. Добавить всякие надписи или усложнить условие. Главное, чтобы у вас было 15-20 грамм мозгов и до хрена терпения. А, кстати, попробуйте убрать строку где написано "Решите..", а строку с инпутом измените так: INPUT "Решите пример: (500-100)*2"; a. Так будет лучше.
8. Часть Восьмая. Сохранение, Загрузка, Компилирование
Что же делать, если вы хотите сохранить ваше первое жалкое подобие игры? Воспользуемся меню File -> Save. Нам откроется следующее окно:

Учитель: С какими видами графики вы знакомы? (Растровая графика, векторная графика)
Каковы особенности каждого вида графики?

Сегодня мы выясним, можно ли использовать язык программирования Quick Basic для создания изображений, и к какому виду графики можно отнести это изображение.

Прежде чем работать с графикой Quick Basic, необходимо задать графический режим экрана при помощи команды SCREEN N, где N – номер графического режима. Режимы отличаются разрешением и количеством цветов. В качестве примера рассмотрим режим SCREEN 9:


Также можно изменить цвет фона при помощи оператора COLOR,C, где C – номер цвета в палитре.

  1. Использование графических примитивов
  2. Использование макроязыка GML.

1. Создание изображений при помощи графических примитивов (см. Приложение 2)

PSET (X, Y), C , где:
(Х, У) – координаты точки на экране
С – номер цвета

LINE(X1,Y1) – (X2,Y2), C где:
(X1,Y1) – координаты начальной точки отрезка
(X2,Y2) – координаты конечной точки отрезка
C – номер цвета линии

LINE(X1,Y1) – (X2,Y2), C, B
где:
(X1,Y1) – координаты начальной точки диагонали прямоугольника
(X2,Y2) – координаты конечной точки диагонали прямоугольника

Закрашенный прямоугольник:
LINE(X1,Y1) – (X2,Y2), C, BF

CIRCLE (X,Y), R, C
(X,Y) – координаты центра окружности
R – радиус окружности
C – номер цвета линии

5) Дуга окружности

CIRCLE (X,Y), R, C, L1, L2 где:
(X,Y) – координаты центра окружности
R – радиус окружности
C – номер цвета линии
L1 – начальное значение угла вычерчивания дуги
L2 – конечное значение угла вычерчивания дуги

CIRCLE (X,Y), R, C, L1, L2, К где:
(X,Y) – координаты центра эллипса
R – радиус окружности
C – номер цвета линии
L1 – начальное значение угла для вычерчивания дуги эллипса
L2 – конечное значение угла для вычерчивания дуги эллипса
К – коэффициент сжатия дуги эллипса


Если рисуется эллипс, то параметры L1 и L2 отсутствуют, т.е. оператор имеет вид:
CIRCLE (X,Y), R, C, , , К

Если параметры L1 и L2 в операторах
CIRCLE (X,Y), R, C, L1, L2 (для дуги окружности)
CIRCLE (X,Y), R, C, L1, L2, К (для дуги эллипса)
отрицательные, то концы дуги соединяются отрезками с центром окружности (эллипса), т.е. вычерчивается круговой сектор.

9) Закраска ограниченной области

PAINT (X,Y), C1, C2 где:
(X,Y) – координаты любой точки внутри контура
C1 – номер цвета, которым закрашивается контур
С2 – номер цвета самого контура

Пример рисования объекта:

SCREEN 9
CIRCLE (159, 99), 80, 12: PAINT (159, 99), 12, 12
CIRCLE (89, 99), 39, 12: PAINT (78, 98), 12, 12
CIRCLE (228, 99), 39, 12: PAINT (248, 98), 12, 12
CIRCLE (120, 99), 15, 12, , , 3: PAINT (120, 99), 12, 12
CIRCLE (198, 99), 15, 12, , , 3: PAINT (198, 99), 12, 12
CIRCLE (120, 70), 19, 8, , , .5: PAINT (120, 70), 15, 8
CIRCLE (120, 70), 12, 6: PAINT (120, 70), 6, 6
CIRCLE (199, 70), 19, 8, , , .5: PAINT (199, 70), 15, 8
CIRCLE (199, 70), 12, 6: PAINT (199, 70), 6, 6
CIRCLE (159, 99), 20, 7, , , 2
CIRCLE (159, 130), 23, 4, 3.14, 6.28, .5
CIRCLE (159, 130), 24, 4, 3.14, 6.28: PAINT (159, 145), 4, 4
LINE (159, 40) – (110, 50), 8 : LINE (159, 40) – (130, 50), 8
LINE (159, 40) – (159, 50), 8 : LINE (159, 40) – (188, 50), 8
LINE (159, 40) – (208, 50), 8

Итог:


2. Создание изображений при помощи макроязыка GML (см. Приложение 3).

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


В программе Криса порождающее значение (seed) PRNG связано с системными часами ( RANDOMIZE TIMER , идиомой QBasic). Программа заполняет массив спонсорами, представленными в виде целых чисел (индексов), а потом постоянно перемешивает список, пока пользователь не нажмёт клавишу, после чего, наконец, выводит случайную выборку из массива. Вот упрощённая версия программы (примечание: комментарии в QBasic начинаются с апострофа ' ):

В конечном итоге, готовый результат — это функция от всего трёх множеств входных данных:

RND в QBasic

PRNG языка QBasic представляет собой такой 24-битный линейный конгруэнтный метод (Linear Congruential Generator, LCG):


Результатом является полное 24-битное состояние. RND делит его на 2^24 и возвращает результат как число с плавающей запятой одиночной точности, поэтому вызывающая программа получает значение в интервале от 0 до 1 (не включая 1).

Не стоит говорить, что это очень плохой PRNG. Константы LCG выбраны разумно, но странно, что было решено ограничить состояние 24 битами. Согласно 16-битному ассемблерному коду QBasic (примечание: перечисленные здесь константы LCG неверны), реализация является полным значением, кратным 32 битам и состоящим из 16-битных частей, и при сохранении результата она выделяет память и записывает все 32 бита. Как и можно ожидать для 8086, от использования только нижних 24 бит реализация ничего не выигрывает.

Чтобы показать, насколько он плох, покажу рандограмму этого PRNG, в которой заметна очевидная структура. (Это небольшой срез рандограммы размером 4096x4096, в которой каждый из 24-битных сэмплов 2^23 нанесён на график как две 12-битные координаты.)


Общепризнанно, что это сильно ограничивает PRNG. При 24-битном состоянии он хорош только для 4 096 (2^12) выходных значений, после чего он больше не следует парадоксу дней рождения: никакие выходные значения не повторяются, хотя мы должны увидеть повторения. Однако, как я покажу ниже, на самом деле это неважно.

Вместо того, чтобы отбрасывать верхние 8 бит — самые высококачественные выходные биты — проектировщики QBasic должны были отказаться от нижних 8 бит, превратив реализацию в урезанный 32-битный LCG:


Этот LCG имел бы такую же производительность, но со значительно лучшим качеством. Вот рандограмма этого PRNG, и она тоже сильно ограничена (больше 65 536 (2^16) выходных значений).


Качественное улучшение, и получили мы его совершенно бесплатно!

RANDOMIZE в QBasic

Но это ещё не конец наших проблем. Конструкция RANDOMIZE получает seed с двойной точностью (т.е. 64-битной). Верхние 16 бит его двоичного представления по IEEE 754 подвергаются XOR с следующими верхними 16 битами. Верхним 16 битам состояния PRNG присваивается этот результат. Самые нижние 8 бит сохраняются.

Чтобы это стало понятнее, приведу реализацию на C, проверенную по QBasic 7.1:


Другими словами, RANDOMIZE задаёт генератору PRNG только одно из 65 536 возможных состояний.

В качестве последнего примера: вот как реализован RND , тоже проверенный по QBasic 7.1:

Seed по системным часам

Функция TIMER возвращает количество секунд с одиночной точностью, прошедших с полночи, и точность составляет ~55 мс (т.е. равна счётчику прерываний таймера 18,2 Гц). Это только время суток, в результат не входит текущая дата, как это происходит, например в unix-времени.

Это означает, что TIMER может возвращать всего 1 572 480 уникальных значений. Это количество мало даже без учёта того, что конструкцией RANDOMIZE они сопоставляются всего с 65 536 возможными seed. К счастью, все эти значения реализуемы с помощью TIMER .

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

Итерации цикла

Идея Криса по постоянному перемешиванию массива до нажатия клавиши в большой степени компенсирует слабость PRNG языка QBasic. Он позволяет выполнять более 200 000 обменов массива, проходя более 2% периода PRNG, и сам массив используется как расширенное состояние PRNG, дополняя 24-битное состояние RND .

Поскольку итерации происходят так быстро, точное количество итераций становится ещё одним источником энтропии. Результаты при выполнении в течение 214 600 итераций будут сильно отличаться от результатов при 273 500 итераций.

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

Заменяем PRNG

Поскольку встроенный PRNG настолько плох, мы можем улучшить ситуацию, реализовав новый в самом QBasic. Сложность в том, что в QBasic нет беззнаковых integer, нет даже операторов с беззнаковыми integer (например, >>> из Java и JavaScript), а переполнение значений со знаком является ошибкой времени выполнения. Мы даже не можем заново реализовать сам LCG языка QBasic без выполнения программного умножения long, потому что промежуточный результат переполняет его 32-битный LONG .

При таких ограничениях популярными вариантами выбора являются генератор Парка-Миллера (как мы видели это в Bash) или запаздывающий генератор Фибоначчи (он используется в Emacs, который долгое время был ограничен 29-битными integer).

Однако у меня есть идея получше: PRNG, основанный на RC4. Точнее, мой собственный проект называется Sponge4, функцией губки поверх RC4. Если вкратце: для примешивания дополнительных входящих данных достаточно снова выполнить развёртывание ключа. Для реализации этого PRNG требуются всего две простые операции: сложение по модулю 2^8 и обмен массивов. В QBasic есть конструкция SWAP , поэтому такая система очень ему подходит!

Sponge4 (RC4) обладает гораздо более качественными результатами, чем 24-битный LCG, и к нему можно примешать больше источников энтропии. При своём 1700-битном состоянии он без потерь может впитать довольно много энтропии.

Изучаем QBasic

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

Реализуем Sponge4

Как и в RC4, мне нужен 256-элементный массив байтов и два 1-байтных индекса, i и j . Sponge4 также хранит третий 1-байтный счётчик k для подсчёта входящих данных.


QBasic не имеет типа byte. Обычно в таком случае подходит 256-байтная строка фиксированной длины, но поскольку здесь они не являются массивами, строки несовместимы со SWAP и не индексируются эффективно. Поэтому я решил смириться с неиспользуемым пространством и использовать для всего 16-битные integer.


Инициализация выполняется в соответствии с RC4:


Для сжатия байта может сначала потребоваться примешивание состояния, после чего производится обычное выполнение генератора RC4.


Вот и весь генератор на QBasic! Однако нам будет полезна пара вспомогательных функций. Одна поглощает целые строки, а вторая возвращает 24-битные результаты.


QBasic не имеет операций битового сдвига, поэтому приходится пользоваться умножением. &H — это шестнадцатеричная запись.

Используем губку в деле

Одна из проблем исходной программы заключается в том, что в seed используется только время суток. Даже если смешивать его получше, то при запуске ровно в один и тот же момент в два разных дня мы получим одинаковый seed. Функция DATE$ возвращает текущую дату, поэтому мы можем поглотить её в губку, сделав частью входящих данных дату целиком.


За этим следует таймер. Он преобразуется в строку при помощи MKS$ , возвращающей двоичное представление с одиночной точностью в little-endian в виде 4-байтной строки. MKI$ делает то же самое для INTEGER в виде 2-байтной строки.

Одной из проблем исходной программы было смещение: умножение RND на константу с последующим усечением результата до integer в большинстве случаев неоднородно. Некоторые числа выбираются чуть чаще, чем остальные, потому что входящие данные 2^24 не могут равномерно быть сопоставлены, допустим, с 10 выходящими данными. Учитывая, что в исходной программе используется перемешивание массива, это, вероятно, не имеет на практике разницы, но я бы хотел этого избежать.


Затем выполняем тасование Фишера-Йетса и вывод первых N элементов:


Но если вам очень понравилась идея Криса, то можно сделать так:


Если вы хотите проверить программу самостоятельно, допустим, в DOSBox, вот её полные исходники: sponge4.bas .

На правах рекламы

Эпичные серверы — это виртуальные серверы для любых задач. Вы можете создать собственный тарифный план, максимальная конфигурация — 128 ядер CPU, 512 ГБ RAM, 4000 ГБ NVMe!


Мои поиски приводили меня на бесконечные форумы, благодаря которым я попробовал бесчисленное множество рекомендуемых языков и платформ: SmallBasic, Pico-8, Smalltalk, Scratch и т.д. Я даже задавал вопросы великим оракулам StackOverflow, но тщетно. Спустя пять месяцев я пришёл к разочаровывающему выводу: ничто и близко не сравнимо с тем, что было у меня в мои годы. 30 лет спустя QBasic по-прежнему остаётся лучшим языком для новичков в программировании.

Сегодня я установил QBasic на 11-дюймовый HP Stream сына, установку пришлось выполнять вручную через DOSBox. Он дважды нажал на значок рабочего стола и спустя долю секунды мы уже увидели IDE, приветствовавшей нас вводным экраном, который вызвал у меня кучу воспоминаний:


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

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


Мы изучили ещё пару команд: CLS, COLOR, PLAY, INPUT и IF. Ничего не нужно было объяснять: никакой сложности, никаких неуклюжих операторов, никаких абстрактных концепций, никакой документации, которую необходимо изучать, никаких концепций объектов/классов/методов, не требовалась установка никаких фреймворков, нет кучи меню и кнопок в IDE, никаких специальных ключевых слов или скобок. Это был код во всей его чистейшей простоте и форме.

Спустя менее часа он написал собственную программу — интерактивное и невероятно изощрённое приложение, сообщающее о том, что думает о вас компьютер:


… которое Ноа с искренней гордостью запустил для своего двоюродного брата и лучшего друга Кристиана:


… после чего он легко объяснил, как оно работает и что делает код!


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


Я был так рад, что он понял, почему я постоянно говорю, что у меня лучшая работа в мире.

Единственное, о чём я сейчас сожалению, так это о том, что за тридцать с лишним лет мы не смогли придумать для детей чего-то лучшего: Qbasic имеет ограниченное множество простых ключевых слов (вся справка умещается на одном экране, вызываемом по F1, и дополнена простыми примерами!), не отвлекает кодера визуальными артефактами, обладает очень компактной и уютной средой разработки, сразу же указывает на ошибки, компилирует и исполняет код за доли секунды нажатием одной клавиши, и к тому же чрезвычайно прост. Мы создали более надёжные и сложные языки/фреймворки/IDE (которые, разумеется, необходимы для любого практичного приложения), но никогда не придумывали более простого способа получить прямой доступ к удовольствию от программирования, чем QBasic. Даже запуск QBasic сегодня стал пугающей задачей для новичков, работающих на современной машине Mac/PC/Linux, хотя раньше для этого достаточно было просто вставить 3,5-дюймовую дискету в дисковод A:\…

Но, впрочем, хватит проповедей, сегодня ведь нужно праздновать знакомство ещё одного человека с радостями и красотой программирования!

На правах рекламы

Наша компания предлагает современные серверы в аренду для любых проектов. Создайте собсвенный тарифный план в пару кликов, максимальная конфигурация бьёт рекорды — 128 ядер CPU, 512 ГБ RAM, 4000 ГБ NVMe!

Читайте также: