Ввод данных
До этого момента все данные в программах были жёстко заданы в коде: числа, строки, условия. Но настоящая программа должна общаться с пользователем — спрашивать имя, принимать команды, получать настройки.
Для этого в Lua есть функция read().
Базовое использование
read() ждёт пока пользователь введёт строку и нажмёт Enter. Возвращает введённый текст как строку:
print("Как тебя зовут?")
local name = read()
print("Привет, " .. name .. "!")
Программа замирает на read() и ничего не делает, пока пользователь не нажмёт Enter. Это не баг — так и задумано.
Ввод числа
read() всегда возвращает строку. Если нужно число — конвертируй через tonumber():
print("Введи глубину шахты:")
local input = read()
local depth = tonumber(input)
if depth then
print("Копаем " .. depth .. " блоков")
else
print("Это не число!")
end
Повтор ввода при ошибке
Валидируй ввод в цикле — не останавливайся на первой попытке:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
local function readNumber(prompt, min, max)
while true do
print(prompt)
local input = read()
local n = tonumber(input)
if not n then
print("Ошибка: введи число")
elseif min and n < min then
print("Ошибка: минимум " .. min)
elseif max and n > max then
print("Ошибка: максимум " .. max)
else
return n
end
end
end
local depth = readNumber("Глубина (1-100):", 1, 100)
local width = readNumber("Ширина (1-16):", 1, 16)
print("Копаем " .. width .. "x" .. depth)
Скрытый ввод (пароль)
Второй параметр read() — символ маскировки. Всё что вводит пользователь заменяется этим символом на экране:
print("Введи пароль:")
local password = read("*")
if password == "secret123" then
print("Доступ разрешён")
else
print("Неверный пароль")
end
Ввод с вариантами по Tab (автодополнение)
read() поддерживает автодополнение — передай таблицу вариантов вторым аргументом (после маски):
local commands = {"start", "stop", "status", "help", "exit"}
print("Команда:")
local input = read(nil, commands)
print("Введено: " .. input)
Пользователь нажимает Tab — терминал подставляет подходящий вариант.
Интерактивное меню
Классический паттерн — меню выбора:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
local function showMenu()
print("╔══════════════════╗")
print("║ CONTROL PANEL ║")
print("╠══════════════════╣")
print("║ 1. Запустить ║")
print("║ 2. Остановить ║")
print("║ 3. Статус ║")
print("║ 4. Выход ║")
print("╚══════════════════╝")
print("Выбор:")
end
while true do
term.clear()
term.setCursorPos(1, 1)
showMenu()
local choice = read()
if choice == "1" then
print("Запускаем...")
sleep(1)
elseif choice == "2" then
print("Останавливаем...")
sleep(1)
elseif choice == "3" then
print("Статус: работает")
print("Топливо: " .. turtle.getFuelLevel())
sleep(2)
elseif choice == "4" then
print("До свидания!")
break
else
print("Неизвестная команда: " .. choice)
sleep(1)
end
end
REPL — цикл команд
Более гибкий подход — принимать команды как строки и разбирать их:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
local running = true
local handlers = {
help = function()
print("Команды: help, status, go N, stop, exit")
end,
status = function()
print("Топливо: " .. turtle.getFuelLevel())
print("Слоты: " .. getFreeSlots() .. " свободно")
end,
exit = function()
running = false
end,
}
print("Введи 'help' для списка команд")
while running do
io.write("> ")
local line = read()
-- Разбить на команду и аргументы
local cmd, args = line:match("^(%S+)%s*(.*)")
if not cmd then
-- пустая строка
elseif handlers[cmd] then
handlers[cmd](args)
elseif cmd == "go" then
local n = tonumber(args) or 1
for i = 1, n do turtle.forward() end
print("Сделано " .. n .. " шагов")
else
print("Неизвестная команда: " .. cmd)
end
end
Ввод да/нет
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local function confirm(question)
while true do
print(question .. " (y/n)")
local input = read():lower()
if input == "y" or input == "yes" or input == "да" then
return true
elseif input == "n" or input == "no" or input == "нет" then
return false
else
print("Введи y или n")
end
end
end
if confirm("Начать добычу?") then
startMining()
else
print("Отменено")
end
Конфигуратор при первом запуске
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
local config = {}
local function setup()
print("=== Первый запуск — настройка ===")
print("Имя робота:")
config.name = read()
config.depth = readNumber("Глубина шахты (1-100):", 1, 100)
config.width = readNumber("Ширина шахты (1-9):", 1, 9)
if confirm("Выбрасывать мусор (булыжник, гравий)?") then
config.dropTrash = true
end
print("Настройка завершена!")
print("Робот: " .. config.name)
print("Шахта: " .. config.width .. "x" .. config.depth)
end
setup()
🚀 Задания
Задание 1
Напиши программу-калькулятор: просит ввести два числа и знак операции (+, -, *, /). Выводит результат. Обрабатывает деление на ноль и нечисловой ввод.
Задание 2
Напиши программу-угадайку: загадай число от 1 до 100 через math.random. Читай числа от пользователя через read(), подсказывай "больше" или "меньше". Считай попытки.
Задание 3
Создай интерактивное меню управления черепашкой: вперёд (w), назад (s), влево (a), вправо (d), вверх (q), вниз (e), стоп (stop). Каждая команда — один шаг в нужном направлении.
Задание 4
Напиши функцию readNumber(prompt, min, max) из примера выше. Добавь поддержку "exit" — если пользователь введёт это слово вместо числа, функция возвращает nil.
Задание 5
Напиши систему паролей с тремя попытками. После трёх неверных попыток — вывести "Аккаунт заблокирован" и завершить программу через os.shutdown(). При верном пароле — вывести приветствие с именем пользователя (спросить после успешного входа).