love2d-chapter7-tables-and-for-loops

love2d-chapter7-tables-and-for-loops

十月 12, 2020

第七章-表和for循环
我们可以在里储存一组变量。
我们用一对花括号({})来创建表。

1
2
3
function love.load()
fruits = {}
end

这样,我们就创建了一个叫fruit的表。现在我们可以往里面储存值了。要往表里储存值,有许多方法。
其中一种办法是在创建表时,在花括号里加入值。

1
2
3
4
function love.load()
-- 不同的值间用逗号分开
fruits = {"apple", "banana"}
end

或者使用函数table.insert。第一个参数是表的名字,第二个参数是你希望储存的值。

1
2
3
4
5
function love.load()
--Each value is separated by a comma, just like with parameters and arguments
fruits = {"apple", "banana"}
table.insert(fruits, "pear")
end

现在,当love.load()结束后,我们的表里应该包括了“apple”,“banana”和“pear”。为了证明这一点,我们将他们打印到屏幕上。我们将使用函数love.graphics.print(text, x, y)。第一个参数text是你要打印的内容,后两个x、y是你希望打印的位置。

1
2
3
4
function love.draw()
--Arguments: (text, x-position, y-position)
love.graphics.print("Test", 100, 100)
end

当你运行游戏,你应该看到“Test”出现在你的游戏窗口里。那么怎么打印表里的内容呢?要访问表中的内容,我们用表的名字加上一对方括号([]),在方括号里,我们加入要访问的值的位置。

就像我说的,表是一个值的列表。我们首先加入了“apple”"banana",所以它们分别在表的第一和第二个位置上。接下来我们增加了“pear”,所以它是第三个。第四个位置上还没有值,所以是nil
所以如果我们希望打印“apple”,我们就要访问表中的第一个值。

1
2
3
function love.draw()
love.graphics.print(fruits[1], 100, 100)
end

现在运行游戏,窗口中应该绘制了“apple”,如果你把[1]换成[2],那么就是"banana"[3]就是“pear”
现在我们要打印所有表中的全部3个水果。你当然可以使用三次love.graphics.print

1
2
3
4
5
function love.draw()
love.graphics.print(fruits[1], 100, 100)
love.graphics.print(fruits[2], 100, 200)
love.graphics.print(fruits[3], 100, 300)
end

但是如果表里有100个值怎么办?用100次love.graphics.print?万幸的是,我们不必这么做——我们可以使用——

for循环

for循环是一种让一段代码重复运行多次的办法。
要创建一个for循环,你可以这么写:

1
2
3
4
5
6
7
8
function love.load()
fruits = {"apple", "banana"}
table.insert(fruits, "pear")

for i=1,10 do
print("hello", i)
end
end

如果你运行游戏,控制台上就应该会输出:hello 1,hello 2,hello 3,直到hello 10。
要创建一个for循环,首先用保留字for开头。然后创建一个变量并且赋给它一个值。这个变量可以用任何名字,但是通常我们用i。这个变量只能在for循环内部使用。然后用逗号,再跟上一个数值(我们设它为j)。每次循环结束,i的值都会+1,直到i的值达到j,循环结束。所以循环将会执行(j-i+1)次。
还有一个可选的第三个数字。for i=6,18,4 do意味着:从6开始,每次加4,直到18。你还可以这样:for i=114514,1,-1,意思是从114514开始,每次减1,直到1。
我们的表从1开始,里面一共有三个值,所以我们这样:

1
2
3
4
5
6
7
8
function love.load()
fruits = {"apple", "banana"}
table.insert(fruits, "pear")

for i=1,3 do
print(fruits[i])
end
end

当你运行游戏,你将看到控制台输出了所有的3个水果。在第一个循环中,它打印fruits[1],然后在第二个循环中打印fruits[2],最后在第三个循环中打印fruits[3]

编辑表

如果我们又往表中添加或者移除了一个值,怎么办?我们当然可以把3改成对应的数字。但是有更好的办法,我们可以用#fruits#可以用来获取一个表的长度(也就是表中元素的数量)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function love.load()
fruits = {"apple", "banana"}

print(#fruits)
--Output: 2

table.insert(fruits, "pear")

print(#fruits)
--Output: 3

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

现在我们将试着在游戏的窗口上绘制这三种水果。

1
2
3
4
5
function love.draw()
for i=1,#fruits do
love.graphics.print(fruits[i], 100, 100)
end
end

如果你运行游戏,你会发现确实绘制了3种水果,但是重叠在一起,我们可以这样修复这个问题:

1
2
3
4
5
function love.draw()
for i=1,#fruits do
love.graphics.print(fruits[i], 100, 100 + 50 * i)
end
end

这样,"apple"将在y=100+50*1处绘制,"banana"在200,“pear”在250。

如果我们要添加其他水果,则无需进行任何更改。它将自动绘制。让我们添加“pineapple”

1
2
3
4
5
6
function love.load()
fruits = {"apple", "banana"}
table.insert(fruits, "pear")
table.insert(fruits, "pineapple")
table.remove(fruits, 2)
end

我们也可以从表中移除值,通过table.remove。第一个参数是我们希望从中移除元素的表的名字,第二个参数是我们希望移除的元素的位置。所以如果我们希望移除banana,我们这么做:

1
2
3
4
5
6
function love.load()
fruits = {"apple", "banana"}
table.insert(fruits, "pear")
table.insert(fruits, "pineapple")
table.remove(fruits, 2)
end

现在当你运行游戏,banana不再会被绘制,并且pear和pinapple的位置会向前移动。

当你使用table.remove从表中移除元素时,所有在被移除元素之后的元素都会向前移动一个位置。所以原本在第3位的pear移动到了第2位。
你也可以改变已经存储在表中的值。举个例子,你可以吧apple改成tomato。

1
2
3
4
5
6
7
8
function love.load()
fruits = {"apple", "banana"}
table.insert(fruits, "pear")
table.insert(fruits, "pineapple")
table.remove(fruits, 2)
--The value of position 1 in the table becomes "tomato"
fruits[1] = "tomato"
end

ipairs

现在我们回到for循环。当你需要用循环遍历一个表时,有一个更简单的办法,那就是使用ipairs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function love.load()
fruits = {"apple", "banana"}
table.insert(fruits, "pear")
table.insert(fruits, "pineapple")
table.remove(fruits, 2)
fruits[1] = "tomato"

for i,v in ipairs(fruits) do
print(i, v)
end
--Output:
--1, "tomato"
--2, "pear"
--3, "pineapple"
end

上面的这个for循环,我们也叫它迭代器。我们用迭代器来遍历一个表。变量i告诉我们我们现在在表中的位置,v是在该位置处的值。你可以认为vfruits[i]的简便写法。举个例子,在第一次迭代中i的值为1,v的值为"apple",而在第二次迭代中,iv将分别是2和“pear”
但是这究竟是这么工作的?ipairs函数的原理究竟是什么?不过那些都是另外一回事了。现在你只需要知道ipairs基本上是这样的:

1
2
3
for i=1, #fruits do
v = fruits[i]
end

让我们用ipairs绘制表:

1
2
3
4
5
6
function love.draw()
-- i and v are variables, so we can name them whatever we want
for i,frt in ipairs(fruits) do
love.graphics.print(frt, 100, 100 + 50 * i)
end
end

总结

表是我们可以在其中存储值的列表。我们在创建表时使用table.inserttable_name[1]=“some_value”存储这些值。我们可以使用#table_name获取表的长度。使用for循环,我们可以多次重复一段代码。我们还可以使用for循环遍历表。