Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

БAL Лаб4

.docx
Скачиваний:
0
Добавлен:
05.09.2026
Размер:
212 Кб
Скачать

МИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ, СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ

УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ

«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ТЕЛЕКОММУНИКАЦИЙ ИМ. ПРОФ. М.А. БОНЧ-БРУЕВИЧА»

(СПбГУТ)

Факультет Кибербезопасности

Кафедра Защищенных систем связи

Дисциплина Безопасность Astra-Linux

ОТЧЕТ ПО ЛАБОРАТОРНОЙ РАБОТЕ №4

Введение в язык командного интерпретатора Bash

(тема работы)

Направление/специальность подготовки

10.05.02 «Информационная безопасность телекоммуникационных систем»

(код и наименование направления/специальности)

Студенты:

(Ф.И.О., № группы) (подпись)

(Ф.И.О., № группы) (подпись)

Преподаватель:

ст.преп. Гельфанд А.М.

(уч. степень, уч. звание, Ф.И.О.) (подпись)

ТЕКСТ ЗАДАНИЯ

Цель лабораторной работы

  1. Ознакомится с языком одной из самых популярных командных оболочек

Linux– bash(Bourneagainshell).

  1. Изучить создание переменных, организацию циклов и ветвлений.

  2. Освоить работу с массивами и передачу аргументов в программу.

  3. Освоить ввод данных в программу с клавиатуры.

  4. Получить навык написания простейших скриптов.

Используемое программное обеспечение

Для выполнения лабораторной работы используется установленный

дистрибутив ОС Linux с установленным bash (является стандартным в

большинстве дистрибутивов).

ХОД РАБОТЫ

1. Создали файл скрипта и написали код с помощью команды nano «lab4.sh» (рис. 1).

Рис.1 – Текст программы

2. Сделали файл исполняемым благодаря команде «chmod +x lab4.sh».

3. Проверили работу программы (рис. 2, рис. 3).

Рис. 2 – Игровой процесс

Рис. 3 – Конец игры

ЛИСТИНГ ПРОГРАММЫ

#!/usr/bin/env bash

# Объявление основных переменных игры

declare -ia board # игровое поле как массив чисел

declare -i pieces # количество заполненных ячеек

declare -i score=0 # счет игрока

declare -i flag_skip # флаг для предотвращения многократных сдвигов

declare -i moves # счетчик возможных ходов

declare ESC=$'\e' # escape-символ для управления курсором

# Настройки игры по умолчанию

declare -i board_size=4 # размер поля 4x4

declare -i target=2048 # целевое число для победы

# Цвета для отображения чисел

declare -a colors

colors[2]=33 # желтый

colors[4]=32 # зеленый

colors[8]=34 # синий

colors[16]=36 # голубой

colors[32]=35 # фиолетовый

colors[64]="33m\033[7" # желтый фон

colors[128]="32m\033[7" # зеленый фон

colors[256]="34m\033[7" # синий фон

colors[512]="36m\033[7" # голубой фон

colors[1024]="35m\033[7" # фиолетовый фон

colors[2048]="31m\033[7" # красный фон

exec 3>/dev/null # отключение логирования по умолчанию

trap "end_game 0 1" INT # обработка прерывания Ctrl+C

# Функция для генерации последовательности чисел (замена seq)

function _seq {

local cur=1

local max

local inc=1

case $# in

1) let max=$1;;

2) let cur=$1

let max=$2;;

3) let cur=$1

let inc=$2

let max=$3;;

esac

while test $max -ge $cur; do

printf "$cur "

let cur+=inc

done

}

# Функция отрисовки игрового поля

function print_board {

clear # очистка экрана

printf "Board status:\n" >&3 # логирование в файл

printf "\n"

# Отрисовка верхней границы поля

printf '/------'

for l in $(_seq 1 $index_max); do

printf '+------'

done

printf '\\\n'

# Отрисовка строк с числами

for l in $(_seq 0 $index_max); do

printf '|'

for m in $(_seq 0 $index_max); do

if let ${board[l*$board_size+m]}; then # если ячейка не пустая

if let '(last_added==(l*board_size+m))|(first_round==(l*board_size+m))'; then

# Красный цвет для новых плиток

printf '\033[1m\033[31m %4d \033[0m|' ${board[l*$board_size+m]}

else

# Цвет в зависимости от значения

printf "\033[1m\033[${colors[${board[l*$board_size+m]}]}m %4d\033[0m |" ${board[l*$board_size+m]}

fi

printf " %4d |" ${board[l*$board_size+m]} >&3 # логирование

else

printf ' |' # пустая ячейка

printf ' |' >&3

fi

done

let l==$index_max || {

# Разделитель между строками

printf '\n|------'

for l in $(_seq 1 $index_max); do

printf '+------'

done

printf '|\n'

printf '\n' >&3

}

done

# Нижняя граница поля

printf '\n\\------'

for l in $(_seq 1 $index_max); do

printf '+------'

done

printf '/\n'

}

# Генерация новой плитки на поле

function generate_piece {

while true; do

let pos=RANDOM%fields_total # случайная позиция

let board[$pos] || { # если ячейка пустая

let value=RANDOM%10?2:4 # 90% - 2, 10% - 4

board[$pos]=$value

last_added=$pos # запоминаем позицию новой плитки

printf "Generated new piece with value $value at position [$pos]\n" >&3

break;

}

done

let pieces++ # увеличиваем счетчик плиток

}

# Функция сдвига плиток в заданном направлении

function push_pieces {

case $4 in # определение направления

"up") # вверх

