CustomGames.ru - Dota 2 пользовательские игры

Программирование для чайников

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Для кого эта статья
Статья рассчитана на людей, далеких от программирования, но желающий хоть как-то к нему приблизится.
Все определения не являются "официальными", это лишь мысли и рассуждения в слух автора, то есть меня, направленные на максимальную прозрачность повествуемой сути дела. По сути, это статья для лентяев, которые не могут посадить себя за серьезную литературу по данному вопросу.
Затрагиваться в ней будет парочка основ. Язык программирования непосредственно lua с workshop уклоном.
В статье будет применяться слово "объект", но оно не имеет никакого отношения к ООП и является просто удобным словом. lua не объектно-ориентированный язык, хоть и наделен некоторыми его механизмами. 

Об авторе:
В школе изучал pascal, delphi.
Отучился в Питере в СПБГЭТУ (ЛЭТИ) 6 лет. Диплом бакалавра "техники и технологии", диплом магистра "техники и технологии". В универе в графе "программирование" стояло изначально 3, потом уже 4. Языки программирования основные - C++, java, остальные перечислять не вижу смысла (много всяких нам показывали, включая assembler). Отработал два года в геоинформационной канторе, потом надоело. Сейчас отдыхаю.
Нет, все это не для того, чтобы "похвастаться" или еще чего (любой студент поймет, что тут и хвастаться нечем). Я вообще во многом разочарован, что касается именно моего образования (может и системы в целом) и считаю себя троишником (хоть дипломы на 5 и 4, все студенты знают, что эти оценки вообще ни о чем не говорят). Все это лишь для понимания вами планки, уровня далее повествуемого материала и его, так сказать, подложки. Естественно, если хотите заняться программированием всерьез, то идите читайте серьезную литературу. Остальным же хватит и ниже сказанного.

Предисловие
Что такое программирование? Это придумывание логических цепочек, алгоритмов, с целью перейти из состояния А в состояние Б. Например, вы находитесь в состоянии А - голода, и хотели бы попасть в состояние Б - сытости. Что вам для этого надо? Для этого нам нужно состояние В - употребление еды. Мгм, то есть путь к Б на самом деле не прямой, а через состояние В.  А что нам надо для того, чтобы попасть в состояние В? Ну естественно, приготовить еду - состояние Г. И так далее.

Казалось бы, простой вопрос, простое действие, однако если вникнуть, то оказывается, что все гораздо сложнее, чем кажется. Просто невероятное количество "мелочных", "посредственных" дел уже вошло нам в привычку. Дошло до такого автоматизма, что мы над этим не задумываемся. Однако когда вы занимаетесь программированием, вам необходимо над этим задумываться.  Вам необходимо представлять себе настолько детальную цепочку действий, насколько это необходимо вашему уровню абстракции в разбираемом вами вопросе.

Но, придумыванием логических цепочек дело не ограничивается, ведь тогда почти каждого человека можно было бы назвать программистом. В глубинном смысле этого слова да, так и есть, однако в общепринятом уровне абстракции этого определения (вот вам и пример с разными уровнями абстракции) программисты составляют эти цепочки на машинных языках. Сами же эти языки взялись из неоткуда, когда человечество переживало эпоху ренессанса, и Джон Коннор родился на свет. Шучу, конечно же эти языки придумали люди для облегчения себе жизни. Почему облегчению? Это не тема данной статьи, поэтому перейдем обратно к делу.

Таким образом программист, используя синтаксис машинного языка, описывает придуманные им логические цепочки машине, что он программирует. Это даже можно назвать "проецированием своего разума" на механизм. А само проецирование осуществляется
в среде программирования.

- Среда программирования, что это?
- Это программа, что считывает написанные вами стихи на машинном языке и объясняет их самой машине. 
- Но как, разве машине нужно объяснять её же язык?
- Да, блеать, потому что "машинные языки" придуманы людьми для людей как посредники между специализированными программами
и гномом Компилятором, что сидит у вас в микросхеме процессора и знает настоящий машинный язык - Ассемблер.

