编译型语言:代码在运行前需要使用编译器,先将程序源代码编译为可执行文件,再执行
C/C++ Java C# Go Objective-C
解释型语言(脚本语言)
需要提前安装编译语言解析器,运行时使用解析器执行代码
JavaScript Phthon PHP SQL Lua
特点:运行才能调试,运行速度稍慢,开发速度快
一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放,其设计目的为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能
Lua特点
轻量级,可扩展
游戏行业
- 魔兽世界客户端,大话西游2等知名网游中有Lua的身影
- 现代众多热更新手游也常用Lua写游戏逻辑,便于做热更新
- Lua在skynet等现代网络游戏框架中有广泛应用
需要高性能的程序部分,使用c/c++实现。需要快速实现功能部分,使用Lua实现
Unity3D:使用如xLua插件(API的Lua调用),实现游戏核心代码使用C#实现(打包时il2cpp,编译为c++),游戏逻辑使用Lua开发(王者荣耀)
Lua寄宿性的,寄在宿主语言下的一种语言
注释
Lua的单行注释--
Lua的多行注释—[[多行注释]]
定义变量
name="hxsd"--Lua会自动推到类型变量
print(name)
输出:hxsd
--内置变量
--特点:下划线加大写字母
print(_VERSION) --查看Lua的版本
输出:Lua 5.4
--可以调用一个不存在的变量,值是nil,等同于C#中的null
print(id)
输出:nil
--销毁一个已经定义的变量
name=nil
--全局变量和局部变量
name1="abc"--全局
local name2="def"--局部
--一般开发中,轻易不会使用全局变量
local name="Unity"
--获得变量类型,使用type()
print(type(name))
输出:string
--获得type()返回值的类型
print(type(type(name)))
输出:string
--对于一个没有定义的变量获取类型
print(type(bb))
输出:nil
--判断一个未定义的变量
print(type(bb)=="nil")
输出:true
print(type(12))
输出:number
print(type(12.3))
输出:number
print(type(true))
输出:boolean
--type是函数结构,是一个代码片段,可以重复调用执行,有参数有返回值
--字符串操作
--单行定义字符串
local str1="abc"
local str2="def"
--多行定义字符串
--完全的还原字符串内部的定义结构,和换行符都是存储的
local str3=[[
one
two
]]
print(str3)
--Lua字符串拼接
print(str1..str2)
输出:abcdef
--Lua对两个字符串相加时,会将它们转换为数字类型,转换失败会报错,如果转换成功,则进行加运算后,得到数字结果
print("1"+"2")
输出:3
--获取字符串长度
print(#str1)
输出:3
--string.函数名()
--字符串大写化
print(string.upper(str1))
输出:ABC
--字符串小写化
print(string.lower(str1))
输出:abc
--Lua支持多返回值
--Lua字符串的下标是从1开始的
--字符串查找
--(参数1:被查找的字符串,参数2:查找的内容,返回值:起始找到的位置下标和结束找到的位置下标)
print(string.find("abcdefg","cde"))
输出:3 5
--字符串反转
print(string.reverse("abcdefg"))
输出:gfedcba
--截取字符串
--方式一(提供起始位置下标,截取到结尾)
print(string.sub("abcdefg",3))
输出:cdefg
--方式二(提供起始位置下标,提供结束位置下标)
print(string.sub("abcdefg",3,6))
输出:cdef
--截取到倒数第二个字符
local data="abcdefghijklmn"
print(string.sub(data,3,#data-1))
输出:cdefghijklm
--字符串格式化
--参数一:需要被格式化的字符串,其中包含占位符,%d表示数字;参数二:填入格式化字符串中的内容
print(string.formar(" Im the %d player,other is %d",1,2))
输出:Im the 1 player,other is 2
--字符串重复
print(string.rep("abc",2))
输出:abcabc
--ASCI码转字符串
print(string.char(65))
输出:A
--字符串转ASCI码
print(string.byte("A"))
输出:65
--字符串替换
--参数一:原始字符串;参数二:需要替换的内容;参数三:替换后的内容
--返回值:替换结果,替换次数
print(string.gsub("abcd","bc","**"))
输出:a**d
local data={}
--起始索引是1开始
--类型可以混合
--索引值可以为负数
--即使索引从1开始,也可以赋值0索引
--索引可以断开
--初始化时,对于没有索引的值,索引是从1向上累加的
--初始化提供索引的赋值方法,[索引值]=数值
data={"abc",123,[-1]=100,[0]=99,[5]=233}
print(data[1])
输出:abc
print(data[2])
输出:123
print(data[-1])
输出:100
print(data[0])
输出:99
print(data[5])
输出:233
--获取数组长度
--这种方式,获得的是从1索引开始,索引连续的数据个数,中间断开,计数结束
--这种方式不稳定
print(#data)
输出:a**d
--修改某一个值
data[1]="def"
print(data[1])
输出:def
local data2={{"aa","bb"},{11,22}}
print(data2[2][1])
输出:11
--数组在Lua中是用Table实现的
--2的3次方
print(2^3)
输出:8.0
--C#不等于 !=;Lua中 ~=
print(2~=3)
输出:true
--Lua没有++ --
local i=0;
i=i+1;
--Lua没有+=、-=、*=
local conl=true
if(conl)
then
print("条件1达成")
end
输出:条件1达成
if(false)
then
print("条件1达成")
else
print("else达成")
end
输出:else达成
if(false)
then
print("条件1达成")
elseif(true)
then
print("else if达成")
else
print("else达成")
end
输出:else if达成
if(true)
then
if(true)
then
print("进入第二层if")
end
end
输出:进入第二层if
--Lua没有swith,所以可以使用if-else if-else的结构代替
local num=1
while(num<3)--当满足条件时,进入循环
do
print(num)
num=num+1
end
--local修饰的num,虽然是局部变量,但是作用域为当前文件,所以在循环体内,可以取得值
输出:
1
2
local num=1
repeat
print(num)
num=num+1
until (num>5)--直到条件满足时,跳出循环
输出:
1
2
3
4
5
local data={"aa","bb","cc","dd","ee"}
--参数1:变量i的初始值,遍历lua表,使用
--参数2:增长到多少
--参数3:增长步长,默认为1
for i=1,#data,2
do
print(data[i])
end
输出:
aa
cc
ee
--倒序遍历
for i=#data,1,-1
do
print(data[i])
end
输出:
ee
dd
cc
bb
aa
local data={one="cc","aa","bb",[3]=3,[-1]=4,["two"]="dd"}
--[[
one是不加中括号的字符串索引,"aa”"bb""自动加1,2索引
[4]指定数字索引[-1]指定负数索引
["two"]是加中括号的字符串索引写法
]]
--连续索引数值迭代器
for k,v in ipairs(data)
do
print("k:"..k..",v:"..v)
end
输出:
k:1,v:aa
k:2,v:bb
k:3,v:3
--[[
迭代器就是指向table的指针
连续数字索引迭代器,只会获取从1开始的数字索引,
且必须索引是连续的才能持续获得值
此处的for结构,可以理解为C#的foreach结构
]]
--所有数值迭代器
for k,v in pairs(data)
do
print("k:"..k..",v:"..v)
end
输出:
k:1,v:aa
k:2,v:bb
k:one,v:cc
k:-1,v:4
k:two,v:dd
k:3,v:3
--脚本型语言都是从上往下依次执行的
--先定义再调用
--第一种声明函数
function func1()
print("这是func1")
end
func1()--先定义再调用,没有问题
输出:
这是func1
__________________________________________________
--将函数定义为一个变量,函数是一种数据类型
local func2=function ()
print("这是func2")
end
func2()
输出:
这是func2
_________________________________________________
local func3=function (a,b)
print(a+b)
end
--函数的调用,参数可以多余形参,但不能少于形参
func3(5,7)
func3(5,7,9)
输出:
12
12
__________________________________________
local func4=function (...)
--将无固定参数,转换为table
--arg的作用域是func4函数体
local arg={...}
local total=0
for k,v in pairs(arg)
do
total=total+v
end
print(total)
end
func4(1,2,3)
func4(1,2,3,4,5)
输出:
6
15
__________________________________________
function func5()
return 99,100
end
--将多返回值,同时赋值给两个变量
local num1,num2=func5()
print(num1)
print(num2)
输出:
99
100
--Table支持数字索引存储数据
--支持字符串索引(关联索引)存储数据
local data={one="cc","aa","bb",[4]=3,[-1]=4,["two"]="dd"}
print(data[2])
print(data["one"])
print(data.two)
输出:
bb
cc
dd
--因为函数是一种数据类型
--所以将func1索引下定义了一个函数
data.func1=function ()
print("data表中的func1函数")
end
--所以data.func1调用数据,是个函数,也就调用了函数
data.func1()
输出:
data表中的func1函数
________________________________________________
data.func2=function ()
print(data.two)
end
data.func2()
输出:
dd
--第一种self调用写法
--[[
成员函数定义时,显式加入self变量,对应C#的this关键字
函数内部可以通过self变量获取当前table的其他值或函数
]]
data.func3=function (self)
print(self.two)
end
--调用时,必须使用“:”,因为":"调用,会对self关键字赋值
data:func3()
输出:
dd
_____________________________________________
--第二种self调用写法
--隐式给self赋值
function data:func4()
print("func4:"..self.two)
end
data:func4()
输出:
func4:dd
_____________________________________________
--思路:所有数组迭代器,在for循环里作基数
function table_count(t)
local count=0
for k,v in pairs(t)
do
count=count+1
end
return count
end
local data={one="cc","aa","bb",[4]=3,[-1]=4}
print(table_count(data))
输出:5
function maopao(...)
local nums={...}
for i=1,#nums
do
for j=1,#nums-1
do
if(nums[j]>nums[j+1])
then
local tmp=nums[j]
nums[j]=nums[j+1]
nums[j+1]=tmp
end
end
end
return nums
end
local t=maopao(7,1,23,8)
print(t[1])
print(t[2])
print(t[3])
print(t[4])
输出:
1
7
8
23