复杂的数据类型

终于到了这个折磨人的地方了,这里也是最能表现lua的灵活性和不严谨性的地方

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
38
39
40
41
42
43
44
45

print("*********复杂数据类型 table************")
--所有额复杂类型都是table (表)


print("*********数组************")

a ={1,2,3,4,5,6,7,nil,"123"};


--lua中的索引从1开始
print(a[1]);

print(#a);

-- #是通用获取长度的关键字
-- 在打印长度的时候 空被忽略了//之前的版本

print("*********数组的遍历************")

for i = 1,#a do
print(a[i])
end

print("*********二位数组************")

a={ {1,2,3},{4,5,6} }

print(a[2][1] )

print("*********二位数组的遍历************")

for i = 1,#a do
b =a[i]
for j=1,#b do
print(b[j])
end
end


print("*********自定义索引************")

aa= {[0] =1,2,3,[-1]=4,5}
print(aa[0])

表的遍历

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
print("*******迭代器遍历******")
--迭代器遍历 主要是用来遍历表的
--#得到的长度 并不准确 一般不用#来遍历

a ={[0]=1 ,2,[-1] =3,4,5,[5]=6}

print("*******ipairs迭代器遍历******")
--ipairs
--ipairs遍历 还是从1开始往后后遍历 小于等于0的值得不到
--只能找到连续索引的键值 如果中间断序了 他也无法遍历出后面的内容
for i,k in ipairs(a) do
print("iparis遍历键值"..i.."_"..k)
end
print("*******pairs迭代器遍历******")

--谈能够把所有的键都找到 通过键可以得到值
for i,v in pairs(a) do
print("paris遍历键值"..i.."_"..v)
end
for i in pairs(a) do
print("paris遍历键值"..i.."_"..a[i])
end
print("*******pairs迭代器遍历键******")
for i in pairs(a) do
print("paris遍历键"..i)
end

更加复杂的数据类型

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

print("*********复杂数据类型---表2************")
print("*********字典************")

print("*********字典的声明************")
a = {["name"] = "我",["age" ] = 14,["1"] = 5}
--访问单个变量用中括号填键来访问
print(a["name"]);
print(a["1"]);
print(a.age)
--虽然可以通过全局变量的形式得到值 但是这个值不能是数字

a["name"] = "me"
print(a["name"])

--新增
a["sex"] = false

print(a.sex)
--删除

a.sex=nil
print(a.sex)



print("*********字典的遍历************")
--如果要模拟字典遍历一定要用pairs
for k,v in pairs(a) do
--可以传多个参数一样可以打印出来
print(k,v)
end


for k in pairs(a) do
print(k)
print(a[k])
end

print("*********类和结构体************")
--lua里面默认没有面相对象,需要自己来实现
--成员变量 成员函数......
Student =
{
--年龄
age =1,
--性别
sex = true,
--成长函数
Up =function ( )
--这样写 这个age和表中的age没有任何关系 他是一个全局的变量
print(age)
--想要在表内部函数中调用表本身的属性或方法
--一定要指定是谁的 所以要使用 表名.属性 或 表明.方法
print(Student.age)
print("我成长了")
-- body
end,
Learn =function(t)
--第二种能够在函数内部调用自己属性或方法的方法
--把自己左右一个参数传进来内部访问
print(t.sex)


print("好好学习,天天向上")
end

}
--申明表过后 在表外去申明表有的变量和方法
Student.name = "my!!!!"
Student.Speak =function()
print("说话")
end


--lua中.和:的区别

Student.Learn(Student)
--冒号调用方法会默认把调用者作为第一个参数传入方法中
Student:Learn()

function Student:Speak2()
--lua中有一个关键字self表示默认传入第一个参数

print(self.name.."说话222")
end



--c#要是使用类 实例化对象new 静态直接点
--Lua中类的表现 更像是一个类中有很多静态变量和函数
print(Student.age)
Student.Up()
Student:Speak2()
Student.Speak2(Student)
print("*********表的公共操作************")
--表中 table提供的一些公共方法的讲解

t1 ={ {age =1,name ="123"},{age =2,name ="345"} }

t2 ={name ="谁?",sex =true}
print(#t1)
--表的插入
table.insert(t1,t2);
print(#t1)

print(t1[1])
print(t1[2])
print(t1[3])
print(t1[3].sex)

--删除指定元素
--remove方法 传表进去 会移除最后一个索引的内容
table.remove(t1)
print(#t1)
print(t1[1].name)
--remove方法 传俩个参数 第一个参数是要移除内容的表
--第二个参数 是要移除内容的索引
table.remove(t1,1)
print(t1[1].name)

t2= {5,2,1,5,6,8}
--升列排序
table.sort(t2)
for _,v in pairs(t2) do
print(v)
end
--降列排序
table.sort( t2, function(a,b)
if a>b then
return true
end
end)
for _,v in pairs(t2) do
print(v)
end
--print("****拼接************")

tb ={"123","456","789","10010"}
--连接函数 用于拼接表中元素 返回值是一个字符串
str=table.concat( tb, "," )
print(str)

本地变量和全局变量的区别

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

print("*********多脚本执行************")

print("*********全局变量和本地变量************")
--全局变量
a=1
b="123"
for i =1,2 do
c="自己"
print(i)
end

print(c)

--本地变量的关键字 是 local
for i =1,2 do
local d="自己"
print(i)
print("循环中的d"..d)
end
print(d)

fun =function ( )
-- body
local tt ="12345123"
end
fun()
print(tt)

local tt2 ="555"
print(tt2)

print("*********多脚本执行************")

--关键字require("脚本名字"(部分大小写?))
require("text")
print(testA)
print(textLocalA)

print("*********脚本卸载************")
--如果是require加载执行的脚本 加载一次过后不会再被执行
require("text")

--package.loaded["脚本名"]
--返回值是boolean 意思是该脚本是否被执行
print(package.loaded["text"])
--卸载已经执行过的脚本
package.loaded["text"] = nil
print(package.loaded["text"])
require("text")


print("*********大G表************")
-- _G表是一个总表(tavle) 他将我们声明的全局变量都储存在去中
for k,v in pairs(_G) do
print(k,v)
end

lua中的一些小方法

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

print("*********特殊用法************")
print("*********多变量赋值************")
local a,b,c = 1,2,"123"

print(a)
print(b)
print(c)
--多变量赋值 如果后面的值不够会自动补空
a,b,c =1,2

print(a)
print(b)
print(c)
--多变量赋值 如果后面得到值多了会自动省略
a,b,c =1,2,3,4,5,6
print(a)
print(b)
print(c)

print("*********多返回值************")
function Test( )
return 10,20,30,40

-- body
end
--多返回值时 你用几个变量接 就有几个值
--如果少了 就少接几个 如果多了 就自动补空
a,b,c,d = Test()
print(a,b,c,d)


print("*********and or ************")
--逻辑与 逻辑或
--and or 他们不仅可以连接boolean 任何东西都可以用来连接
--在lua中 只有nil和false 才认为是假
--短路:对于and来说有假则假 对于or来说 有真则真
--所以 他们只需要判断第一个是否满足 就会停止计算了
print(1 and 2)
print(0 and 1)
print(nil and 1)
print(false and 2)
print(true and 3)

print(true or 1)
print(false or 1)
print( nil or 2)

--lua不支持三目运算符
x=3
y=2
-- ?:
local res = (x >y) and x or y
print(res)
--(x>y) and ---->x
--x or y ----->x

x=1
y=2
-- ?:
local res = (x >y) and x or y
print(res)
--(x>y) and ---->(x>y)
--(x>y) or y -----> y

在lua中实现协程

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
print("*********协同程序************")
print("*********协程的创建 ************")
--常用方式
--coroutine.create()
function fun( )
print(123)
-- body
end
co =coroutine.create(fun)
--协程的本质是一个线程对象
print(co)
print(type(co))
--coroutine.wrap()
co2 = coroutine.wrap(fun)
print(co2)
print(type(co2))


print("*********协程的运行************")
--第一种方式 对应的是通过create创建的协程
coroutine.resume(co)
--第二种方式
co2()

print("*********协程的挂起************")
fun2 =function()
local x = 1
while true do
x= x+1;
print(x)
print(coroutine.status(co3))
print(coroutine.running())
--协程的挂起函数
coroutine.yield(1)
end
end

co3 = coroutine.create(fun2);
--默认第一个返回值是协程是否启动成功
--yield里面的返回值
isok ,tempI = coroutine.resume(co3)
print(isok,tempI)
coroutine.resume(co3)

--这种方式的协程调用 也可以有返回值 只是没有默认第一个返回值了
co4 = coroutine.wrap(fun2)
co4("返回值"..co4())
co4()



print("*********协程的状态************")
--coroutine.status(协程对象)
--dead
--suspended暂停
-- running 进行中
--coroutine.status(co3)
print(coroutine.status(co3))
print(coroutine.status(co))
--这个函数可以得到当前正在运行的协程的线程号
coroutine.running()

元表和子表

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
print("*********元表************")
print("*********元表概念************")
--任何表变量都可以作为另一个表变量的元表
--任何变量都可以有自己的元表(父级)
--当我们子表进行一些特定操作时
--会执行元表中的内容

print("*********设置元表************")
meta ={}
myTable={}
--设置元表
--第一个参数 子表
--第二个参数 元表
setmetatable(myTable,meta)


print("*********特定操作************")
print("*********特定操作-__tostring************")
meta2 ={
--当子表要被当做字符串使用是 会默认调用这个元表中的tostring方法
__tostring=function (t)
return t.name
end


}
myTable2={
name ="who"
}
--设置元表
--第一个参数 子表
--第二个参数 元表
setmetatable(myTable2,meta2)
print(myTable2)


print("*********特定操作-__call************")
meta3 ={
--当子表要被当做字符串使用是 会默认调用这个元表中的tostring方法
__tostring=function (t)
return t.name
end,
--当子表被当做一个函数来使用时, 会默认调用这个__call中的内容
--当希望传入参数时 一定要记住 默认第一个参数调用的是自己
__call = function(a,b)
print(a)
print(b)
print"not is me"
end


}
myTable3={
name ="me "
}

--设置元表
--第一个参数 子表
--第二个参数 元表
setmetatable(myTable3,meta3)
--吧子表当做函数使用 就会调用元表的 __call方法
myTable3(1)
print("*********特定操作-运算符重载************")
meta4 = {
--相当于运算符重载,当子表使用+运算符时 会调用该方法
__add = function(t1,t2)
return t1.age + t2.age
end,
__sub = function(t1,t2)
return t1.age - t2.age
end,
__mul = function(t1,t2)
return t1.age * t2.age
end,
__div = function(t1,t2)
return t1.age / t2.age
end,
__mod = function(t1,t2)
return t1.age % t2.age
end,
__pow = function(t1,t2)
return t1.age ^ t2.age
end,
__eq = function(t1,t2)
return t1.age == t2.age
end,
__lt = function(t1,t2)
return false
end,
__le = function(t1,t2)
return t1.age <= t2.age
end,
__concat = function(t1,t2)
return t1.age .. t2.age
end

}
myTable4 ={age =1}

myTable5 ={age =2}
setmetatable(myTable4,meta4)
setmetatable(myTable5,meta4)


print(myTable4 .. myTable5)
print(myTable4 < myTable5)
--如果要用条件运算符来比较俩个对象
--这俩个对象的元表一定要一致 才能准确调用发方法

print("*********特定操作-__index和newIndex************")
meta6Father = { age =2}
meta6Father .__index =meta6Father

meta6 = {
--age=1,
-- __index = meta6
}
--index的赋值 卸载表外面来初始化
meta6.__index = meta6
--meta6.__index = {age =2}
myTable6 ={}

setmetatable(myTable6,meta6)
setmetatable(myTable6,meta6Father)
--得到元表的方法
print(getmetatable(myTable6))
--__index当子表中 找不到某一个属性时
--会到元表中 __index指定的表去找索引
print(myTable6.age)
--当我们使用它时 会去找自己身上有没有这个变量 不会去元表找
rawget(myTable6,"age")
print(rawget(myTable6,"age"))


--newIndex当赋值时,如果赋值一个不存在的索引
--那么就会吧这个值赋值到newindex所指的表中 不会修改自己
meta7 = {}
meta7.__newindex={}
myTable7 ={}
setmetatable(myTable7,meta7)
myTable7.age =1
print(myTable7.age)
--rawset该方法会忽略newindex的设置 指挥改自己的变量

rawset (myTable7,"age",2)
print(myTable7.age)

面向对象

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

print("*********面向对象************")

print("*********封装************")
--面向对象 类 其实都是基于table来实现
--元表相关的知识点
Objcet = {}
Objcet.id = 1
function Objcet:Test()
print(self.id)
end
--冒号会自动将调用这个函数的对象 作为第一个参数传入的想法(传入object
function Objcet:new ()
--self代表的是我们默认传入的第一个参数

-- 对象就是变量返回一个新的变量
--返回出去的内容 本质上就是表对象
local obj = {}
--元表知识 __index 当找自己的变量找不到时 就会去找元表当中__index指向的内容
self.__index = self
setmetatable(obj,self)

return obj
end

--[[local myObj = Objcet :new()
print(myObj)
print(myObj.id)
myObj:Test()
--对空表中声明一个新的属性 叫做id
myObj.id = 2
myObj:Test()--]]

print("*********继承************")

--c# class类名 : 继承类
--写一个用于继承的方法
function Objcet:subClass(className)
--_G知识点 是总表 所有声明的全局变量都以键值对的形式存在其中
_G[className] = {}
--写相关继承的规则
--用元表
local obj =_G[className]
self.__index = self
--子类定义一个base属性 base属性代表父类
obj.base =self;
setmetatable(obj,self)

end


Objcet:subClass("Person")
local p1 = Person:new()
print(p1.id)

Objcet : subClass("Monster")
local m1 = Monster:new ()
print(m1.id)
print("*********多态************")
--相同行为不同表现就是多态
--相同方法 不同执行逻辑 就是多态
Objcet:subClass("GameObject")
GameObject.posX = 0;
GameObject.posY = 0;
function GameObject:Move()
self.posX =self.posX +1
self.posY = self.posY +1;
print(self.posX)
print(self.posY)
end
GameObject:subClass("Player")
function Player:Move( )
--这个base指的是GameObject表(类
--这种方式调用相当于是吧基类表作为第一个参数传入了方法中
--避免把基类表传入到方法中 这样相当于共用一张表的属性
--我们如果要执行父类逻辑 我们不要直接使用冒号调用
--要通过.调用 然后自己传入第一个参数
self.base.Move(self)

end
local p1 = Player:new();
p1:Move()
--目前这种写法 有坑 不同对象使用的成员变量 居然是相同的成员变量
--不是自己的
local p2 =Player:new()
p2:Move()


面向对象

这部分太复杂,如果写到一个地方会显得非常的冗长并且不方便查看

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--面相对象实现
--万物之父,所有对象的基类 object
--封装
Object = {}
function Object : new()
local obj = {}
--给空对象设置元表以及_index
self.__index =self
setmetatable(obj,self)
return obj

-- body
end
--继承
function Object:subClasss(classname)
--根据名字生成一张表 就是一个类
_G[classname] ={}
local obj =_G[classname]
--设置自己的"父类"

obj.base = self
--给子类设置元表 以及_index
self.__index =self
setmetatable(obj,self)
end
--声明一个新的类
Object:subClasss("GameObject")
--成员变量
GameObject.posX = 0
GameObject.posY =0
--成员方法
function GameObject:Move( )
self.posX = self.posX + 1
self.posY = self .posY + 1
-- body
end
--实例化对象使用
local obj = GameObject:new()
print(obj.posX)
obj:Move()
print(obj.posX)

local obj2 = GameObject:new()
print(obj2.posX)
obj2:Move()
print(obj2.posX)

--声明一个新的雷 player继承GameObject
GameObject:subClasss("Player")
--多态 重写了 GameObject的move方法
function Player:Move()
--base调用父类方法 用点船第一个参数
self.base.Move(self)
end
print("&&&&&&&&&&&&&")
--声明实例化player对象
local p1 = Player:new()
print(p1.posX)
p1:Move()
print(p1.posX)

一些小技巧和自带库

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
38
39
40
41
42
43
44
45
46
47
48
49
print("*********自带库************")
--string
--table
print("*********时间************")
--系统时间
print(os.time())
--自己传入参数得到时间
print(os.time({year = 2014,month = 8,day = 14}))

--os.data("*t")
local nowTime = os.date("*t")
print(nowTime)
for k,v in pairs(nowTime) do
print(k,v)
end

print(nowTime.hour)
print("*********数学运算************")
--math
--绝对值
print(math.abs(-11))
--弧度转角度
print(math.deg(math.pi))
--三角函数
print(math.cos(math.pi))
--向上下取整
print(math.floor(2.6))
print(math.ceil(5.2))
--最大最小值
print(math.max(1,2,3,4))
print(math.min(1,2,3,4))

--小数分离 分成整数部分和小数部分
print(math.modf(1.2))
--幂运算
print(math.pow(2,5))

--随机数
--先设置随机数种子
math.randomseed(os.time())
print(math.random())

--开方
print(math.sqrt(4))
print("*********路径************")
--LUA脚本加载路径
print(package.path)


测试代码

1
2
3
4
5
6
7
print("text测试")
testA = "123"
local textLocalA = "3425"
print(123%10)
print(123/10)