Это все, конечно, шутки и дела обстоят намного глубже, но, думаю, суть вы уловили.

Так что вам нужно вынести из всего этого предисловия?
То, что мы, программисты, занимаемся описанием своего поведения в той или иной ситуации,
используя чернила машинного языка, логическое перо и среду программирования в качестве бумаги.

Мгм, поэты, что пишут машинные стихи, боже, что я несу...



Lua в workshope

Итак. Как уже можно было догадаться, в программировании требуется доскональность, конкретика.
Но конкретика не в привычном понимании этого слова. Здесь конкретику мешают с универсальностью. Сейчас все поймете. Однако прежде необходимо определить три величины из предисловия:

Машинный язык - lua
Логическое перо - ваш разум, ваши логические цепочки
Бумага, среда программирования - workshop, но по сути любой текстовый редактор.

И, хоть workshop и является нашим компилятором, что производит сборку наших набросков в выполняемую программу, он не предоставляет интерфейс, холст для письма. Ну как не предоставляет - в чистом виде его нет. Вместо этого нам говорят: "вот вам главный листочек в виде файла .lua  и именем addon_game_mode. Ну и его можно дополнять своими листочками."
То есть среды программирования в привычном понимании этой пары слов - как некого редактора с подсветкой синтаксиса, пошаговой компиляции, дебагером и т.д. нет. Поэтому мы используем сторонние утилиты в духе Notepad++, Sublime, что позволяют хотя бы подсветить синтаксис языка lua.

Так, разобрались с ролями, теперь что касается самого языка. Что я подразумевал под универсальностью:
вспомним школьный курс математики. Как решаются все задачки, уравнения? Через универсальный подход - использования переменных. Вы, как бы, не знаете того, что ищите, но вам надо это как-то обозначить, конкретизировать. И вы прибегаете к обозначениям - буковкам, переменным.
Так и в программировании - у вас нет конкретики, но её нужно добиться. И добиваемся мы её универсальностью.

Например: мы хотим сложить два числа. Из состояния с наличием некоторых двух чисел хотим перейти в состояние наличия одного, третьего числа.
Для начала надо определить эти два числа, конкретизировать их. В lua это делают следующим способом:
Указывают тип переменной, вам достаточно знать лишь один - локальный (local), в пределах рассматриваемого блока кода. И имя переменной - любой допустимый синтаксисом символ
или последовательность символов. Но, имя переменной не должно начинаться с цифры.
Таким образом у нас есть:

local a - некая локальная переменная "а", которая олицетворяет наше первое число
local b - некая локальная переменная "б", которая олицетворяет другое число

Однако, сейчас мы лишь имеем обертки конфет, но не имеем самих конфет. Нам необходимо конкретизировать эти переменные, приравнять их к чему-то. Наполнить.

Делается это через оператор "=" - функция, что копирует текущее состояние объекта и делает из него новый объект.
Иными словами это клонирование. И, если вы делаете так: Объект 1 = Объекту 2. А затем делаете Объект 2 = Объекту 3, то Объект 1 не будет равен Объекту 3. Объект 1 - это новый объект, что является клоном Объекта 2 на момент его клонирования. Но не на последующие моменты.

Итак, определим наши переменные. Пусть:

Код
local a = 33
local b = 9

Это наше первое состояние. Далее нам необходимо перейти к состоянию "суммы". Как это сделать? Через состояние "сложения". А для состояния сложения нам нужен оператор сложения - "+" - функция, что позволяет сложить два числа. Уже не объекта, а именно числа (ну где-то и объекты, но не это не наш текущий уровень).
Соответственно, если в качестве наших объектов будут выступать не числа, то при использовании оператора сложения вы получите ошибку. Вот наше состояние сложения:

Код
a + b

Для состояния "суммы" нам необходимо определить еще одну обертку для конфеты, что мы получим после сложения.
И выглядит наше состояние суммы так:

Код
local c = a + b