let "first=$2*$board_size+$1"

let "second=($2+$3)*$board_size+$1"

;;

"down") # вниз

let "first=(index_max-$2)*$board_size+$1"

let "second=(index_max-$2-$3)*$board_size+$1"

;;

"left") # влево

let "first=$1*$board_size+$2"

let "second=$1*$board_size+($2+$3)"

;;

"right") # вправо

let "first=$1*$board_size+(index_max-$2)"

let "second=$1*$board_size+(index_max-$2-$3)"

;;

esac

let ${board[$first]} || { # если первая ячейка пустая

let ${board[$second]} && { # и вторая не пустая

if test -z $5; then # если не фейковый ход

board[$first]=${board[$second]} # перемещаем плитку

let board[$second]=0

let change=1 # отмечаем изменение

printf "move piece with value ${board[$first]} from [$second] to [$first]\n" >&3

else

let moves++ # увеличиваем счетчик возможных ходов

fi

return

}

return

}

let ${board[$second]} && let flag_skip=1 # блокировка дальнейших сдвигов

let "${board[$first]}==${board[second]}" && { # если значения равны

if test -z $5; then # если не фейковый ход

let board[$first]*=2 # объединяем плитки

let "board[$first]==$target" && end_game 1 # проверка победы

let board[$second]=0

let pieces-=1 # уменьшаем счетчик плиток

let change=1 # отмечаем изменение

let score+=${board[$first]} # увеличиваем счет

printf "joined piece from [$second] with [$first], new value=${board[$first]}\n" >&3

else

let moves++ # увеличиваем счетчик возможных ходов

fi

}

}

# Применение сдвига ко всему полю

function apply_push {

printf "\n\ninput: $1 key\n" >&3

for i in $(_seq 0 $index_max); do

for j in $(_seq 0 $index_max); do

flag_skip=0

let increment_max=index_max-j

for k in $(_seq 1 $increment_max); do

let flag_skip && break # если сдвиг заблокирован

push_pieces $i $j $k $1 $2 # сдвиг плитки

done

done

done

}

# Проверка доступных ходов

function check_moves {

let moves=0

# Проверяем все направления

apply_push up fake

apply_push down fake

apply_push left fake

apply_push right fake

}

# Обработка нажатий клавиш

function key_react {

let change=0 # сбрасываем флаг изменений

read -d '' -sn 1 # чтение одного символа

test "$REPLY" = "$ESC" && { # если нажата ESC

read -d '' -sn 1 -t1

test "$REPLY" = "[" && { # стрелки

read -d '' -sn 1 -t1

case $REPLY in

A) apply_push up;; # стрелка вверх

B) apply_push down;; # стрелка вниз

C) apply_push right;; # стрелка вправо

D) apply_push left;; # стрелка влево

esac

}

} || { # обычные клавиши

case $REPLY in

k) apply_push up;; # vim-стиль

j) apply_push down;;

l) apply_push right;;

h) apply_push left;;

w) apply_push up;; # wasd-стиль

s) apply_push down;;

d) apply_push right;;

a) apply_push left;;

esac

}

}

# Завершение игры

function end_game {

print_board # показываем финальное состояние

stty echo # включаем отображение ввода

printf "Game over\n" # сообщение о завершении

exit 0

}

# Функция помощи

function help {

cat <<END_HELP

Usage: $1 [-b INTEGER] [-t INTEGER] [-l FILE] [-h]

-b размер игрового поля (от 3 до 9)

-t целевое число для победы (степень двойки)

-l файл для логирования отладочной информации

-h показать эту справку

END_HELP

}

# Парсинг аргументов командной строки

while getopts "b:t:l:h" opt; do

case $opt in

b ) board_size="$OPTARG" # установка размера поля

let '(board_size>=3)&(board_size<=9)' || {

printf "Invalid board size, please choose size between 3 and 9\n"

exit -1

};;

t ) target="$OPTARG" # установка целевого числа

printf "obase=2;$target\n" | bc | grep -e '^1[^1]*$' # проверка что это степень двойки

let $? && {

printf "Invalid target, has to be power of two\n"

exit -1

};;

h ) help $0 # показать справку

exit 0;;

l ) exec 3>$OPTARG;; # включить логирование в файл

\?) printf "Invalid option: -"$opt", try $0 -h\n" >&2

exit 1;;

: ) printf "Option -"$opt" requires an argument, try $0 -h\n" >&2

exit 1;;

esac

done

# Инициализация игрового поля

let fields_total=board_size*board_size # общее количество ячеек

let index_max=board_size-1 # максимальный индекс

for i in $(_seq 0 $fields_total); do board[$i]="0"; done # заполняем нулями

let pieces=0 # обнуляем счетчик плиток

generate_piece # генерируем первую плитку

first_round=$last_added # запоминаем позицию первой плитки

generate_piece # генерируем вторую плитку

# Главный игровой цикл

while true; do

print_board # отрисовываем поле

key_react # обрабатываем ввод

let change && generate_piece # если было изменение - генерируем новую плитку

first_round=-1 # сбрасываем флаг первого раунда

let pieces==fields_total && { # если поле заполнено

check_moves # проверяем возможные ходы

let moves==0 && end_game 0 # если ходов нет - завершаем игру

}

done

ВЫВОДЫ

В результате выполнения работы изучены основы bash: переменные, циклы, ввод/вывод, реализована программа-игра 2048, получен навык написания и запуска bash-скриптов в Astra Linux.

18

Соседние файлы в предмете Безопасность Astra Linux