/*
1. 保留LCD顯示
2. 增加二位數七段顯示器
3. 按下Start Key 開始遊戲
4. 再次按下Start Key 分數歸零
5. 所有通道點亮時自動重新執行亂數取通道
6. 修正LCD清除點數問題
*/
#include <Wire.h> // I2C程式庫
#include <LiquidCrystal_I2C.h> // LCD_I2C模組程式庫
// LCD I2C位址,默認為0x27或0x3F,依據背板的晶片不同而有差異,16、2為LCD顯示器大小。
LiquidCrystal_I2C lcd(0x27, 16, 2);
int ledPin[]={2,3,4,5,6};
int TONE_PIN = 7; // 蜂鳴器的接腳
int Startpin = 14; // Start 的接腳 A0
int ButtonPin[]={8,9,10,11,12};
boolean ledState[]={0,0,0,0,0};
int n[5]={};
int m[]={1,2,3}; // 通道數
unsigned long time_now;
int i,j,k,a;
int score=0;
int Hello=0;
int Rerandom=LOW;
// These are connected to 74HC595 shift register (used to show game score):
const int LOAD_PIN = A2; // 74HC595 pin 12
const int SDI_PIN = A1; // 74HC595pin 14
const int SCLK_PIN = A3; // 74HC595 pin 11
void setup() {
pinMode(TONE_PIN, OUTPUT); //設定蜂鳴器的PIN腳為輸出
// 初始化LCD
lcd.init();
lcd.backlight();
Serial.begin(9600);
for(int i=0;i<5;i++){
pinMode(ledPin[i], OUTPUT);
pinMode(ButtonPin[i], INPUT_PULLUP);
}
pinMode(Startpin, INPUT_PULLUP);
pinMode(LOAD_PIN, OUTPUT);
pinMode(SCLK_PIN, OUTPUT);
pinMode(SDI_PIN, OUTPUT);
}
/* Digit table for the 7-segment display */
const uint8_t digitTable[] = {
0b11000000,
0b11111001,
0b10100100,
0b10110000,
0b10011001,
0b10010010,
0b10000010,
0b11111000,
0b10000000,
0b10010000,
};
const uint8_t DASH = 0b10111111;
void sendScore(uint8_t high, uint8_t low) {
digitalWrite(LOAD_PIN, LOW);
shiftOut(SDI_PIN, SCLK_PIN, MSBFIRST, low);
shiftOut(SDI_PIN, SCLK_PIN, MSBFIRST, high);
digitalWrite(LOAD_PIN, HIGH);
}
void displayScore() {
int high = score % 100 / 10;
int low = score % 10;
//sendScore(high ? digitTable[high] : 0xff, digitTable[low]);
sendScore(digitTable[high], digitTable[low]);
}
void loop()
{
//跑馬燈
while(digitalRead(Startpin)!=LOW && a==LOW ){
Serial.println(Hello); //將Hello顯示在LCD上
lcd.setCursor(6, 0); // 從第一排的第6個位置開始顯示
lcd.print("Hello");
sendScore(DASH, DASH); //七段顯示器顯示 "--"
for(int i=0;i<5;i++){
digitalWrite(ledPin[i],HIGH);
ledState[i]=HIGH;
delay(200);
digitalWrite(ledPin[i],LOW);
delay(50);
if(digitalRead(Startpin)==LOW){ //Start 鍵按下即跳出
Rerandom=HIGH;
break; }
}
}
// 2023/01/17
if(digitalRead(Startpin)==LOW ) //Start 鍵是否按下
{
lcd.setCursor(4, 0);
lcd.print("SCORE:0 ");
score=0; //計分歸零
Rerandom=HIGH; //執行亂數取通道
}
//if(digitalRead(Startpin)==LOW || Rerandom==1) //Start 鍵是否按下
if(Rerandom==HIGH) //重新執行亂數取通道 2023/01/17
{
for(i=0;i<2;i++){ //蜂鳴器響聲0.2秒 2次
digitalWrite(TONE_PIN,HIGH);
delay(200);
digitalWrite(TONE_PIN,LOW);
delay(100);
}
//先將所有LED關閉
for(i=0;i<5;i++){
digitalWrite(ledPin[i],LOW);
ledState[i]=LOW;
}
//執行亂數選取,並將選取到的LED點亮
k=m[random(3)]; // 執行亂數選取通道數
for(i=0; i<k; i++){
//for(i=0; i<3; i++){
do{
n[i]=random(5);
for(j=0; j<i; j++){
if(n[i]==n[j]){
break;
}
}
}while(j!=i);
digitalWrite(ledPin[n[i]],HIGH);
ledState[i]=HIGH;
}
a=HIGH;
delay(200);
}
//檢查選取到的LED對應按鈕是否被按下,若被按下則分數加1
for(i=0;i<3;i++){
if(digitalRead(ButtonPin[n[i]])==LOW&&ledState[i]==HIGH){
digitalWrite(TONE_PIN,HIGH); //蜂鳴器就響了
delay(100); //蜂鳴器響聲持續0.1秒
digitalWrite(ledPin[n[i]],LOW);
digitalWrite(TONE_PIN,LOW); //蜂鳴器就不響
ledState[i]=LOW;
switch(k){
case 1:
score=score+3;
break;
case 2:
score=score+2;
break;
case 3:
score++;
break;
}
}
}
// if(digitalRead(Startpin)==LOW&&digitalRead(12)==LOW){ //歸零 D12+A0
// score=0;}
//將分數顯示在LCD上
Serial.println(score);
lcd.setCursor(4, 0); // 從第一排的第三個位置開始顯示
lcd.print("SCORE:");
lcd.print(score);
displayScore(); // 分數顯示在七段顯示器上
//確認通道是否都點亮, 如果都點亮就重新取 亂數通道
if((ledState[0]| ledState[1]| ledState[2]| ledState[3]| ledState[4])==LOW) Rerandom=HIGH;
else Rerandom=LOW;
}