Arduino入门教程20--反应速度测试「DFR0100」
本帖最后由 zoey不种土豆 于 2024-11-21 20:30 编辑在这个项目中我们将用Arduino制作一个反应速度测试游戏。通过点亮LED灯并快速按下对应按钮来得分,游戏持续一分钟。准备挑战你的反应极限了吗?让我们开始吧!
元件清单
硬件连接
在这个项目中,我们使用到的LED灯和按键模块,都是在之前的项目中出现过的。不同的一点是之前项目【交通信号灯】中给按键外加了一个下拉电阻,在这个项目中,我们使用Arduino芯片内部的上拉电阻,详见本项目的硬件回顾。请按照下图将硬件连接正确。
图 1 反应速度测试连线图示例代码
样例代码://项目 - 反应速度测试
// 定义LED灯和按钮的引脚
const int LEDS[] = {3, 5, 7};
const int BUTTONS[] = {2, 4, 6};
int score = 0; // 玩家的得分
bool gameStarted = false; // 游戏是否开始的标志
unsigned long gameStartTime; // 记录游戏开始的时间戳
const unsigned long gameDuration = 60000;
// 游戏持续时间,单位为毫秒(1分钟)
void setup() {
Serial.begin(9600); // 初始串口通信
// 设置LED灯和按钮的引脚模式
for (int i = 0; i < 3; i++) {
pinMode(LEDS, OUTPUT);
pinMode(BUTTONS, INPUT_PULLUP);
}
}
void loop() {
// 检查是否同时按下了所有三个按钮来开始游戏
if (!gameStarted && digitalRead(BUTTONS) == LOW && digitalRead(BUTTONS) == LOW && digitalRead(BUTTONS) == LOW) {
Serial.println("游戏开始");
gameStarted = true;
score = 0; // 重置得分
gameStartTime = millis(); // 记录游戏开始的时间
delay(1000); // 等待一秒后开始游戏
}
// 如果游戏已经开始,检查游戏是否超时
if (gameStarted && millis() - gameStartTime < gameDuration) {
int led = random(0, 3); // 随机选择一个LED
digitalWrite(LEDS, HIGH); // 点亮这个LED
long startTime = millis(); // 记录点亮LED的时间
bool buttonPressed = false; // 初始化按钮状态(未被按下)
// 给玩家一定时间来按按钮
while (millis() - startTime < 1000) {
if (digitalRead(BUTTONS) == LOW) {
// 检查是否按下了对应的按钮
buttonPressed = true;
break; // 如果按下了按钮,跳出循环
}
}
digitalWrite(LEDS, LOW); // 熄灭LED
if (buttonPressed) {
score++; // 如果按下了按钮,增加得分
Serial.println("得分 +1");
}
delay(200); // 等待一段时间再继续下一轮
} else if (gameStarted) {
// 如果游戏时间超过一分钟或玩家没有在时间内按下按钮,游戏结束
gameStarted = false;
Serial.print("游戏结束! 你的得分: ");
Serial.println(score); // 通过串口输出得分
delay(3000); // 等待3秒后可以重新开始游戏
}
}上传代码后,打开串口监视器,同时按下三个按键开始游戏,串口监视器上出现游戏开始字样。一旦游戏开始,系统将随机点亮一个LED灯,并给玩家一秒钟的时间来按下对应的按钮,便可获得1分。当游戏时间到达1分钟时,串口监视器出现游戏结束并告知你的游戏得分。
代码回顾
变量声明部分不做过多解释了,这个部分用于定义LED和按钮的引脚数组,以及用于跟踪得分、游戏状态和游戏时间的变量。const int LEDS[] = {3, 5, 7};
const int BUTTONS[] = {2, 4, 6};
int score = 0;
bool gameStarted = false;
unsigned long gameStartTime;
const unsigned long gameDuration = 60000;gameDuration是一个非负长整型的常数,用于定义游戏的持续时间。在这里,它被设置为60000毫秒,即1分钟,以确保游戏持续一分钟。在setup()函数中,初始化串口通信,并使用一个for循环设置LED和按钮的引脚模式。在loop()函数中,流程如下:// 游戏开始前的检查
if (!gameStarted && digitalRead(BUTTONS) == LOW && digitalRead(BUTTONS) == LOW && digitalRead(BUTTONS) == LOW
) {
// 游戏初始化
gameStarted = true;
}
// 游戏被激活后
if (gameStarted && millis() - gameStartTime < gameDuration) {
// 游戏进行中
} else if (gameStarted) {
// 游戏结束
}
// 返回游戏开始前的检查如果用流程图,表示如下:第一个部分是游戏开始前的检查。用来判断游戏是否被激活,激活指的是从游戏的非激活状态(即未开始也未在进行中)转换到准备开始的状态。if (!gameStarted && digitalRead(BUTTONS) == LOW && digitalRead(BUTTONS) == LOW && digitalRead(BUTTONS) == LOW) 所以在第一个判断中,既要判断三个按键是否被同时按下,又要判断当时游戏是否处于未激活状态。游戏被激活后进行游戏的初始化:Serial.println("游戏开始");
gameStarted = true;
score = 0; // 重置得分
gameStartTime = millis(); // 记录游戏开始的时间
delay(1000); // 等待一秒后开始游戏通过串口输出“游戏开始”,将gameStarted设置为true以标记游戏已经开始,重置得分score为0,记录游戏开始的时间gameStartTime为当前毫秒数(使用millis()函数获取),然后暂停1秒以给用户一个视觉或心理上的准备时间。第二部分是游戏激活后的逻辑结构。if(gameStarted && millis() - gameStartTime < gameDuration) {
// 游戏进行中
} else if (gameStarted) {
// 游戏结束
}当游戏已经开始且游戏时间未超过设定的持续时间gameDuration时,执行游戏进行中的逻辑。如果游戏已经开始但游戏时间超过了设定的持续时间gameDuration,执行游戏结束的逻辑。接下来是对于游戏进行中的逻辑和游戏结束的逻辑的详解。
游戏进行中:一旦游戏开始,系统将随机点亮一个LED灯,并给玩家一秒钟的时间来按下对应的按钮。int led = random(0, 3); // 随机选择一个LED
digitalWrite(LEDS, HIGH); // 点亮这个LED
long startTime = millis();
bool buttonPressed = false;// 初始化按钮状态(未被按下)同时记录下点亮LED的时间startTime,并且把buttonpressed的状态设为fasle(初始化),之后进入一个while循环,等待玩家在1秒内按下对应的按钮。while (millis() - startTime < 1000) {
if (digitalRead(BUTTONS) == LOW) {
// 检查是否按下了对应的按钮
buttonPressed = true;
break; // 如果按下了按钮,跳出循环
}如果玩家在1秒内按下了对应的按钮(通过检查BUTTONS是否被按下),则标记buttonPressed为true并跳出循环。while循环结束后,无论是否按下了按钮,都会熄灭LED。if (buttonPressed) {
score++; // 如果按下了按钮,增加得分
Serial.println("得分 +1");
}
delay(200); 如果buttonPressed为true,则增加得分并输出得分增加的消息。最后,使用delay(200)等待200毫秒后继续下一轮游戏。
游戏结束:else if (gameStarted) {
// 如果游戏时间超过一分钟,游戏结束
gameStarted = false;
Serial.print("游戏结束! 你的得分: ");
Serial.println(score); // 通过串口输出得分
delay(3000); // 等待3秒后可以重新开始游戏
}否则如果游戏已经开始但游戏时间超过了设定的持续时间gameDuration,则执行游戏结束的逻辑。将gameStarted设置为false以标记游戏结束,通过串口输出游戏结束的消息和玩家的最终得分,然后暂停3秒,给用户一个重新开始游戏前的缓冲时间。
硬件回顾上拉电阻通常,如果没有输入,将输入引脚引导至已知状态非常有用。这可以通过在输入端添加一个上拉电阻(至+5V)或一个下拉电阻(接地电阻)来实现。这个项目中使用的按键,由于没有内置上拉电阻,则需要在代码中设置引脚为INPUT_PULLUP或使用外部电阻。Arduino的ATmega 芯片内置了 20K 上拉电阻器,可通过软件访问。这些内置上拉电阻可通过将 pinMode() 设置为 INPUT_PULLUP 来访问。这有效地反转了 INPUT 模式的行为,其中 HIGH 表示传感器关闭,LOW 表示传感器打开。
课后练习
尝试用现有的硬件,做一个颜色记忆游戏,实现一个简化版的记忆翻牌游戏,使用两个LED(代表两张牌)和一个按钮。游戏开始时,两个LED随机亮起(模拟翻牌),然后熄灭。玩家需要记住这两个LED的亮起状态,并通过按钮输入来“翻牌”(实际上是重新点亮LED),尝试匹配之前的亮起状态。根据结果配合串口输出“恭喜,你赢了!”;否则,输出“很遗憾,你输了!”。还有更多的玩法等待着你发现。
示例代码
下一课:Arduino入门教程21--数码管摇骰子「DFR0100」
页:
[1]