Вот и все. Весь код сложения двух переменных выглядит вот так:

Код
local a = 33
local b = 9
local c = a + b

Поздравляю. Вы написали свой первый осмысленный код на lua (ну может и не первый).
"с" у нас будет в итоге равно 42. Однако, можно исхитриться, и обойтись без переменной "с":

Код
local a = 33
local b = 9
b = a + b

или

Код
local a = 33
local b = 9
a = a + b

Все зависит от того, нужна ли вам эта новая переменная "с" в вашем случае, или нет.

Теперь после такого осмысленного примеры я могу вам сказать то, что вы сможете понять.

На этом сайте расположены не иначе как "операторы". Но они не в привычном вам виде значков + и -.
Это немного иные операторы, которые так же носят имена "функций" и "методов".
Просто значки называют операторами, а эти штуки функциями и методами.
Да, с ними надо иначе работать, но теперь вы их не будете бояться. Они так же берут одни объекты и дают вам другие.

Как же работать с этими функциями? Чтобы ответить на этот вопрос, напишем свою функцию. Определяют функции так:

Код
function MyFunc(a,b)

end


function - ну, указатель, что у нас именно функция. По сути это тот же тип переменной MyFunc.
MyFunc - имя функции, имя переменной.
end - указатель конца функции.
Все, что идет после строчки с указателем "function" и до строчки с указателем "end" - тело нашей функции.
В скобочках указывают через запятую те объекты, переменные, которыми мы будем оперировать в теле функции.
То есть то, что нам поставляют. Мы можем ими даже не пользоваться. Тогда мы просто оставляем скобочки пустыми.
Например так:

Код
function MyFunc()

end

Здесь наша функция делает свои дела, не используя при этом какие-либо переменные извне.

Итак, для начала реализуем самую простую функцию

Код
function MyFuncHW()
   print("Hello World")
end

функция print() - отправляет на отрисовку в консоль то, что вы в ней укажите.
Если хотите просто строчку, то пишите её в кавычках. Если хотите содержимое переменной, объекта, то кладете в неё этот объект, без кавычек.

В нашем случае мы кладем в неё строчку Hello World.
В итоге наша функция MyFuncHW() используя функцию print() пишет в консоль строчку Hello World.

Начинаете ощущать понимание работы функций? Да/нет - не важно, мы все равно идем к следующему примеру.

Я хочу создать свою функцию сложения двух чисел. И да, она будет невероятно глупая, но зато вы поймете принцип работы функций. Вот как будет выглядеть код:

Код
function MyFuncSum(a,b)
   local c = a + b
   return c
end

Вау, новый оператор return, что он делает? Он позволяет использовать нашу функцию как объект в операторах "=" и т.д.. То есть мы с его помощью можем написать где-то в коде вот так:

Код
g = MyFuncSum(10,15)

Функции пишут как с ним, так и без него.
Например наша функция  MyFuncHW() написана без него и мы в итоге при таком её употреблении:
g = MyFuncHW() - получим ошибку.
Как вы могли догадаться, оператор return обеспечивает обратную связь. Но она не всегда нужна. В нашей функции MyFuncHW() она не нужна.

Разберем поподробнее строчку
 
Код
local c = a + b

Ибо это наглядно демонстрирует работу с типом данных.
То, что переменная "с" указана в теле функции как local, говорит о том, что она существует только в теле функции. Вызвать эту переменную вне тела функции у вас не выйдет.
Умники скажут - но мы же посылаем её "назад в будущее" через оператор return! Нет, мы посылаем не перемнную, мы посылаем её начинку. Переменные - это всего лишь обертки конфет.

Теперь, когда мы более менее поняли, что же значит local, мы обойдемся в нашем примере без переменной "с":

Код
function MyFuncSum(a,b)
   return a + b
end

Да, так можно делать, потому что оператор return по сути тот же оператор "=", только немного иначе реализован.
Он как бы говорит: "вот то, что справа будет равно тому, что слева, но я фиг не знаю, что там слева, однако знаю, что у меня справа".
Иначе говоря, в строчке

