基于Micro:bit无线通信的双人猜数游戏设计与实现
1. 项目概述:从零构建一个无线猜数游戏
在嵌入式开发和物联网(IoT)的入门领域,Micro:bit 绝对算得上是一块“明星”开发板。它麻雀虽小,五脏俱全:一个5x5的LED点阵屏、两个可编程按键、一个加速度计、一个磁力计,以及我们今天要重点用到的——一个内置的2.4GHz无线电模块。很多初学者拿到手,可能玩过滚动名字、测个加速度,但如何让两块甚至多块Micro:bit“说上话”,实现真正的设备间交互,往往是进阶路上的一道坎。
这个“无线猜数游戏”项目,就是一个绝佳的敲门砖。它不涉及复杂的电路焊接,也不需要额外的传感器,仅仅依靠两块Micro:bit本身,就能实现一个完整的双人对战游戏。核心玩法很简单:你和对手各持一块Micro:bit,各自在心中(实则是程序中)生成一个0-9的随机数。然后,你们轮流通过按键调整自己的猜测,并通过无线电将猜测值发送给对方。对方收到后,会秘密比较这个猜测值与自己的秘密数字,并通过无线电发回“高了”、“低了”或“猜中了”的提示。这个过程,完美串联了变量管理、用户输入、条件逻辑判断和无线数据收发这几个嵌入式编程的核心概念。
我之所以推荐这个项目,是因为它把抽象的概念变得非常具体可感。你写的每一行代码,都能立刻在LED点阵和按键反馈上得到回应,而无线电通信则让代码的“影响力”超越了单块板子,这种即时、可见的成就感是学习编程的巨大动力。无论你是对物联网感兴趣的学生、希望开展创客教育的老师,还是想找个有趣项目练手的电子爱好者,这个案例都能让你在动手实践中,扎实地掌握Micro:bit无线通信的用法。下面,我就带你从设计思路到代码细节,完整地拆解这个项目。
2. 核心设计思路与方案选型解析
2.1 为什么选择“猜数游戏”作为教学案例?
在构思一个教学或演示项目时,选择“猜数游戏”并非偶然。它的核心优势在于规则极度简单,但涵盖的知识点非常全面。游戏逻辑本身就是一个经典的“二分查找”算法的雏形,玩家需要根据“高/低”的反馈不断缩小范围,这本身就蕴含了算法思维。更重要的是,为了实现这个游戏,我们必须解决几个关键问题:
- 状态管理:每个设备需要维护两个核心变量:自己设定的秘密数字(
Value)和当前准备猜对方的数字(Guess)。 - 人机交互:如何让用户输入(调整猜测值)并看到反馈?Micro:bit的A/B按键和LED点阵屏正好派上用场。
- 事件驱动编程:Micro:bit的编程模式是典型的事件驱动。我们需要响应“按键按下”和“收到无线电消息”这两个核心事件。
- 通信协议设计:两块设备之间需要传递哪些信息?如何定义这些信息的含义?这其实是一个微型通信协议的设计过程。
这个项目避免了复杂的图形或网络协议,将全部焦点集中在数据流和状态机上。数据在设备间流动(猜测值、提示信息),驱动设备状态发生变化(显示箭头、显示胜利),整个过程清晰得像一张流程图,非常适合初学者理解设备间交互的本质。
2.2 硬件方案:为什么是Micro:bit及其无线电模块?
市面上类似的开源硬件不少,比如Arduino,但Micro:bit在这个项目上优势明显。首先,它内置了无线电模块,无需像Arduino那样额外购买和连接NRF24L01之类的射频模块,大大降低了硬件门槛和连接出错的可能性。其无线电工作在2.4GHz频段,采用简单的数字信号收发,在MakeCode环境中被封装成极其简单的积木块,如“无线电发送数字”和“当收到数据时”,让通信编程变得像串口打印一样简单。
其次,它的集成化输入输出设备非常友好。5x5 LED点阵虽然分辨率低,但显示数字和简单箭头图案绰绰有余,且编程直观。两个物理按键(A和B)提供了最直接的数字增减输入方式。如果换用其他没有屏幕或按键的设备,这个项目的交互部分就会变得复杂很多,需要连接外设,从而分散了学习无线通信的核心注意力。
最后,MakeCode图形化编程环境和Python文本编程的双重支持,使得它既能吸引编程零基础的初学者通过拖拽积木快速实现功能,也能满足希望深入学习的用户用代码进行更精细的控制。本项目以MakeCode为例,但其设计思想完全适用于Python或其他语言。
2.3 通信逻辑设计:半双工与消息类型定义
在这个双机游戏中,通信模式是典型的半双工:同一时间,只有一个设备在发送,另一个在接收,然后角色互换。我们设计了两类消息:
- 数字消息(Number):用于传递猜测值。当玩家按下A+B键时,将当前的
Guess变量值作为数字发送出去。 - 字符串消息(String):用于传递游戏状态反馈。接收方在比较猜测值和自己的秘密数字
Value后,会发送“up”、“down”或“win”这样的字符串。
这里有一个关键的设计考量:为什么反馈要用字符串而不是数字或自定义代码? 使用像“up”、“down”这样语义明确的字符串,极大地提高了代码的可读性和可调试性。当你看到代码中判断收到的字符串是否是“win”时,其含义一目了然。如果使用数字代码(比如用1代表高了,0代表低了),我们还需要额外维护一个“密码本”,增加了记忆和出错的成本。在简单的教学项目中,清晰至上。
注意:无线电通信需要设置“组号”(Radio Group)。这类似于对讲机的频道。只有将两块Micro:bit设置为同一个组号(1-255之间的任意数字),它们才能互相通信。这是一个必须确保一致的配置点,也是调试时第一个要检查的地方。
3. 详细实现步骤与代码解析
我们将使用MakeCode for micro:bit的图形化编程环境(网址:makecode.microbit.org)进行开发。即使你没有实体Micro:bit,也可以在该网站进行仿真,效果几乎一样。
3.1 第一步:初始化与变量设置
所有程序的起点都是当开机时积木。这部分代码只会在设备启动或复位时执行一次,用于完成初始状态的设置。
-
创建变量:
Guess(猜测值):代表玩家当前准备发送出去猜测对方的数字。初始值设为0。Value(目标值):代表对方要猜的、我们自己设定的秘密数字。
-
生成随机秘密数字:
- 使用
将Value设为在0到9之间取随机数积木。这里选择范围0-9,而非1-10,是一个重要的细节考量。Micro:bit的LED点阵在显示数字“10”时,需要依次显示“1”和“0”,会产生一个明显的滚动效果,这会破坏游戏的即时反馈感,让玩家觉得反应迟钝。0-9都是单字符,可以瞬间完整显示。
- 使用
-
配置无线电:
- 使用
无线电设置组积木,将一个数字(比如1)作为参数输入。务必确保对战的两块Micro:bit设置成相同的组号,否则它们将无法通信。
- 使用
实操心得:在当开机时中,除了上述设置,我习惯再加一句显示图标(比如一个勾号)或显示数字(显示生成的Value用于自检,正式游戏时可注释掉),作为初始化完成的视觉提示,这对于调试非常有用。
3.2 第二步:玩家输入——调整猜测值
这部分代码响应用户的按键操作,用于调整Guess变量的值并实时显示。
-
响应按钮A(减小猜测值):
- 拖入
当按钮A被按下积木。 - 内部先使用
如果...那么...进行边界检查:如果 Guess > 0 那么。这是因为我们的有效范围是0-9,当Guess已经是0时,再减1就会变成-1,超出显示范围。 - 在条件内,使用
以1增减 Guess积木,选择“-1”。 - 最后,使用
显示数字 Guess,让玩家立即看到当前猜测值。
- 拖入
-
响应按钮B(增大猜测值):
- 同理,拖入
当按钮B被按下积木。 - 边界条件变为:
如果 Guess < 9 那么。 - 在条件内,将
Guess增加1,并显示。
- 同理,拖入
-
响应按钮A+B(发送猜测):
- 拖入
当按钮A+B被按下积木。这是一个组合键事件。 - 内部直接使用
无线电发送数字 Guess积木。此时,当前的Guess值就会被广播到同一无线电组的所有设备。
- 拖入
注意事项:在调整Guess时,每次按键都会触发显示数字。你会发现LED屏幕上的数字会不断变化,这提供了很好的即时反馈。但要注意,Micro:bit的显示是独占的,如果在显示过程中收到无线电消息需要显示箭头,可能会产生冲突。好在我们的游戏节奏不快,这种冲突概率很低,属于可接受范围。在更复杂的项目中,可能需要管理显示队列。
3.3 第三步:接收并判断猜测值(裁判逻辑)
这块代码运行在“被猜”的设备上。它监听无线电,当收到一个数字(即对方的猜测)时,扮演裁判角色,将其与自己的Value进行比较,并发送相应的提示信息。
-
监听无线电数字消息:
- 拖入
当无线电收到数据时积木,它会提供一个receivedNumber变量,存放对方发来的数字。
- 拖入
-
三层条件判断:
- 使用
如果...那么...否则如果...那么...否则...这个多分支判断积木。 - 第一层(猜中):
如果 receivedNumber = Value 那么。如果成立,说明对方猜对了。我们使用无线电发送字符串 "win"向对方发送胜利消息。 - 第二层(猜低):
否则如果 receivedNumber < Value 那么。对方猜的数字太小了。我们使用无线电发送字符串 "up",提示对方“需要往大了猜”。 - 第三层(猜高):
否则。既然不等于也不小于,那就只能是大于了。我们使用无线电发送字符串 "down",提示对方“需要往小了猜”。
- 使用
核心细节解析:这里的逻辑顺序很重要。必须先判断“等于”,因为这是游戏的终止条件。如果先判断小于或大于,当数字正好等于时,也会被其中一个条件捕获,导致无法发送“win”消息。这种顺序是编写条件语句时常见的“边界优先”原则。
3.4 第四步:接收反馈并显示(玩家逻辑)
这块代码运行在“猜测方”的设备上。它监听无线电的字符串消息,根据收到的“up”、“down”或“win”来更新显示,告诉玩家下一步该怎么做。
-
监听无线电字符串消息:
- 拖入
当无线电收到数据时积木(注意,这次是接收字符串版本,积木形状可能略有不同,在MakeCode中需从无线电类别选择接收字符串的块)。它会提供一个receivedString变量。
- 拖入
-
根据消息内容显示:
- 同样使用多分支
如果...那么...积木。 - 如果 receivedString = "up":说明上次猜低了。使用
显示图标积木,选择一个向上箭头(↑)的图标,提示玩家增加猜测值。 - 否则如果 receivedString = "down":说明上次猜高了。显示一个向下箭头(↓)的图标。
- 否则如果 receivedString = "win":恭喜!猜对了。可以先用
显示字符串 "YOU WIN!"滚动显示胜利信息,然后跟一个笑脸图标显示图标(😊),给玩家一个强烈的正反馈。
- 同样使用多分支
经验技巧:显示箭头后,箭头图标会一直停留在屏幕上。为了让玩家在调整下一个猜测值时能看到数字,最好让箭头显示一段时间后自动清空。可以在每个显示箭头图标后面,加一个暂停(ms)积木(比如暂停1000毫秒),然后跟一个清空屏幕积木。这样箭头提示会持续1秒后消失,屏幕恢复空白,等待玩家输入下一个猜测。
4. 系统联调、优化与扩展思路
4.1 双机联调流程与常见问题排查
当两块Micro:bit都烧录好程序后,就可以开始联调了。建议遵循以下步骤:
- 独立测试:分别给两块板上电。分别按下各自的A/B键,观察
Guess变量是否在0-9之间正常增减并显示。这是确保输入部分正常。 - 检查无线电组:这是最常见的问题源。反复确认两块板子在
当开机时中设置的无线电组号是否完全相同。一个设为1,另一个设为2,它们就永远收不到对方的消息。 - 单向发送测试:让设备1按下A+B键发送猜测。观察设备1的屏幕,发送瞬间无线电图标会闪烁一下。此时查看设备2,如果程序正确,设备2应该会根据判断发送一个字符串反馈(但此时设备1还无法显示反馈,因为我们在测单向)。你可以临时在设备2的裁判逻辑里,在发送字符串后加一句
显示图标(比如心形),来确认设备2确实收到了数字并执行了判断逻辑。 - 完整流程测试:现在测试端到端流程。设备1发送一个猜测(比如5)。设备2收到后,会根据它的
Value发送“up”、“down”或“win”。设备1应该收到这个字符串并显示相应的箭头或胜利信息。
常见问题速查表:
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 按键后屏幕无反应 | 程序未成功烧录;电池没电或USB接触不良。 | 重新插拔USB线,在MakeCode点击“下载”并拖入MICROBIT盘符。检查电源。 |
| 按下A+B键,对方无任何反应 | 1. 无线电组号设置不一致。 2. 距离过远或有强干扰。 3. “无线电发送数字”积木未正确使用。 |
1. 核对两块板的无线电设置组代码。2. 将设备靠近(1米内),避开WiFi路由器等。 3. 检查 Guess变量是否被正确传入发送积木。 |
| 收到猜测后,裁判方不发送反馈 | 裁判方的当无线电收到数据时事件未触发,或内部逻辑错误。 |
在裁判方的当无线电收到数据时事件内第一行,添加显示数字 receivedNumber,看是否触发。检查Value变量是否已正确初始化。 |
| 收到反馈后,显示错误图标或没显示 | 玩家方的当无线电收到数据时(字符串)事件逻辑错误,或字符串对比有误(大小写、空格)。 |
在玩家方事件内第一行,添加显示字符串 receivedString,确认收到的具体内容。检查条件判断中的字符串是否完全匹配,包括引号。 |
| 游戏结束后无法重新开始 | 程序没有重置机制。 | 按下Micro:bit背面的复位按钮(RESET),或重新上电。这是最简单的方式。 |
4.2 项目优化与功能扩展
基础版本运行稳定后,你可以尝试以下优化和扩展,让游戏更完善、更富挑战性:
- 增加游戏状态管理:目前游戏结束后,需要手动复位。可以增加一个“游戏结束”状态变量。当一方获胜后,双方都进入结束状态,忽略后续的按键和消息。同时,可以设计长按A+B键来重置游戏(重置
Value为随机数,Guess为0,并清空状态)。 - 加入声音提示:Micro:bit可以通过蜂鸣器(连接引脚)播放音调。可以在发送猜测、收到反馈(特别是获胜时)加入简短的提示音,体验更佳。
- 扩展数字范围:将范围从0-9扩大到0-99。这时,调整
Guess的按键逻辑需要改变:比如,按A键减1,按B键加1,同时按A+B切换“十位/个位”编辑模式。这大大增加了编程的复杂度,也更有挑战性。 - 多人游戏模式:利用无线电的广播特性,可以设计一个“主持人”和多个“玩家”的模式。主持人生成一个随机数,所有玩家同时竞猜,谁先猜中主持人就广播获胜者ID。这涉及到设备地址识别和更复杂的通信协议。
- 加入加速度计控制:除了按键,可以用倾斜Micro:bit来控制
Guess值的增减,比如向左倾斜减1,向右倾斜加1,摇一摇发送。这利用了板载的加速度计,让交互更有趣。
4.3 从图形化到文本编程的进阶
如果你已经熟练掌握了MakeCode的积木编程,强烈建议你用Python(MicroPython)重新实现这个游戏。在MakeCode编辑器中,点击右上角的“{} JavaScript”或通过离线工具使用Python,你会看到完全不同的编程视角。
用Python实现,你会更深入地理解:
- 事件回调函数:如何用
on_button_pressed和radio.on()来注册事件处理函数。 - 全局变量:如何在函数外定义
guess和value。 - 条件语句的语法:
if...elif...else的结构。 - 无线通信的数据处理:如何发送和接收字节数组,如何编码解码。
文本编程能给你更大的灵活性和控制力,也是走向更复杂嵌入式开发的必经之路。这个猜数游戏的所有逻辑,用Python实现大约也就50行左右的清晰代码,是一个完美的练手项目。
这个基于Micro:bit的无线猜数游戏,虽然代码量不大,但它像一颗种子,包含了嵌入式交互产品从设计、实现到调试的完整基因。当你成功让两块小板子通过你编写的代码“对话”并完成一个游戏时,你所理解的,已经远远超出了一个简单的猜数字逻辑。你理解了状态、事件、通信协议这些构建更宏大物联网应用的基础砖石。接下来,不妨试着修改参数,增加功能,或者用它作为课堂项目展示给你的伙伴,在动手和分享中,这些知识会掌握得更加牢固。