按钮

到目前为止我们创建代码让micro:bit做一些事情,称之为 输出 。相反地,我们还需要让micro:bit对一些事物起作用,称之为 输入

输出是设备对外界输出信息,而输入是设备自己处理信息。这很容易记住。

micro:bit最明显的输入方式是通过 AB 两个按钮。我们需要MicroPython以某种方式对按钮进行响应。

这非常简单:

from microbit import *

sleep(10000)
display.scroll(str(button_a.get_presses()))

这些脚本的作用是:睡眠1万毫秒(10秒),接着滚动显示按钮 A 被按下的次数。这就是全部了。

尽管这些脚本意义不大,它还是引出了一些很有趣的新想法:

  1. sleep 函数 能使 micro:bit 睡眠一定量的毫秒数。如果想让程序暂停,这便是实现的方式。 函数 就像是*方法*,但它不是通过一个点连接到一个 对象
  2. 有一个叫 button_a 的对象,可以通过 get_presses 方法 获得表示被按压次数的数字。

由于 get_presses 能够提供数值,而 display.scroll 只显示字符,因此需要将数值转换为字符串。 str 函数可以做到这一点(str是“string”的简称,它可以将其他信息转换成字符串)。

第三行有点像洋葱。假设括号是洋葱皮,你会注意到 display.scroll 包含 strstr 包含 button_a.get_presses。Python实现最内层功能之后,才开始下一层。这被称为 嵌套 - 这些代码就像是一组俄罗斯套娃。

../_images/matrioshka.jpg

假设按钮被按下10次,Python实现第三行代码的方式如下:

Python理解了完整的行后,获取了 get_presses 的值:

display.scroll(str(button_a.get_presses()))

Python知道按钮被按下的次数后,将数值转换成字符串:

display.scroll(str(10))

最终,Python得知通过显示器应滚动显示的内容:

display.scroll("10")

虽然看起来工作量很大,MicroPython 却让这件事实现起来非常之迅速。

事件循环

通常你需要让程序等待某事件发生。要做到这一点,需要围绕一段代码定义循环,这段代码定义了如何对某些预期事件(例如按下按钮)作出反应。

在Python中创建循环需要用关键字 while ,用来事件是否为 。 如果是,它会运行一个 代码块,这个代码块称为循环 。 如果不是,则中断循环(忽略这个循环体),程序的其余部分继续执行。

Python定义代码块很容易。假设有一张纸质的待办清单,可能看起来像这样:

Shopping
Fix broken gutter
Mow the lawn

如果想把这份清单写得更详细些,则可能是这样:

Shopping:
    Eggs
    Bacon
    Tomatoes
Fix broken gutter:
    Borrow ladder from next door
    Find hammer and nails
    Return ladder
Mow the lawn:
    Check lawn around pond for frogs
    Check mower fuel level

很明显,主任务被分解为与之相关的主任务下的 缩进 子任务。 所以 Eggs, BaconTomatoes 显然与 Shopping 有关。通过缩进,我们可以很容易地看到任务之间的联系。

这被称为 嵌套。我们运用嵌套定义代码块如下:

from microbit import *

while running_time() < 10000:
    display.show(Image.ASLEEP)

display.show(Image.SURPRISED)

running_time 函数会在设备启动后返回毫秒数。

while running_time() < 10000: 这一行检查运行时间是否小于1万毫秒(10秒)。如果是, 则属于事件执行范围,设备将会显示 Image.ASLEEP (睡眠)。 像待办清单一样,请注意 while 语句下的缩进。

显然,若运行时间≥1万毫秒,则会显示 Image.SURPRISED。原因是 running_time 不满足<1万毫秒的条件, while 条件不成立。在这种情况下,循环终止,程序将会继续执行 while 循环之后的代码块。 看起来像是设备休眠10秒后,露出“惊喜”的表情。

试试看吧!

处理事件

如果我们希望MicroPython对按下按钮事件做出反应,应该把它放入一个永久循环并检查按钮是否 is_pressed (被按下)。

永久循环很简单:

while True:
    # Do stuff

(记住:如果要运行某代码块, while 会检查该事件是否为 True ,由于 True 事件永久为 True ,如此,一个永久循环就实现了!)

我们一起来做一个简单的网络宠物吧。这只宠物总是很悲伤,除非按下按钮 A。如果按下按钮 B ,这只宠物会死掉。(我意识到这不是一个令人愉快的游戏,所以也许你会想出改善这个游戏的方法。):

from microbit import *

while True:
    if button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        break
    else:
        display.show(Image.SAD)

display.clear()

你知道我们是如何判断哪些按钮应该被按下吗?我们用 ifelif (“else if”的缩写)和 else 来实现。这些被称为 条件,原理如下:

if something is True:
    # do one thing
elif some other thing is True:
    # do another thing
else:
    # do yet another thing.

这与英语极为相似。

is_pressed 方法仅产生两个结果: TrueFalse。按下按钮后系统要么返回 True,要么返回 False。上面代码的含义是:当按钮A被按下时,永久循环显示“高兴”的表情;而当按钮B被按下时,该循环终止;其他情况则显示“悲伤”的表情。 break 语句则用来终止循环。

最终,当网络宠物死亡时,我们对显示屏做了 clear (清除)。

你能想出让这个游戏不这么悲剧的办法吗?当 两个 按钮被同时按下时,该如何检查呢?(注释:Python中可以用逻辑运算符 and, ornot 来检查多重判断语句[multiple truth statements](产生 TrueFalse 结果的语句)