Код
g = MyFuncSum(10,15)

оператор return, что спрятан в функции MyFuncSum(10,15) выступает в роли розетки для вилки "=" извне.

Что ж, теперь в коде мы можем использовать вместо "+" нашу глупую функцию MyFuncSum(a,b). Почему глупую?
Потому что мы вместо простого использования уже готового оператора "+" используем функцию, что использует этот самый оператор "+". То есть мы ничего нового и упрощающего нашу жизнь не сделали.
Мы просто взяли чужое одеяло, надели на него свой пододеяльник и говорим, что это наше одеяло. Пример тоже глупый, но ничего умнее голову сейчас не приходит. Но, повторюсь, мы делали этот пример не для чего-то "умного", мы это делали для того, чтобы понять принцип работы функций.
Например, мне вот нужно будет постоянно в коде из суммы двух чисел вычитать семерку.
Вот раз пять надо будет это делать. А такого оператора нет. И тут наша функция станет полезной, стоит её только чутка подкорректировать:

Код
function MyFuncSum(a,b)
   return a + b - 7
end

И все. Да, мы можем в коде каждый раз писать "a + b - 7", а можем каждый раз писать MyFuncSum(a,b).
Не особо заметна разница, однако если вместо "a + b - 7" нам нужно будет считать определенный интеграл на отрезке (а,б) или какую-нибудь сложную функцию, то вы ощутите разницу.

Что ж, пожалуй, на сегодня на этом закончим (че-то я  устал).
Поясню лишь еще вот какие моменты:

API workshopa - это не встроенные в lua функции, это функции, что реализованы разработчиками дотки на том же языке lua.
У них так же есть тело, но оно от нас скрыто и нафиг нам не сдалось. Эти функции реализованы как раз таки для того, чтобы упростить нам жизнь.
Чтобы нам не приходилось каждый раз решать интеграл в ручную, а просто взять функцию, что его считает и запустить её.

void CancelEntityIOEvents(ehandle ehandle_1) - какая-то функция из API workshopa. Взял её для примера.

void - позиция возвращаемой величины, переменной, то, что нам передает return. В нашем случае этой void - пустота, т.е. в этой функции returna нет и она как наша MyFuncHW().
CancelEntityIOEvents - имя функции
(ehandle ehandle_1) - переменная и её тип. То есть, чтобы эта функция отработала правильно, в неё необходимо поместить какую-то переменную с обязательным типом ehandle.
Иначе мы получим ошибку. Например, если передадим в неё какое-нибудь число. Скажем так:

Код
CancelEntityIOEvents(45) 

или

Код
local a = 45
CancelEntityIOEvents(a)

В обоих случаях получим ошибку.

Но если так

Код
...
local a = b.GetEntityHandle()
CancelEntityIOEvents(a)

Где переменная "b" - это какой-то объект типа CBaseEntity либо типа CEntityInstance, то ошибки не будет, ведь функция GetEntityHandle() возвращает как раз таки переменную типа "ehandle".


Послесловие

Далее советую сначала прочитать вот этот пост, далее читать эту, затем эту и вот эту статейки. Так же разобраться, что из себя представляют операторы "for" и "if else".  И почитываем о Lua.




« Последнее редактирование: 03-09-2016, 12:05:53 от Илья »

Оффлайн Илья

  • Супермодератор
  • 1904
  • Мощь: 16
Re: Программирование для чайников
« Ответ #1 : 16-07-2016, 14:18:50 »
Exotic, мне тут слово "употребабушкася" (употре-б-л-я-т-ь-с-я) коверкает твой анализатор текста  :-X

Оффлайн -ErøtiC-

  • Администратор
  • 335
  • Мощь: 3
  • Забанен
Re: Программирование для чайников
« Ответ #2 : 17-07-2016, 02:37:53 »
Илья, это фильтр от мата, попозже посмотрю как можно сделать только для целых слов.
UPD: употребляться.