简介
还记得经典的西蒙说游戏吗?它是学习 Arduino 上数组、状态机和用户输入处理的完美项目。在本教程中,我们将使用四个 LED 和四个按钮构建一个功能完整的西蒙说游戏,所有操作都在浏览器中通过 Velxio 模拟完成,无需任何硬件!

电路讲解
让我们看看各个组件及其连接方式。
组件
| 组件 | ID | 用途 |
|---|---|---|
| Arduino Uno | arduino-uno | 游戏的大脑 |
| 红色 LED | led-red | 红色序列输出 |
| 绿色 LED | led-green | 绿色序列输出 |
| 蓝色 LED | led-blue | 蓝色序列输出 |
| 黄色 LED | led-yellow | 黄色序列输出 |
| 红色按钮 | button-red | 红色用户输入 |
| 绿色按钮 | button-green | 绿色用户输入 |
| 蓝色按钮 | button-blue | 蓝色用户输入 |
| 黄色按钮 | button-yellow | 黄色用户输入 |
接线
每个 LED 的阳极 (A) 连接到 Arduino 的数字引脚,阴极 (C) 通过限流电阻(内部模拟)连接到 GND。按钮的一个引脚 (1.l) 连接到数字引脚,另一个引脚 (2.l) 连接到 GND,使用 Arduino 的内部上拉电阻。
- 红色 LED:引脚 8(红线)接阳极,阴极接 GND(黑线)。
- 绿色 LED:引脚 9(绿线)接阳极,阴极接 GND。
- 蓝色 LED:引脚 10(蓝线)接阳极,阴极接 GND。
- 黄色 LED:引脚 11(黄线)接阳极,阴极接 GND。
- 红色按钮:引脚 2(浅蓝线)接 1.l,2.l 接 GND。
- 绿色按钮:引脚 3(浅蓝线)接 1.l,2.l 接 GND。
- 蓝色按钮:引脚 4(浅蓝线)接 1.l,2.l 接 GND。
- 黄色按钮:引脚 5(浅蓝线)接 1.l,2.l 接 GND。
所有接地连接共享 Arduino 的 GND 引脚。
代码讲解
在 Velxio 中打开代码编辑器查看完整草图。

常量和变量
const int LED_PINS[] = {8, 9, 10, 11};
const int BUTTON_PINS[] = {2, 3, 4, 5};
const int NUM_LEDS = 4;
int sequence[100];
int sequenceLength = 0;
int currentStep = 0;
我们定义了 LED 和按钮引脚的数组,与接线匹配。sequence 存储随机模式(最多 100 步)。sequenceLength 跟踪玩家需要重复的步数,currentStep 跟踪玩家的进度。
初始化
void setup() {
Serial.begin(9600);
for (int i = 0; i < NUM_LEDS; i++) {
pinMode(LED_PINS[i], OUTPUT);
pinMode(BUTTON_PINS[i], INPUT_PULLUP);
}
randomSeed(millis());
newGame();
}
我们将 LED 引脚设置为输出模式,按钮引脚设置为带内部上拉的输入模式(因此按钮按下时读取为 LOW)。randomSeed(millis()) 确保每次游戏生成不同的序列。newGame() 开始第一轮。
游戏逻辑
newGame() 将序列长度重置为 1,添加一个随机步骤,并播放序列。
void newGame() {
sequenceLength = 1;
currentStep = 0;
addToSequence();
playSequence();
}
void addToSequence() {
sequence[sequenceLength - 1] = random(0, NUM_LEDS);
}
void playSequence() {
for (int i = 0; i < sequenceLength; i++) {
flashLED(sequence[i]);
delay(500);
}
}
void flashLED(int led) {
digitalWrite(LED_PINS[led], HIGH);
delay(300);
digitalWrite(LED_PINS[led], LOW);
}
playSequence() 遍历存储的序列,每个 LED 闪烁 300 毫秒,间隔 500 毫秒。
主循环
void loop() {
for (int i = 0; i < NUM_LEDS; i++) {
if (digitalRead(BUTTON_PINS[i]) == LOW) {
flashLED(i);
if (i == sequence[currentStep]) {
currentStep++;
if (currentStep == sequenceLength) {
delay(1000);
sequenceLength++;
currentStep = 0;
addToSequence();
playSequence();
}
} else {
// 按错按钮——游戏结束
for (int j = 0; j < 3; j++) {
for (int k = 0; k < NUM_LEDS; k++) {
digitalWrite(LED_PINS[k], HIGH);
}
delay(200);
for (int k = 0; k < NUM_LEDS; k++) {
digitalWrite(LED_PINS[k], LOW);
}
delay(200);
}
newGame();
}
delay(300);
while (digitalRead(BUTTON_PINS[i]) == LOW);
}
}
}
主循环持续检查所有按钮。当按钮被按下(LOW)时,闪烁对应的 LED。如果按下的按钮与预期步骤(sequence[currentStep])匹配,则前进。如果玩家完成了整个序列,则添加一个新步骤并播放更长的序列。如果按错,所有 LED 闪烁三次,然后开始新游戏。
关键概念
- 数组:使用数组存储引脚编号和游戏序列,使代码可扩展且整洁。
- 内部上拉电阻:
INPUT_PULLUP省去了外部电阻;按钮按下时读取为 LOW。 - 按键消抖:
delay(300)和while(digitalRead(...)==LOW)循环提供了简单的消抖处理。 - 随机性:
randomSeed(millis())和random()生成不可预测的序列。 - 状态机:游戏通过
currentStep和sequenceLength跟踪进度。
常见问题与调试技巧
- 按钮无响应? 检查按钮引脚是否设置为
INPUT_PULLUP且接线正确(1.l 接引脚,2.l 接 GND)。 - LED 不亮? 确认 LED 引脚为
OUTPUT模式,且阳极/阴极连接正确。 - 序列太快? 调整
flashLED()和playSequence()中的delay()值。 - 游戏意外重置? 确保
randomSeed(millis())仅在setup()中调用一次。 - 使用串口监视器:添加
Serial.println()语句调试序列值。
建议扩展
- 添加蜂鸣器:为每个 LED 颜色播放音调。
- 难度等级:随着序列增长提高速度。
- 最高分:记录达到的最长序列。
- 多人模式:两名玩家轮流操作。
- 视觉反馈:使用不同的 LED 亮度或模式。
亲自试试!
准备好了吗?在 Velxio 上打开实时示例并启动模拟。按下按钮重复序列。你能走多远?
祝你构建愉快!