Как стать автором
Обновить

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

Для перемещения курсора нам понадобится код ANSI-терминала <ESC>[1;1H. <ESC> – это символ с кодом 27 (033 или 0x1B).

Не сработало на Win7 Eng Pro в cmd.exe. Стакан не перерисовывается. Вместо этого рисуются новые стаканы с этим вот кодом между ними.

В Win10 выходило обновление, добавляющее поддержку ESC ANSI Sequences. Потому в более ранних осях это не работает.

Неа, в Win7 cmd.exe нормально отрабатывает Esc[1;1H если эти байты записаны в какой-нибудь test.txt и выдается команда cat test.txt.

Не cat, а type, наверное

Ну да. У меня CygWin стоит - я по привычке...

PS Нет, это зло! type как раз не работает. cat работает.

Вероятно, Cygwin'овский cat у вас как раз и обрабатывает ANSI-последовательности, преобразуя их к командам Windows console API.

Для получения ESC (а также BACKSPACE) не обязательно печатать спецсимвол напрямую. Можно получить их с помощью разбора prompt, см: https://www.cyberforum.ru/post4375870.html

Для отображения Esc-последовательностей необходимо предварительно загружать драйвер ansi.com или ansi.sys.

Не уверен, что в чистом досе и его command.com поддерживаются другие фичи, которые я тут использую

Ну да, choice в состав dos не входит. Под winxp его тоже не нашлось)

В win10 в этом необходимости уже нет.

for /f %e in ( '"prompt $E & for %e in (1) do rem"' ) do @echo:%e[91m%e[107mbright red on white%e[0m
Ваши сведения устарели лет этак на двадцать.

Для таймаутов <1s можно использовать ping localhost ;)

Можно. Но проблема в том, что нельзя проверить нажание клавиши без минимального таймаута

Да. Штош, не заложили Отцы-Основатели такую функцию в MS-DOS.

Посмотрите здесь: https://www.dostips.com/forum/viewtopic.php?f=3&t=6812

Там используются сантисекундные задержки и ввод производится с помощью set /p и одного хитрого трюка (сам еще не до конца понял его) "%~F0" Input >> pipeFile.txt | "%~F0" Main < pipeFile.txt.

Я понял, что там у них сделано.

Для ввода используется xcopy /W. Опция /W означает ждать нажатия. При этом введенный символ выводится на stdout, а сообщение "Нажмите..." - на stderr. Важно передать в качестве источника и цели для копирования существующие файлы. Иначе xcopy спросит, файл или каталог указан как цель. В данном случае bat-файл копирует сам себя в себя же. Если вы до сих под четко знали азбучную истину о том, что нельзя копировать файл в себя, забудьте. xcopy так может.

Для задержек используется цикл с проверкой, не достигла ли переменная %TIME% нужного значения. Из этой переменной берутся последние два символа - доли секунды. Перед ними добавляется единица, и действия производятся с числами от 100 до 199. Если единицу не добавлять, будет проблема с тем, что последовательность цифр, начинающаяся с нуля, означает число в 8-ричной системе. Т.е. 08 и 09 - это синтаксическая ошибка.

А трюк для ввода без задержек заключается в том, что set /P в случае, когда ввод перенаправлен от другого процесса, не ждет ввода, как это обычно происходит. Если на вводе что-то есть, оно читается. Если ничего нет, переменная не устанавливается, но выполнение скрипта продолжается без задержек. Запускаются два процесса - %0 Input и %0 Main. Input с помощью xcopy ждет ввода, интерпретирует его и выводит код действия. Main использует set /P.

Я, когда работал над статьей, рассматривал вариант с запуском процесса, который будет убивать choice.exe командой taskkill. Процесс, убитый таким образом, возвращает errorlevel 1. Надо сделать "s", т.е. движение вниз, не только вариантом по умолчанию, но еще и первым в списке и, казалось бы, всё.

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

Раз уж всё равно используются внешние программы, то почему бы не попробовать использовать другой интерпретируемый язык, который позволяет сделать меньшие задержки? Например, можно в батник воткнуть кусок кода для powershell, и вызвать сам powershell, передав ему этот же батник (да, хитро можно разделить выполнение), а в powershell есть например start-sleep -m. Можно в цикле проверять нажатие клавиши и возвращать определённый код возврата. Хотя... тогда будет сильно проще и вовсе всё на powershell переписать, там возможностей больше.

> Для ввода используется xcopy /W

Теперь все понятно. Я видел эту команду, но потом забыл о ней и все не мог понять как set /p принимает ввод клавиш без ожидания.

Прикольно конечно. А по что не в цвете если ANSI-последовательности поддерживаются?

ps: ждём змейку

Всё-то уже сделали до нас

"на bat-файлах не получится написать Doom". Легко :)

cd Doom

Doom.exe

Поиграл… М-да… Несмотря на то, что я ещё тот любитель заскриптовать… оказывается я вовсе и не фанат, а так себе)

Спасибо :)

Если кому интересно могу кинуть ссылку на свой js тетрис. там же собственно и код. что то порядка 150-200 строк

JS - это в браузере? Или Node JS? Или, может, cscript/wscript?

В FreeDOS есть DOjS «JavaScript programming environment for systems running MS-DOS, FreeDOS or any DOS based Windows (like 95, 98, ME). It features an integrated editor, graphics & sound output, mouse/keyboard/joystick input and more. The latest DOjS release V1.7.0 includes a bunch of new features»
CMD чудовищен в плане синтаксиса и практически полностью кастрирован в плане возможностей. С любым JS не сравнить.
А тут ещё и на чистом CMD (я лично давно плюнул и стал юзать греп, сторонние парсеры и самописные утилиты, иначе боль).

В wt проблемы с кодировкой

Hidden text

11 последняя, русская. wt последний или предпоследний.

А у меня 10. Что же они, в новой версии выпилили русский язык из терминала? Может, как-нибудь можно выбрать шрифт...

НЛО прилетело и опубликовало эту надпись здесь

Ещё можно попробовать скрыть курсор - чуть более гладкий вывод получим.

<ESC>[?25l

Согласен

Отличная статья и реализация Тетриса в BAT-файле, спасибо!

Я бы так вряд ли бы смог. Но от небольшой критики не могу удержаться... :)

  1. Я обычно использую кавычки в SET, чтобы включить или исключить пробелы в переменной.

:: в переменную LINE не попадёт случайный пробел:
set "LINE=║"
:: в переменную LINE попадёт обязательный пробел:
set "LINE=!LINE! "
  1. Дело вкуса, но я бы использовал для выхода из процедур/функций единый стиль: "exit /b [значение]" (вместо "goto :eof" и "exit /b <значение>").

Круто. Не хватает только подсчёта очков (и увеличения уровня влияющего на скорость падения фигур при достижении определённых значений) и отображения где-нибудь сбоку какая фигура выпадет следующей. Думаю это всё несложно реализовать.

Ах да, ещё стакан вроде бы маловат, где-то 2-3 клетки по ширине и столько же по высоте не хватает (или мне кажется?).

А что насчёт цветных фигур, слишком сложно будет это сделать?

Всё это вполне реализуемо. Для цветных фигур надо хранить для каждой клеточки не 0 или 1, а цвет. Чтобы это рендерить, нужно будет вместо того, чтобы выводить разные символы, использовать только один символ с закрашенной половинкой и менять только цвет. Цвет меняется кодами ANSI-терминала. Т.е. тут уже только Windows 10. На семерке ни в каком виде не получится.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий