урок 1
Совсем скоро мы начнем с вами писать свою игру в roblox. В нем все программирование будет на языке Luau - диалекте Lua с постепенной типизацией. Поэтому сегондя наша задача - вспомнить как вообще в lua писать. Откроем онлайн инетрпертатор, например https://play.luau.org/
Именная конвенция
Поскольку очень часто люди пишут один проект вместе, есть определенные договоренности. В том числе они зависят от языка. В роблоке принято писать :
переменные, функции классовые поля - camelCase
константы - LOUD_SNAKE_CASE
API роблокса, названия классов и энумераторов - PascalCase
Переменные
В luau есть следующие типы переменных:
- nil - неуказаное значение, единственное, приводящееся к false (0 ~=false)
- boolean ∊ {true;false}
- number == float
- string - строка текста произвольной длины
- function - ссылка на функцию
- table - ассоциативный массив (помесь list и dict)
Называть переменные можно любыми названиями, кроме начинающихся с цифр и зарезервированных слов.
Есть возможность параллельного присваивания
local x, y = 90, 'fff' -- x= 90, y = 'fff' x, y = y, x -- x= 'fff', y = 90
Области видимости
По умолчанию у пременной область видимости - global.
Пожалуйста, делайте их локальными и const, если это применимо. Luau гораздо быстрее работает с локальными переменными.
local isGameActive = true -- boolean
local playerScore = 150 -- number
local playerName = "Alex" -- string
local randomArray = { 8, "a19", nil, false, {true, isGameActive} } -- table with assumed index of 1,2,3...
local playerStats = { -- table with custom index
health = 100,
mana = 50
}
Арифметические операции
помимо базовых +-*/ есть:
% - остаток от деления
^ - степень
IF
if <условие> then
<действия>
else
<действия2>
end
Чуть больше о массивах
массивы нумеруются с 1. Соответвенно индекс последнего элемента - мощность множества +1
Чтобы найти мощность (длину) массива , испольуется #name
local randomArray = { 8, "a19", nil, false, {true, 1} }
print(#randomArray) -- выведется 5
Для индексации внутри массива используется []
local randomArray = { 8, "a19", nil, false, {true, 1} }
print( randomArray[2] )
-- вывод 'a19'
Чтобы добавить значение в массив:
local randomArray = { 8, "a19", nil, false, {true, 1} }
randomArray[ #randomArray+1 ] = 'это последнее значение'
table.insert(randomArray , 2 , 'хаха я вставил это во вторую позицию')
-- randomArray == {
["1"] = 8,
["2"] = "хаха я вставил это во вторую позицию",
["3"] = "a19",
["5"] = false,
["6"] = {true,1},
["7"] = "это последнее значение",
}
Учтите, что поскольку для Lua таблица - просто словарь, то сохранять значение nil она не будет, просто пропустив его.
local randomArray = { 8, "a19", nil, false, {true, 1} }
randomArray == {1 = 8,
2 = 'a19',
--третьего индекса просто нет, поскольку там nil
4 = false,
5 = { 1 = true , 2 = 1}
}
Циклы for
Цикл for берет как рабочую переменную либо созданную,
for i = startValue , endValue , stepValue do
--действия
end
либо уже существующую таблицу, тогда на вход дается два значения index , value :
local randomArray = { 8, "a19", nil, false, {true, 1} }
for index , value in randomArray do
print(index , value)
end
--[[выведется
1 8
2 a19
4 false
5 { true, 1}
]]--
Принято неиспольлзуемую переменную называть _
local randomArray = { 8, "a19", nil, false, {true, 1} }
for _,v in randomArray do
print(v)
end
Чаще всего для перебора в словарях используется pairs(dict), а в списках - ipairs(array)
Итерацию цикла можно закончить досрочно с помощью continue, а из цикла целиком можно выйти с помощью break
Задача №1
Создать список всех чисел [1,100] , делящихся на 7
Можно сделать это двумя способами. Дайте ребятам время подумать и не наказывайте за использование чита в виде for:
способ #1 - трушный, через проверку каждого числа
local divBy7={}
for candidate = 1,100 do
if candidate %7 ==0 then
divBy7[#divBy7+1] = candidate
end
end
спобос #2 - читовый
local divBy7={}
for candidate = 7,100,7 do
divBy7[#divBy7+1] = candidate
end
Задача №2
Создать список всех простых чисел в промеждутке [2,100]
1 - не простое число (согласно Математическая энциклопедия (в 5 томах) и Arguments for and against the primality of 1
Пример решения (без какой либо оптимизации):
local primes = {}
for candidate = 2 , 100 do
local isPrime = true
for possibleDivisor = 2 , candidate-1 do
if candidate % possibleDivisor == 0 then
isPrime = false
break
end
end
if isPrime then
primes[#primes+1] = candidate
end
end
Можно довесить оптимизаций, обрезать верхний край проверки до половины числа, не проверять четные и тд
local primes = {2}
for candidate = 3 , 100, 2 do
local isPrime = true
for possibleDivisor = 2 , math.round(candidate/2) do
if candidate % possibleDivisor == 0 then
isPrime = false
break
end
end
if isPrime then
primes[#primes+1] = candidate
end
end
Функции
Для создания функции:
local function name( --[[inputVars]]-- )
--operations
опционально return <возвращаемое значение>
end
Например, функция, которая прибавляет к числу 1
local randomArray = { 8, "a19", nil, false, {true, 1} }
local
Задача №3
Занулить массив. Массив дан. После результата работы функции все значения в нем должны быть 'ДАННЫЕ УДАЛЕНЫ'
Учтите, что при использовании цикла for, как и всегда, передается копия массива,а не он сам. Для изменения массива используйте индексацию в него
-- не сработает
local randomArray = { 8, "a19", nil, false, {true, 1} }
local function delete( array )
for _,v in array do
v = 0
end
end
-- сработает
local randomArray = { 8, "a19", nil, false, {true, 1} }
local function delete( array )
for i,_ in array do
randomArray[i] = 0
end
end
Задача №4
Попробуем решить какоe-нибудь сложное уравнение простым подбором. Для этого определим сначала, с какой точностью ответ нам подойдет, т.е. погрешность.
Затем просто будем проверять числа, пока не найдем нужное.
Для примера, возьмите уравнение 2*n^3 + 6*n^2+7*n+2 = 0
Чтобы найти, насколько мы близки к ответу, берем модуль результата и сравниваем с допуском (привет, предел по Коши)
local function solver(range)
local answers = {}
for n = -1000 , 1000 , 0.0001 do
if math.abs(2*n^3 + 6*n^2+7*n+2)