
Коротко о главном
Переменные в bash
В bash нет типов данных, а еще при присваивании нельзя ставить лишних пробелов:
y=11 #правильно B="" #и это тоже правильно x = 3 #а это - неправильно
Чтобы прочитать значение переменной, перед ее именем нужно ставить знак доллара. Не возбраняется (а иногда и необходимо) заключать имя переменной в фигурые скобки, а затем перед открывающей скобкой все же ставить знак доллара. Арифметические операции (целочисленные) выполнять можно так:
r=$(( $x + $y )) #и снова обратите внимание на скобки и пробелы r=$(( ${x} + ${y} )) #можно делать и так
Массивы в bash бывают только одномерные, инициализировать их не нужно. Можно обращаться к данным по индексу, а так же задавать пачками:
map[3]=4 map[${r}]="_" map=( 1 2 3 4 5 6 ) #обратите внимание на пробелы
Ввод и вывод
Для вывода используется команда echo. Она поддерживает escape-последовательности, и это очень удобно.
echo "Hello, world!" #привет, мир! echo -en "\E[3;3f Hello, world!" #курсор будет установлен по координатам (3;3), а затем будет выведен текст echo "${x}" #переменные выводят вот так echo -en "\E[${x};${y}f Hello!" #кстати, их можно использовать в качестве параметров escape-последовательностей
Для ввода используется команда read.
read B #ожидать ввода, сохранить результат в переменную B read -n 1 B #ожидать ввода с клавиатуры одного символа read -t 1 -n 1 B #ожидать в течении секунды ввода символа с клавиатуры
Управляющие конструкции
Конструкция if-then-else:
if [[ "$B" = "Q" ]] #сравнение строк, обратите внимание на пробелы и скобки then #команды тут fi #конец сравнения if [[ "$B" -eq 3 ]] #сравнение чисел then #команды fi #конец сравнения
Конструкции while и case:
while ( [ "$B" != "Q" ] ) do #в скобках - условие, обратите внимание на пробелы и скобки #команды done case "$B" in #аналог команды switch "W" ) команда1;; #обратите внимание на скобку и пробелы "S" ) команда2;; [Q-Z] ) команда3;; #можно использовать маски, похожие на регэкспы esac #конец case
Цикл for:
for (( value=1 ; value<LIMIT; value++ )) do #где LIMIT - переменная #команды done
Интерактивная компьютерная игра Sokoban
#!/bin/bash #Компьютерная игра Sokoban #Определим карту как массив map=( W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W _ _ _ W W W W W W W W W W W W W W W W W = _ _ W W W W W W W W W W W W W W W W W _ _ = W W W W W W W W W W W W W W W _ _ = _ = _ W W W W W W W W W W W W W W _ W _ W W _ W W W W W W W W W W W W _ _ _ W _ W W _ W W W W W W _ _ o o W W _ = _ _ = _ _ _ _ _ _ _ _ _ _ _ o o W W W W W W _ W W W _ W _ W W W _ _ o o W W W W W W _ _ _ _ _ W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ) #И зададим начальные координаты грузчика x=9 y=11 #За одно на всякий случай очистим переменную B, в которую будем сохранять ввод с клавиатуры B="" #установим счетчик цикла (а за одно размер игровой карты) LIMIT=20 #Очистим экран echo -en "\E[2J" #И перейдем к главному циклу while ( [ "$B" != "q" ] ) do #Выведем карту на экран for (( mx=1 ; mx<LIMIT; mx++ )) do for (( my=1 ; my<LIMIT; my++ )) do r=$(($mx*20+$my)) #у нас нет двумерных массивов, поэтому обойдемся одномерным echo -en "\E[${mx};${my}f${map[${r}]}" done done #За одно выведем всякую полезную информацию echo -en "\E[22;2fWASD - move, Q - quit" echo -en "\E[23;2fW - wall, X - hero, = and @ - chest, o - place for chest" #И наконец - героя (чтобы курсор моргал в том месте, где он стоит) echo -en "\E[${x};${y}fX\E[${x};${y}f" #Теперь очистим переменную для ввода с клавиатуры B="" #И прочитаем один символ read -s -t 1 -n 1 B #Сбросим переменные, в которые будем сохранять относительное перемещение грузчика nx=0 ny=0 #Пришло время узнать, в какую сторону пользователь хочет переместить грузчика case "$B" in [wW] ) nx=$(( - 1));; [sS] ) nx=$(( 1));; [aA] ) ny=$(( - 1));; [dD] ) ny=$(( 1));; #На случай, если у кого-то нажат CAPS LOCK [qQ] ) B="q";; esac #Найдем координату клетки, на которую грузчик хочет перейти r=$(( ($x + $nx) * $LIMIT + $y + $ny )) #И сразу - следующую за ней r2=$(( ($x + $nx + $nx) * $LIMIT + $y + $ny +$ny )) #Если в этой клетке пусто, то if [[ "${map[${r}]}" = "_" ]] then #Можно смело менять координаты x=$(( $x + $nx )) y=$(( $y + $ny )) fi #По местам для сундуков тоже можно ходить if [[ "${map[${r}]}" = "o" ]] then x=$(( $x + $nx )) y=$(( $y + $ny )) fi #Ага, а что если ящик? if [[ "${map[${r}]}" = "=" ]] then #Если за ящиком пусто, то можно двигать if [[ "${map[${r2}]}" = "_" ]] then map[${r2}]="=" map[${r}]="_" x=$(( $x + $nx )) y=$(( $y + $ny )) fi #Если место для ящика свободно - тоже можно двигать if [[ "${map[${r2}]}" = "o" ]] then map[${r2}]="@" map[${r}]="_" x=$(( $x + $nx )) y=$(( $y + $ny )) fi fi #Столкнулись с ящиком, который стоит на месте if [[ "${map[${r}]}" = "@" ]] then #Если за ним пусто - значит, сдвинем ящик if [[ "${map[${r2}]}" = "_" ]] then map[${r2}]="=" map[${r}]="o" x=$(( $x + $nx )) y=$(( $y + $ny )) fi #Если за ним другое место - то тоже сдвинем if [[ "${map[${r2}]}" = "o" ]] then map[${r2}]="@" map[${r}]="o" x=$(( $x + $nx )) y=$(( $y + $ny )) fi fi #Возвращаемся к выводу на экран и опросу клавиатуры done #Пользователь нажал на Q - пора очистить экран от строительного мусора echo -en "\E[2J"
Уфф! Вроде все. Конечно, рекомендую подробнее почитать про bash scripting.
С нетерпением жду появления 3D-движка или хотя бы аркадного платформера на bash. На JavaScript ведь можно...

