Модуль F#
Eraser предназначен для формирования из одиночных символов фигуры прямоугольника. Координаты каждого символа в пределах консольного окна хранятся в полях записи
Coordinates. Ключевое слово
mutable перед именами полей определяет поля записи как переменные, у таких полей можно изменять значения оператором <-. Изменяемые поля необходимы для изменения хранимых координат при перемещении символов.
type Coordinates = { mutable row: int; mutable col: int }
// Пример изменения координат:
let pos: Coordinates = { row = 0; col = 0 } // создание экземпляра записи
// Присвоение полям новых координат.
pos.row <- 12
pos.col <- 5
Прямоугольник из символов создаётся классом Rectangle. Конструктор класса принимает два параметра: число строк и столбцов. Эти размерности используются в классе для создания двумерного массива arrayPos. Двумерный массив для элементов типа Coordinates хранит координаты каждого символа в группе. В классе Rectangle имеется открытый метод Move direction для передвижения фигуры из символов на один шаг в указанном направлении.
Стирание символа основывается на печатании пробела по координатам символа. Алгоритм передвижения состоит из чередования циклов стирания части символов и рисования их по новым координатам:
- - при вертикальных перемещениях стираются верхний или нижний ряд символов, затем изменяются на единицу координаты строк, далее рисуются символы в новом расположении по вертикали;
- - при горизонтальных перемещениях стираются первый или последний столбец символов, затем изменяются на единицу координаты столбов, далее рисуются символы в новом расположении по горизонтали.
Rectangle умеет передвигать символы только на один шаг. Свойства класса Pos, Right, Left, Top, Bottom выдают информацию о координатах символов, и также крайних рядов и столбцов для вычисления касания помех и целей. Создание непрерывной анимации не входит в функции класса.
type Rectangle(numrows: int, numbercols: int) =
// Одиночный символ группы.
let symbol = "●"
// Координаты символов по рядам и столбцам.
let arrayPos: Coordinates[,]=
Array2D.create numrows numbercols { row = 0; col = 0 }
// Установка позиция курсора для рисования символа
// в любом месте консольного окна.
let cursorpos pos =
Console.CursorLeft <- pos.col
Console.CursorTop <- pos.row
// Рисование символа в данной координате.
let drawsymbols pos =
cursorpos pos
printf "%s" symbol
// Стирание символа в данной координате.
let erasesymbols pos =
cursorpos pos
printf "%s" " "
// Стирание необходимых рядов и столбцов.
let erase direction =
match direction with
| 1 -> // erase right
for i = 0 to numrows - 1 do
let leftcol = arrayPos.[i, 0]
erasesymbols leftcol
| 2 -> // erase left
for i = 0 to numrows - 1 do
let rightcol = arrayPos.[i, numbercols - 1]
erasesymbols rightcol
| 3 -> // erase down
for i = 0 to numbercols - 1 do
let toprow = arrayPos.[0, i]
erasesymbols toprow
| 4 -> // erase up
for i = 0 to numbercols - 1 do
let bottomcol = arrayPos.[numrows - 1, i]
erasesymbols bottomcol
| _ -> ()
let lastIndex dimension = arrayPos.GetLength(dimension) - 1
// Инициализация прямоугольника символов.
do
for row = 0 to numrows - 1 do
for col = 0 to numbercols - 1 do
arrayPos.[row, col] <- { row = row; col = col }
drawsymbols arrayPos.[row, col]
// Получение координат прямоугольника.
member x.Pos = arrayPos
// Одномерные массивы крайних символов для каждой стороны.
// Крайние ряды и столбцы для проверки касания.
member x.Right = arrayPos[*, lastIndex(1)]
member x.Left = arrayPos[*, 0]
member x.Top = arrayPos[0, *]
member x.Bottom = arrayPos[lastIndex(0), *]
// Передвижение на один шаг в указанном направлении.
member x.Move direction =
let mutable x = 0
let mutable y = 0
// Определитель направления движения.
match direction with
// направо
| 1 when arrayPos.[0, lastIndex (1)].col < (Console.WindowWidth - 1) -> x <- 1
// налево
| 2 when arrayPos.[0, 0].col > 0 -> x <- -1
// вниз
| 3 when arrayPos.[lastIndex (0), 0].row < Console.WindowHeight -> y <- 1
// вверх
| 4 when arrayPos.[0, 0].row > 0 -> y <- -1
| _ -> ()
// Передвижение только если выбрано реальное направление.
if x <> 0 || y <> 0 then
erase direction
// Каждый символ передвигаем на шаг в указанном направлении.
// Функция iter применяется к каждому элементу массива.
arrayPos
|> Array2D.iter
(fun pos ->
pos.col <- pos.col + x
pos.row <- pos.row + y
drawsymbols pos)