玩法:
先按「歸零」按鈕
選擇「盲測模式」或「正常模式」後,倒數三秒開始計時
兩玩家按下按鈕,最接近十秒者獲勝
PS. 「盲測模式」會於計時三秒後,數字亂跳。
材料:
1. Arduino Nano V3.0(或UNO) https://tw.shp.ee/whi2Wsf
2. 八位七段顯示器模組 https://tw.shp.ee/P7hBm7s 教學:https://www.x-family.com.tw/?p=6226
3. 螺旋式 5V 帶燈按鈕 x2 https://tw.shp.ee/VNjBLoL
4. 12mm圓形重置按鈕開關 https://tw.shp.ee/QSLbYV8
Arduino 程式碼`:
#include "LedControl.h"
#include "OneButton.h" //使用單按鈕進行多用途輸入,檢測按鈕單擊、雙擊和長按事件
LedControl lc=LedControl(4,6,5,1); //MAX7219 8位七段顯示器模組DIN,Clk,LOAD,No
int btnPinRST=8; //重置腳位
int btnPin1=7; //玩家1按鈕腳位
int btnPin2=9; //玩家2按鈕腳位
int State = 0; //程式執行狀態 0: 初始狀態 1: 倒數狀態 2: 計時狀態 3: 判斷輸贏狀態 4:待機狀態
int playMode=0; //0:雙人模式 1:單人模式
long StartTime = 0; //開始計時時間
long ElapsedTime = 0; //經過時間
int playTime1; //玩家1計時時間
int playTime2; //玩家2計時時間
int stopFlag1=0; //玩家1是否按下停止鈕
int stopFlag2=0; //玩家2是否按下停止鈕
int temp1,temp2;
OneButton buttonRST(btnPinRST, true); //1.單按鈕多用途_腳位設定(啟用內部上拉電阻)
OneButton buttonA(btnPin1, true);
OneButton buttonB(btnPin2, true);
void clickRST(){ //2.單按鈕多用途_事件程序
State=0;
stopFlag1=1; stopFlag2=1;
}
void clickA(){ //玩家1按鈕
if(State==0) {playMode=0; State = 1; } //當狀態0(State=0)時,為模式選擇
if (State == 2) {displayNum1(playTime1); stopFlag1=1;}
}
void clickB(){ //玩家2按鈕
if(State==0) {playMode=1; State = 1; } //當狀態0(State=0)時,為模式選擇
if(State==2) {displayNum2(playTime2); stopFlag2=1;}
}
void setup(){
Serial.begin(9600);
buttonRST.attachClick(clickRST); //3.綁定單按鈕多用途_事件(單擊)
buttonA.attachClick(clickA);
buttonB.attachClick(clickB);
// Initialize the MAX7219 device
lc.shutdown(0,false); // Enable display
lc.setIntensity(0,10); // Set brightness level (0 is min, 15 is max)
lc.clearDisplay(0); // Clear display register
}
void loop(){
buttonRST.tick(); //4.單按鈕多用途_檢測按钮事件
buttonA.tick();
buttonB.tick();
//初始狀態
if (State == 0) {
stopFlag1=0;stopFlag2=0;
displayNum1(0); lc.setLed(0,2,0,1); //顯示小數點
displayNum2(0); lc.setLed(0,6,0,1); //顯示小數點
}
//倒數狀態
if (State == 1) {
countdown(); //倒數三秒計時
StartTime = millis(); //記錄開始時間
State = 2; //設定開始計時並偵測按鈕
}
//計時狀態
if (State == 2) {
if(stopFlag1==1 && stopFlag2==1) State = 3; //兩按鈕皆已完成按下動作,進入判斷輸贏狀態
ElapsedTime = (millis() - StartTime);
ElapsedTime=ElapsedTime/10; //偵測為毫秒(0.001秒),但只需顯示到小數後2位(xx.xx)
if (ElapsedTime > 9999) clickRST(); //超過99.99秒未完成,自動歸零
if(stopFlag1==0)playTime1=ElapsedTime; //當玩家1尚未按下停止,則記錄目前經過時間
if(stopFlag2==0)playTime2=ElapsedTime;
//當進入盲測模式時,超過三秒關閉前五位數字都顯示個位數
if (playMode==1 && ElapsedTime>300){
temp2=1;
temp1=ElapsedTime % 10 ; //取經過時間的個位數(0.01秒)
temp2=temp1*10+temp1;
temp2=temp2*10+temp1;
temp2=temp2*10+temp1;
if(stopFlag1==0)displayNum1(temp2);else {displayNum1(playTime1);lc.setLed(0,2,0,1);} //當玩家1尚未按下停止,則顯示經過時間個位數x4
if(stopFlag2==0)displayNum2(temp2);else {displayNum2(playTime2);lc.setLed(0,6,0,1);}
}else{
lc.setLed(0,2,0,1); //顯示小數點
lc.setLed(0,6,0,1); //顯示小數點
displayNum1(playTime1);
displayNum2(playTime2);
}
}
//判斷輸贏狀態
if (State == 3) {
if(playTime1<1000) temp1=1000-playTime1; else temp1=playTime1-1000; //計算玩家1距離10.00秒的相差值(取正值)
if(playTime2<1000) temp2=1000-playTime2; else temp2=playTime2-1000;
displayNum1(playTime1); lc.setLed(0,2,0,1); //顯示小數點
displayNum2(playTime2); lc.setLed(0,6,0,1); //顯示小數點
for(int k=0;k<3;k++){ //贏家閃爍三次
if(temp1==temp2){ //平手
lc.clearDisplay(0); // 清除螢幕
delay(300);
displayNum1(playTime1); lc.setLed(0,2,0,1); //顯示小數點
displayNum2(playTime2); lc.setLed(0,6,0,1); //顯示小數點
delay(500);
}else if(temp1<temp2) { //玩家1贏
lc.clearDisplay(0); // 清除螢幕
displayNum2(playTime2); lc.setLed(0,6,0,1); //顯示小數點
delay(300);
displayNum1(playTime1); lc.setLed(0,2,0,1); //顯示小數點
delay(500);
}else{ //玩家2贏
lc.clearDisplay(0); // 清除螢幕
displayNum1(playTime1); lc.setLed(0,2,0,1); //顯示小數點
delay(300);
displayNum2(playTime2); lc.setLed(0,6,0,1); //顯示小數點
delay(500);
}
}
State =4;//進入待機模式
}
}
void countdown() {
displayNum1(3333);displayNum2(3333);
lc.setLed(0,2,0,0); //隱藏小數點
lc.setLed(0,6,0,0); //隱藏小數點
delay(1000);
displayNum1(2222);displayNum2(2222);
delay(1000);
displayNum1(1111);displayNum2(1111);
delay(1000);
lc.setLed(0,2,0,1); //顯示小數點
lc.setLed(0,6,0,1); //顯示小數點
}
//自定函式 顯示數字
void displayNum1(int code){ //玩家1
int code1,code2,code3,code4;
code1 = code / 1000 % 10 ; //取千位數
code2 = code / 100 % 10 ; //取百位數
code3 = code / 10 % 10 ; //取十位數
code4 = code % 10; //取個位數 % =>求餘數
lc.setDigit(0,0,code4,false);
lc.setDigit(0,1,code3,false);
lc.setDigit(0,2,code2,false);
lc.setDigit(0,3,code1,false);
}
void displayNum2(int code){ //玩家2
int code1,code2,code3,code4;
code1 = code / 1000 % 10 ;
code2 = code / 100 % 10 ;
code3 = code / 10 % 10 ;
code4 = code % 10;
lc.setDigit(0,4,code4,false);
lc.setDigit(0,5,code3,false);
lc.setDigit(0,6,code2,false);
lc.setDigit(0,7,code1,false);
}
使用bDesigner製作「單人十秒挑戰機」:
材料:
1. Arduino Nano V3.0(或UNO) https://tw.shp.ee/whi2Wsf
2. 4位數字顯示模組 TM1637 https://tw.shp.ee/fadgXFS
3. 螺旋式 5V 帶燈按鈕 https://tw.shp.ee/VNjBLoL
TinkerCAD 製作「單人十秒挑戰機」
接線圖:
#include "Adafruit_LEDBackpack.h"
int state=0; //0:初始模式 1:計時模式 2:等待模式
int btn,old_btn=0;
Adafruit_7segment led_display1 = Adafruit_7segment();
unsigned long startTime = 0; // 記錄計時開始時間
unsigned long elapsedTime = 0; // 記錄經過時間
void setup()
{
led_display1.begin(112);
pinMode(8, INPUT);
}
void loop()
{
int dispTime;
btn=digitalRead(8);
if(btn&&btn!=old_btn){ //按下按鈕時
if(state==1)led_display1.blinkRate(1);//停止計時,LED閃爍
state++; //切換至下一模式
if(state>2)state=0;
startTime=millis();
}
if(state==0){ //初始開始
startTime=0;
led_display1.println(0);
led_display1.blinkRate(0);//不閃爍
led_display1.writeDisplay();
}
if(state==1){ //開始計時
elapsedTime=millis()-startTime;//經過時間
dispTime=elapsedTime/10;//取小數後2位
led_display1.println(dispTime);
led_display1.drawColon(true); //顯示冒號
led_display1.writeDisplay();
}
old_btn=btn;
delay(10);
}
附錄: 科技教育創意實作競賽 [資訊科技組] 競賽 教學影片 https://reurl.cc/9b7dNX