项目代码
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Initialize the LCD, set the address to 0x27 or 0x3F depending on your module
LiquidCrystal_I2C lcd(0x27, 16, 2); // 16 columns, 2 rows
// Pin setup
int ledPins[] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; // Pins for the 8 LEDs
int buttonPin = 2; // Pin for the button
int buzzerPin = 3; // Pin for the piezo buzzer
int middleLED = 5; // The middle LED position (adjust if needed)
int direction = 1; // Initial direction (1 = forward, -1 = backward)
int currentLED = 0; // Start at the first LED
int level = 1; // Start at level 1
int delayTime = 300; // Initial delay time for LED movement (in ms)
int score = 0; // Player score
int levelTime = 10; // Time allowed for each level (in seconds)
unsigned long startTime; // Time when the level starts
unsigned long lastMoveTime = 0; // Time when the LEDs last moved
unsigned long lastToneTime = 0; // Time to control the duration of the tone
unsigned long buttonDebounceTime = 0; // For button debouncing
unsigned long debounceDelay = 50; // Debounce delay in milliseconds
int lastRemainingTime = -1; // To track the last displayed time
int lastLevel = -1; // To track the last displayed level
int lastScore = -1; // To track the last displayed score
bool buttonPressed = false;
bool tonePlaying = false; // Flag to indicate whether the tone is currently playing
bool gameEnded = false; // Flag to indicate the end of the game
// Function to play a tone non-blocking
void startTone(int frequency) {
tone(buzzerPin, frequency); // Start playing the tone
tonePlaying = true; // Set tone playing flag
lastToneTime = millis(); // Record when the tone started
}
void stopTone() {
noTone(buzzerPin); // Stop playing the tone
tonePlaying = false; // Reset tone playing flag
}
void setup() {
// Initialize the LCD
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("HUNTER Game");
delay(2000); // Display the welcome message for 2 seconds
// Pin configurations
for (int i = 0; i < 10; i++) {
pinMode(ledPins[i], OUTPUT); // Set all LED pins as outputs
}
pinMode(buttonPin, INPUT_PULLUP); // Set button pin as input with pullup
pinMode(buzzerPin, OUTPUT); // Set buzzer pin as output
Serial.begin(9600); // Start serial for debugging
Serial.println("Welcome to the Knight Rider Hunter Game!");
lcd.clear();
displayStatus(); // Display the initial level, score, and time
startTime = millis(); // Record when the level starts
lastMoveTime = millis(); // Initialize the last move time
}
void loop() {
// If the game has ended, stop further operations
if (gameEnded) {
return;
}
// Check if the timer has expired
unsigned long elapsedTime = (millis() - startTime) / 1000;
int remainingTime = levelTime - elapsedTime;
// If time has run out, end the game
if (remainingTime <= 0) {
endGame(); // Call the function to end the game
return; // Stop further execution
}
// Handle LED movement (non-blocking using millis)
if (millis() - lastMoveTime >= delayTime) {
moveLED();
lastMoveTime = millis(); // Reset the last move time
startTone(1000); // Start playing the 1000Hz tone when moving LED
}
// Stop the tone after 50ms
if (tonePlaying && millis() - lastToneTime >= 50) {
stopTone(); // Stop the tone after 50ms
}
// Check if the button is pressed (with debouncing)
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW && millis() - buttonDebounceTime > debounceDelay) {
buttonDebounceTime = millis(); // Reset debounce timer
if (currentLED == middleLED) {
Serial.println("You win this level!");
score++; // Increase score for a successful hit
startTone(2000); // Play victory tone
delay(500); // Play for 500ms
stopTone();
levelUp(); // Go to the next level
} else {
Serial.println("Missed! Try again.");
startTone(500); // Play fail sound
delay(300); // Play for 300ms
stopTone();
}
delay(500); // Short pause after button press
}
// Update LCD with the remaining time and score only if there's a change
if (remainingTime != lastRemainingTime || level != lastLevel || score != lastScore) {
displayStatus();
lastRemainingTime = remainingTime;
lastLevel = level;
lastScore = score;
}
}
// Function to move the LEDs
void moveLED() {
// Turn off all LEDs
for (int i = 0; i < 10; i++) {
digitalWrite(ledPins[i], LOW);
}
// Light up the current LED
digitalWrite(ledPins[currentLED], HIGH);
// Move the LED in the current direction
currentLED += direction;
// Reverse direction if we reach the end of the LED array
if (currentLED == 9 || currentLED == 0) {
direction = -direction;
}
}
// Function to advance to the next level
void levelUp() {
level++; // Increase the level
delayTime -= 30; // Decrease delay time to make LEDs move faster
// Ensure delayTime doesn't go below a certain threshold (e.g., 50 ms)
if (delayTime < 50) {
delayTime = 50;
}
Serial.print("Level Up! Now at Level: ");
Serial.println(level);
Serial.print("New LED Speed (ms): ");
Serial.println(delayTime);
// Play level-up sound
startTone(1500); // Play a tone at 1.5kHz
delay(300); // Play for 300ms
stopTone();
delay(1000); // Give a 1-second pause before starting the next level
// Reset the timer for the next level
startTime = millis();
}
// Function to display the current level, score, and remaining time
void displayStatus() {
// Calculate the remaining time in seconds
unsigned long elapsedTime = (millis() - startTime) / 1000; // Convert to seconds
int remainingTime = levelTime - elapsedTime; // Calculate the remaining time
// Ensure the remaining time does not go negative
if (remainingTime < 0) {
remainingTime = 0;
}
lcd.setCursor(0, 0);
lcd.print("Lvl:");
lcd.print(level);
lcd.setCursor(6, 0);
lcd.print("Time:");
lcd.print(remainingTime); // Correctly print the remaining time in seconds
// Clear any leftover characters by overwriting with a space
if (remainingTime < 10) {
lcd.print(" "); // Overwrite the extra digit when remainingTime is a single digit
}
lcd.setCursor(0, 1);
lcd.print("Score:");
lcd.print(score);
}
// Function to end the game when the timer runs out
void endGame() {
gameEnded = true; // Set the flag to end the game
// Turn off all LEDs
for (int i = 0; i < 8; i++) {
digitalWrite(ledPins[i], LOW);
}
// Display "End Game" and the final score on the LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("End Game");
lcd.setCursor(0, 1);
lcd.print("Score:");
lcd.print(score);
// Play a sound to indicate the game has ended
startTone(300); // Play a low tone
delay(1000); // Play for 1 second
stopTone();
// Wait for 3 seconds before starting a new game
delay(3000);
// Restart the game
resetGame();
}
// Function to reset the game and start a new one
void resetGame() {
gameEnded = false; // Reset the game end flag
score = 0; // Reset the score to 0
level = 1; // Reset the level to 1
delayTime = 300; // Reset the delay time for LED movement
startTime = millis(); // Reset the timer
// Clear the LCD and display the initial status
lcd.clear();
displayStatus();
Serial.println("New game started!");
// Restart the LED movement immediately
lastMoveTime = millis();
}
复制代码