#include <LiquidCrystal.h>
#define START 0
#define WAIT 1
#define MEASURE 2
#define CHEATER 3
int8_t g_STATE = START;
LiquidCrystal lcd(12,11,6,5,4,3);
const int8_t g_led_pin = 7;
const int8_t g_button_pin = 2;
const int8_t g_pot_pin = A0; // 电位计连接的引脚
// needed variables
int16_t g_waiting_time;
int16_t g_measure_start;
int16_t g_reaction_time;
int16_t g_cheat_treshhold = 200;
volatile int16_t g_button_press_time;
volatile bool g_b_is_button_pressed = false;
int16_t g_pot_value; // 电位计读数值
int16_t g_pot_min = 0; // 电位计最小值
int16_t g_pot_max = 1023; // 电位计最大值
int16_t g_cheat_threshold_min = 100; // 作弊阈值的最小值
int16_t g_cheat_threshold_max = 500; // 作弊阈值的最大值
/* set the button to indicate it has been pressed and save time */
void button_interrupt() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// 50 ms debounce time
if (interrupt_time - last_interrupt_time > 50) {
g_button_press_time = interrupt_time;
g_b_is_button_pressed = true;
digitalWrite(g_led_pin, LOW);
}
last_interrupt_time = interrupt_time;
}
void
setup()
{
lcd.begin(16,2);
pinMode(g_led_pin, OUTPUT);
pinMode(g_button_pin, INPUT_PULLUP);
pinMode(g_pot_pin, INPUT); // 设置电位计引脚为输入
attachInterrupt(digitalPinToInterrupt(g_button_pin), button_interrupt, FALLING);
}
void
loop()
{
// 读取电位计的值
g_pot_value = analogRead(g_pot_pin);
// 将电位计的值映射到作弊阈值的范围内
g_cheat_treshhold = map(g_pot_value, g_pot_min, g_pot_max, g_cheat_threshold_min, g_cheat_threshold_max);
switch (g_STATE){
case(START):
lcd.clear();
lcd.setCursor(0,0);
lcd.print("press button to");
lcd.setCursor(0,1);
lcd.print("start");
while (!g_b_is_button_pressed)
{
}
g_STATE = WAIT;
break;
case(WAIT):
lcd.clear();
lcd.setCursor(0,0);
lcd.print("The game started!");
g_waiting_time = random(2000,5000);
for (int16_t msec = 0; msec < g_waiting_time; msec++)
{
delay(1);
// check if the button is pressed
// if pressed then cheating has occured
if (g_b_is_button_pressed)
{
g_STATE = CHEATER;
break;
}
}
// if cheating occurred then break and start over
if (CHEATER == g_STATE)
{
break;
}
g_STATE = MEASURE;
break;
case(MEASURE):
// light up led and tell to press the button, save start time
lcd.clear();
lcd.setCursor(0,0);
digitalWrite(g_led_pin, HIGH);
lcd.print("PRESS BUTTON!");
g_measure_start = millis();
while(!g_b_is_button_pressed)
{
// wait for the button press
}
g_reaction_time = g_button_press_time - g_measure_start;
// if reactionTime is too low, cheating has occrred
if (g_reaction_time < g_cheat_treshhold)
{
g_STATE = CHEATER;
break;
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Your time (ms)");
lcd.setCursor(0,1);
lcd.print(g_reaction_time);
delay(2500);
g_STATE = START;
break;
case(CHEATER):
lcd.clear();
lcd.setCursor(0,0);
lcd.print("CHEATER!");
delay(2500);
g_STATE = START;
break;
default:
lcd.clear();
lcd.setCursor(0,0);
lcd.print("FAILURE");
break;
}
g_b_is_button_pressed = false;
}