案例概述
“跟我一起做”是一款记忆类游戏机,由3个LED灯和3个按键组成。游戏总共设置了10个关卡。开始时,LED灯会按一定顺序闪烁,闪烁结束后,玩家需要依次按下3个对应的按钮。如果顺序一致,进入更有挑战性的下一关;如果按错按钮,游戏结束。
游戏用Arduino设计,在制作过程中学生能够得到计算思维和编程能力的锻炼。
适合年龄
初中到高中
使用材料
功能材料:Arduino UNO板(如有一体主板,可直接使用,如无一体主板,可安装IO扩展板使用),LED模块×3,按键模块×3,3p连接线×6
结构材料:瓦楞纸板、彩色卡纸、蓝泥胶、束线带、装饰贴纸
思路分析
在制作开始前,我们应该先理清整个游戏的思路,才能更好地设计游戏机的程序。我们可以先绘制流程图(如图1),让你的思路更加明确。

程序设计
步骤1:硬件连接
如图2所示,分别将蓝、红、黄3个按钮杜邦接口端接在Arduino的5、6、7接口上,再将蓝、红、黄3个LED杜邦接口接在Arduino的8、9、10接口上。


步骤2:变量初始化
首先,要将所有在这个程序中需要用到的变量先声明好。这里我们需要声明的分别有按键接口、LED灯接口、保存关卡数组LedA、保存玩家输入答案用数组userLed、一个专门记录目前关卡数的变量Level,以及通往下一关的布尔变量nextL。程序如下:
// Buttons Pins
int GrBpin = 5;
int ReBpin = 6;
int YeBpin = 7;
// Leds Pins
int GrLpin = 8;
int ReLpin = 9;
int YeLpin = 10;
// Leds Array
int LedA [10]; // 定义关卡数组
int userLed [10]; // 玩家记录数组
int Level; // 计数目前关卡
boolean nextL = true; // 表示是否通关
步骤3:程序初始定义
在游戏开始之前,程序中与硬件沟通相关的指令,都需在setup()函数中完成预先声明。在这里我们要声明输入输出接口、随机种子、开始使用串口沟通的指令。程序如下:
void setup() {
randomSeed(analogRead(0)); //随机种子
// 定义LED灯为输出接口OUTPUT
pinMode(BlLpin, OUTPUT);
pinMode(ReLpin, OUTPUT);
pinMode(YeLpin, OUTPUT);
// 定义按钮为输入接口INPUT
pinMode(BlBpin, INPUT);
pinMode(ReBpin, INPUT);
pinMode(YeBpin, INPUT);
}
步骤4:设置关卡题目
在游戏开始之前,我们必须先将游戏关卡新题目准备好。为了不让主程序过于冗长,我们可以将设置关卡题目功能写进restartLeds()函数中,这样,每一个游戏回合结束后调用1次即可。该函数需要通过随机种子运算,运算结果运用循环一一存储到关卡数组中。程序如下:
// 通过随机种子运算出来的题目存储到关卡数组中
void restartLeds() {
Level = 1;
nextL = true;
int index = 0;
while (index < 10) {
LedA [index] = random (BlLpin, YeLpin+1);
index++;
}
}
步骤5:闯关结果灯号函数
我们让LED灯会显示出不同的状态,用来表示玩家的闯关结果。当玩家闯关成功,LED灯显示为流水灯;当玩家闯关失败,3盏LED灯同时闪烁。为了表示这个状态,我们需要设计2组函数,分别表示闯关成功和失败。程序如下:
// 闯关成功灯号函数
void winnerDance () {
for (int id=1; id <= 5; id++) {
digitalWrite (BlLpin, HIGH);
digitalWrite (ReLpin, LOW);
digitalWrite (YeLpin, LOW);
delay (100);
digitalWrite (BlLpin, LOW);
digitalWrite (ReLpin, HIGH);
delay (100);
digitalWrite (ReLpin, LOW);
digitalWrite (YeLpin, HIGH);
delay (100);
}
digitalWrite (YeLpin, LOW);
delay (2900);
}
// 闯关失败灯号函数
void Loose () {
digitalWrite (BlLpin, HIGH);
digitalWrite (ReLpin, HIGH);
digitalWrite (YeLpin, HIGH);
delay (200);
digitalWrite (BlLpin, LOW);
digitalWrite (ReLpin, LOW);
digitalWrite (YeLpin, LOW);
delay (200);
digitalWrite (BlLpin, HIGH);
digitalWrite (ReLpin, HIGH);
digitalWrite (YeLpin, HIGH);
delay (200);
digitalWrite (BlLpin, LOW);
digitalWrite (ReLpin, LOW);
digitalWrite (YeLpin, LOW);
}
步骤6:按键侦测函数
我们还需要设计一个函数让按键和相应颜色的LED灯对应起来。程序如下:
// 等待按键按下并回传被按下的按键接口号
char w4press() {
boolean bottPress = false;
while (bottPress == false) {
if (digitalRead(BlBpin) == HIGH) { // 读取蓝色按键是否被按下
while (digitalRead (BlBpin) == HIGH) {} // 等待按键是否被放开
return BlLpin; // 返回蓝灯接口号码
bottPress = true;
}
if (digitalRead(ReBpin) == HIGH) { // 读取红色按键是否被按下
while (digitalRead (ReBpin) == HIGH) {} // 等待按键是否被放开
return ReLpin; // 返回红灯接口号码
bottPress = true;
}
if (digitalRead(YeBpin) == HIGH) { // 读取黄色按键是否被按下
while (digitalRead (YeBpin) == HIGH) {} // 等待按键是否被放开
return YeLpin; // 返回黄灯接口号码
bottPress = true;
}
}
delay (200);
}
步骤7:显示关卡题目函数
在步骤4中,我们已经把每一关的题目函数设置好,但并没有用LED灯显示出来。在这一步,我们需要设计一个函数,用LED灯显示步骤4的题目。程序如下:
/ 显示当前关卡题目灯号
void questionLeds () {
int index = 0;
while (index < Level) {
digitalWrite (LedA [index], HIGH);
delay (500);
digitalWrite (LedA [index], LOW);
if (LedA [index] == LedA [index+1])
delay (200);
if (index >= 9)
break ;
index++;
}
}
步骤8:主程序
声明完所有的函数之后,就可以开始设计主程序。由于游戏需要重复执行,所以整个主程序需要写在loop()函数中。主程序分为2个部分:关卡判断和答案判断,其中,答案判断程序嵌套在关卡判断的while语句中。
● 关卡判断。主程序需要判断玩家是否通关,它判断2个变量:Level和nextL。Level变量是确认玩家是否通过全部关卡,当所处关卡不小于总关卡数,即处于最高关卡时,有可能闯关成功,否则继续进入游戏;布尔变量nextL记录玩家是否通关,若为false,代表闯关失败。
只有在布尔变量nextL为true,且所处关卡不小于总关卡数时,程序才会调用winnerDance()函数发出表示胜利的流水灯。
以下为判断部分主程序:
void loop() {
restartLeds();
while (nextL == true && Level <=10) {
// 在这里嵌套步骤8答案判断程序
}
if (nextL == false) {
Loose ();
delay (3000);
}
if (nextL == true && Level >=10)
winnerDance();
}
答案判断:
定义一个新的局部变量ubc,用来计算玩家按键次数。同时调用w4press()按键侦测函数,将其返回值保存至userLED数组中,并核对玩家记录数组userLED和题目数组LedA中的内容是否一致。若不一致,将nextL设为false,闯关失败,并将ubc变量改为低于目前关卡数的Level变量跳出循环结束判断。程序如下:
questionLeds(); // 播放目前关卡
int ubc=0;
while (Level>=ubc+1) { // 读取玩家输入按键并比较循环
userLed[ubc] = w4press();
if (userLed[ubc] != LedA[ubc]) {
nextL = false;
ubc = Level-1;
}
ubc ++;
}
Level ++;
delay (1000); // 每一关卡等待2秒
步骤9:编译上传测试
将程序编译并上传到Arduino,并进行测试,直到游戏机正常工作。
结构设计
完成“跟我一起做”游戏机功能的实现之后,我们还需要为游戏机制作一个外壳,以拥有更好的游戏体验。
步骤1:切割1块10 cm×13 cm长方形纸板和1块10 cm×10 cm纸板,将它们垂直粘贴起来,作为游戏机的底板和背板(如图3)。

(图3)
步骤2:用蓝泥胶将Arduino板、LED模块、按键模块粘贴到纸板上,并用束线带将线缆捆扎起来(如图4)。

(图4)
步骤3:用纸板制作游戏机的侧面和顶部。注意留出Arduino板的数据接口和电源接口(如图5)。

(图5)
步骤4:裁出一段长方形彩色卡纸,在按键和LED灯的对应处挖出圆形窗口。将彩色卡纸粘贴在游戏机的正面。最后粘贴上装饰贴纸,“跟我一起做”游戏机就完成了。连上电源线,玩起游戏机啦(如图6)!

后记,小编朋友公司研发了一个游戏化的少儿编程在线课程(5-12岁),游戏化教学结合scratch(一款在线少儿编程工具,类似乐高的积木拼搭),我家娃娃学了几次课,非常喜欢(超预期),16次课才200多块钱,对锻炼孩子的思维能力和动手动力很有帮助。
声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。