适用场景
两个人进行桌面知识问答,希望按下各自按钮后留下明确结果,后按的人不能覆盖先前结果。本教程使用 micro:bit 自带的 A、B 按键和点阵屏,不需要外接传感器或制作额外电路。
本文整理日期为 2026-10-26,代码使用 micro:bit MicroPython,适合常见第一代和第二代开发板。它用于课堂和桌面游戏,采用软件采样判断先后,不能作为严格竞赛计时设备。
原理:把抢答分成三个阶段
程序有等待松手、等待抢答和结果锁定三个阶段。开机后先要求两键连续松开一小段时间,再显示准备图案。抢答时,每个按键连续检测为按下至少 30 毫秒,才取得一次有效确认。
第一个按键确认后开启 50 毫秒观察窗口;另一个按键也在窗口内确认,就显示平局符号。窗口结束后显示 A 或 B,并锁定结果。这里的“先按”实际指先达到软件确认条件,两者在很短时间内可能无法严格区分。
结果锁定后,同时长按 A、B 一秒申请下一轮。随后仍要松开两键才能重新准备,避免复位动作被当成下一次抢答。复位组合键没有身份认证,游戏中应约定由主持人操作。
准备工作
准备一块 micro:bit、一根可靠的数据线和支持该设备的 MicroPython 编辑器。先保存板上原来的程序源文件,上传新程序会替换原有应用。
本项目只使用板载按键和显示屏,通过正常 USB 接口供电。不要给边缘连接器接入外部电压,也不要把金属物放在开发板背面。若以后增加外接按钮,必须另行核对引脚和电气条件,并断电接线。
第一步:写入完整程序
在 micro:bit Python 编辑器中建立项目,替换为以下代码。代码中的时间单位均为毫秒,没有需要填写的设备地址或凭据。
from microbit import button_a, button_b, display, Image, running_time, sleep
DEBOUNCE_MS = 30
TIE_MS = 50
RELEASE_MS = 150
RESET_MS = 1000
state = 'release'
released_at = None
reset_at = None
pressed_at = [None, None]
confirmed = [None, None]
first_at = None
display.show('-')
while True:
now = running_time()
pressed = [button_a.is_pressed(), button_b.is_pressed()]
if state == 'release':
if not pressed[0] and not pressed[1]:
if released_at is None:
released_at = now
elif now - released_at >= RELEASE_MS:
pressed_at = [None, None]
confirmed = [None, None]
first_at = None
reset_at = None
state = 'ready'
display.show(Image.DIAMOND)
else:
released_at = None
elif state == 'ready':
for i in range(2):
if pressed[i]:
if pressed_at[i] is None:
pressed_at[i] = now
if confirmed[i] is None and now - pressed_at[i] >= DEBOUNCE_MS:
confirmed[i] = now
else:
pressed_at[i] = None
if first_at is None:
times = [t for t in confirmed if t is not None]
if times:
first_at = min(times)
if first_at is not None and now - first_at >= TIE_MS:
a, b = confirmed
if a is not None and b is not None and abs(a - b) <= TIE_MS:
display.show('=')
elif a is not None and (b is None or a < b):
display.show('A')
else:
display.show('B')
state = 'locked'
reset_at = None
elif state == 'locked':
if pressed[0] and pressed[1]:
if reset_at is None:
reset_at = now
elif now - reset_at >= RESET_MS:
state = 'release'
released_at = None
display.show('-')
else:
reset_at = None
sleep(5)
第二步:确认准备过程
将程序下载到开发板,松开两键。屏幕先显示横线,然后显示菱形,表示可以抢答。如果启动时一直按着某个按钮,程序会留在等待松手阶段;这可以避免有人提前压住按钮获得结果。
上传后没有出现预期图案时,先看屏幕是否滚动错误信息,检查代码缩进和是否使用 MicroPython 环境。不要把另一种编辑器的 Python 接口名称混入本程序。
第三步:验证胜出与锁定
看到菱形后,单独按 A 并保持片刻,应显示 A。随后按 B,结果应继续保持 A。重新开局后交换顺序,应显示 B,之后按 A 也不能覆盖。
确认时间用于排除过短按压,平局窗口则用于定义接近同时操作的处理规则。两个阈值承担不同任务,不能简单把确认时间调得很大来改善平局判断,否则短促正常按键也会被忽略。
第四步:验证平局和下一轮
同时按下两键并保持,两个确认时间足够接近时应显示等号。锁定状态下继续同时按住一秒,屏幕变为横线;即使继续按住,也不会立刻重新接受抢答。松开两键后,经过准备间隔才重新显示菱形。
结果没有自动保存在非易失存储中,按复位键或断电会清除本轮结果并重新启动。主持人需要记录分数时,应在复位之前另行登记。
验证方法
按固定顺序检查六种情况:开机按住单键、正常先 A 后 B、正常先 B 后 A、近乎同时按、锁定后反复按落后方按钮、长按复位后继续不松手。分别检查等待、胜出、平局、锁定和重新准备条件是否符合约定。
测试时每轮都等待菱形出现。不要用手指感觉判断几十毫秒的准确差值;本项目验证的是规则能否按预期执行,而不是证明两个按钮拥有精密同步采样能力。
常见错误
把短按没有响应误认为程序停止,可能只是按压没有持续到确认时间。另一种情况是在结果锁定时两个人一直按住各自按钮,达到复位时间后自然会进入下一轮等待,这属于当前组合键设计的行为。
如果把滚动文字动画加入等待抢答阶段,默认阻塞显示可能延迟按键采样。扩展程序时,应把长动画放在锁定之后,或先理解非阻塞显示参数,再检查采样是否仍然稳定。
安全与回退
修改前保留本版源文件,每次只调整一个时间参数并重复验证。参数改乱时恢复上面的默认值。需要退出项目时,使用编辑器重新写入之前保存的程序;断电只会清除运行状态,不会恢复被覆盖的旧程序。
参考资料与转载说明
本文依据上述公开资料进行中文原创整理,不是逐句翻译,也不替代厂商手册。操作前请核对自己的版本、型号和备份。
评论一下?