3 дня с ардуино пытаюсь сделать игру на реакцию

Хочу сделать игру на реакцию когда загорается лампочка посередине надо нажать кнопку и кто быстрее нажал того лампочка загорается то есть победителя. почему то лампочка победителя не загорается прошу помочь

void setup() {
pinMode(11, INPUT);
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(10, INPUT);
pinMode(9, OUTPUT);

}

void loop() {
digitalWrite(9, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
delay(random(5000, 12000));
digitalWrite(9, HIGH);
int right;
int left;
right = digitalRead(11);
left = digitalRead(10);
if (right==1) {digitalWrite(13, HIGH);}
else if (left==1) {digitalWrite(12, HIGH);}
delay(3000);
}

Заранее спасибо хочу подметить что программа никаких ошибок не выявляет

Таким образом сделать игру на реакцию невозможно.
И вообще Ваш код имеет очень мало общего с кодом, который бы соответствовал Вашему описанию.
Расставьте в коде комментарии: что делаете, для чего и какого результата ждете.

Ну и заодно изучите исходник blink without delay. Эти знания Вам обязательно понадобятся, чтобы реализовать свою задумку.

1 лайк

Вот это я понимаю игра в 21 веке - 20 строк и готово … ИИ до этого ещё 1000 лет учиться !!!

1 лайк

Ещё можно попросить ИИ написать код с подробными комментариями и у него поучиться логическим вещам простым.

Не, ему это на полсекунды работы :slight_smile:

Ну, после того, как

поучится :slight_smile:

Диалог с ИИ.

Спойлер

Ты програмист ардуино. Напиши программу и прокомментируй каждую строку. Алгоритм : загорается лампочка через случайный период от 1 до 5 секунд, после загорания лампочки надо нажать одну из трёх кнопок и лампочка соответствующее кнопке должна загореться. Нажатие любой кнопки сбрасывает программну в начальное состояние. Нажатие кнопки раньше загорания первой лампочки приводит к морганию лампочки соответствующей кнопки.

1:59 PM

Конечно! Ниже приведена программа на языке Arduino C++ для описанного тобой алгоритма. Я подробно прокомментирую каждую строку, чтобы было понятно, как всё работает.

Предположим, у нас:

  • 1 лампочка-индикатор ожидания (например, светодиод на пине LED_WAIT) — она загорается случайно через 1–5 секунд.
  • 3 кнопки: BTN1, BTN2, BTN3.
  • 3 лампочки, соответствующие кнопкам: LED1, LED2, LED3.
  • Если нажать кнопку до загорания LED_WAIT — соответствующий LED мигает один раз (например, 200 мс).
  • Если нажать кнопку после загорания LED_WAIT — соответствующий LED загорается и держится, а все сбрасывается через короткую паузу.
  • Любое нажатие кнопки сбрасывает состояние в начало (ожидание нового случайного интервала).

:scroll: Исходный код с комментариями:

// Пины для светодиодов
#define LED_WAIT 13 // “ожидающая” лампочка (обычно встроенный LED на пине 13)
#define LED1 10 // лампочка для кнопки 1
#define LED2 11 // лампочка для кнопки 2
#define LED3 12 // лампочка для кнопки 3

// Пины для кнопок (подключены к GND, используют внутренний подтяжку к VCC)
#define BTN1 2 // кнопка 1
#define BTN2 3 // кнопка 2
#define BTN3 4 // кнопка 3

// Переменные состояния
unsigned long startTime; // время старта текущего цикла (мс)
unsigned long waitTime; // случайный интервал ожидания (1–5 сек → 1000–5000 мс)
bool waitingForLight = true; // флаг: true — ждём, когда загорится LED_WAIT
bool lightIsOn = false; // флаг: true — LED_WAIT уже горит, ждём реакции
bool buttonPressed = false; // чтобы избежать многократной обработки одного нажатия

// Функция инициализации (выполняется один раз при включении или сбросе)
void setup() {
// Инициализация пинов светодиодов как выходов
pinMode(LED_WAIT, OUTPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);

// Инициализация пинов кнопок как входов с подтяжкой к VCC (внутренний резистор)
pinMode(BTN1, INPUT_PULLUP);
pinMode(BTN2, INPUT_PULLUP);
pinMode(BTN3, INPUT_PULLUP);

// Запуск генератора случайных чисел (используем шум с аналогового пина для инициализации)
randomSeed(analogRead(A0)); // A0 не подключён — берём шум как источник энтропии

// Сброс всех светодиодов в выключенное состояние
digitalWrite(LED_WAIT, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);

// Начинаем первую сессию: засекаем время старта
resetGame(); // функция ниже реализует сброс в начальное состояние
}

// Главный цикл (выполняется бесконечно)
void loop() {
// Читаем состояние кнопок
bool btn1Pressed = digitalRead(BTN1) == LOW; // кнопки активны при LOW (из-за INPUT_PULLUP)
bool btn2Pressed = digitalRead(BTN2) == LOW;
bool btn3Pressed = digitalRead(BTN3) == LOW;

// Текущее время в миллисекундах
unsigned long currentTime = millis();

// === Этап 1: Ожидаем случайного интервала, пока не загорится LED_WAIT ===
if (waitingForLight) {
// Проверяем, прошло ли уже нужное время?
if (currentTime - startTime >= waitTime) {
// Время вышло — зажигаем “ожидающую” лампочку
digitalWrite(LED_WAIT, HIGH);
lightIsOn = true; // теперь ждём реакции игрока
waitingForLight = false; // больше не в режиме ожидания старта
}
// Если нажали кнопку ДО загорания — моргаем соответствующим LED
if ((btn1Pressed || btn2Pressed || btn3Pressed) && !buttonPressed) {
buttonPressed = true; // флаг — нажатие зафиксировано (антидребезг)

  // Выключаем ожидание, чтобы не реагировать повторно
  waitingForLight = false;

  // Моргаем нужным светодиодом
  if (btn1Pressed) blinkLED(LED1);
  if (btn2Pressed) blinkLED(LED2);
  if (btn3Pressed) blinkLED(LED3);

  // Сразу сбрасываем игру (т.к. нажатие — досрочное)
  delay(500); // пауза, чтобы игрок увидел моргание
  resetGame();
}

}

// === Этап 2: LED_WAIT горит — ждём нажатия кнопки ===
else if (lightIsOn) {
// Если нажали любую кнопку — загорается соответствующий LED и сброс
if ((btn1Pressed || btn2Pressed || btn3Pressed) && !buttonPressed) {
buttonPressed = true;

  // Гасим индикатор ожидания
  digitalWrite(LED_WAIT, LOW);

  // Включаем нужный LED (и оставляем его включённым на 1 сек, затем гасим)
  if (btn1Pressed) digitalWrite(LED1, HIGH);
  if (btn2Pressed) digitalWrite(LED2, HIGH);
  if (btn3Pressed) digitalWrite(LED3, HIGH);

  // Даём игроку увидеть результат
  delay(1000); // держим LED включённым 1 секунду

  // Гасим все LED и сбрасываем игру
  resetGame();
}

}

// === Антидребезг: когда кнопки отпущены — сбрасываем флаг buttonPressed ===
if (!btn1Pressed && !btn2Pressed && !btn3Pressed) {
buttonPressed = false;
}

// Небольшая задержка для снижения нагрузки (необязательна, но полезна)
delay(10);
}

// Функция: моргнуть светодиодом один раз (200 мс вкл → 200 мс выкл)
void blinkLED(int pin) {
digitalWrite(pin, HIGH);
delay(200);
digitalWrite(pin, LOW);
delay(200);
}

// Функция: сброс игры в начальное состояние
void resetGame() {
// Гасим всё
digitalWrite(LED_WAIT, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);

// Генерируем новое случайное время ожидания: от 1000 до 5000 мс
waitTime = random(1000, 5001); // random(max) — НЕ включает max, поэтому 5001

// Запоминаем текущее время как старт нового раунда
startTime = millis();

// Возвращаем флаги в исходное состояние
waitingForLight = true;
lightIsOn = false;
buttonPressed = false; // на случай, если сброс вызван не через отпускание кнопок
}

:wrench: Подключение в реальности:

Элемент Пин Ардуино Особенности
Светодиод WAIT 13 Встроенный LED на многих платах
LED1 10 Через резистор 220 Ом на GND
LED2 11 То же
LED3 12 То же
Кнопка 1 2 Один вывод → GND, второй → пин. Используется INPUT_PULLUP
Кнопка 2 3 То же
Кнопка 3 4 То же

:warning: Кнопки должны замыкать пин на GND. Внутренняя подтяжка (INPUT_PULLUP) делает пин HIGH при отпущенной кнопке, и LOW при нажатой.


:light_bulb: Как можно улучшить:

  • Заменить delay() на millis()-логику для полноценной неблокирующей работы (если в будущем добавишь таймеры, звук и т.п.).
  • Добавить счётчик реакций, рекорды и т.д.
  • Использовать библиотеку Bounce2 для надёжной антидребёжной обработки кнопок.
1 лайк

Я бы по другому промпт составлял исходный. На два игрока, три светодиода, две кнопки, кнопка ресет - перезапуск игрового цикла.

…ну и видно будет как всегда, что код избыточным получится.

// Определение констант для пинов
const int CENTER_LED = 9; // Центральная лампочка (сигнал)
const int LED_P1 = 12; // Лампочка игрока 1
const int LED_P2 = 13; // Лампочка игрока 2
const int BUTTON_P1 = 10; // Кнопка игрока 1
const int BUTTON_P2 = 11; // Кнопка игрока 2

// Переменные состояния игры
bool gameActive = false; // Флаг активности игры (true = идет раунд)
unsigned long reactionStartTime; // Время начала раунда (момент зажигания центральной лампы)
const unsigned long maxReactionTime = 3000; // Максимальное время реакции (3 секунды)

void setup() {
// Настройка пинов как входов/выходов
pinMode(CENTER_LED, OUTPUT);
pinMode(LED_P1, OUTPUT);
pinMode(LED_P2, OUTPUT);
pinMode(BUTTON_P1, INPUT);
pinMode(BUTTON_P2, INPUT);

// Изначально все лампочки выключены
digitalWrite(CENTER_LED, LOW);
digitalWrite(LED_P1, LOW);
digitalWrite(LED_P2, LOW);
}

void loop() {
// Если игра не активна, начинаем новый раунд
if (!gameActive) {
startNewRound();
}

// Если игра активна, проверяем нажатия кнопок
if (gameActive) {
checkButtons();

// Проверка таймаута: если прошло больше maxReactionTime, завершаем раунд
if (millis() - reactionStartTime > maxReactionTime) {
gameActive = false; // Завершаем раунд
delay(1000); // Пауза 1 секунда перед следующим раундом
}
}
}

// Функция начала нового раунда
void startNewRound() {
// Гасим все лампочки перед началом
digitalWrite(CENTER_LED, LOW);
digitalWrite(LED_P1, LOW);
digitalWrite(LED_P2, LOW);

// Случайная задержка перед зажиганием центральной лампы (от 3 до 8 секунд)
delay(random(3000, 8000));

// Зажигаем центральную лампочку - сигнал к началу реакции
digitalWrite(CENTER_LED, HIGH);

// Запоминаем время начала раунда
reactionStartTime = millis();

// Активируем игру (теперь можно нажимать кнопки)
gameActive = true;
}

// Функция проверки нажатий кнопок
void checkButtons() {
// Проверка кнопки игрока 1
if (digitalRead(BUTTON_P1) == HIGH) {
digitalWrite(LED_P1, HIGH); // Зажигаем лампочку игрока 1
digitalWrite(CENTER_LED, LOW); // Гасим центральную лампу
gameActive = false; // Завершаем раунд
delay(3000); // Показываем победителя 3 секунды
return; // Выходим из функции
}

// Проверка кнопки игрока 2
if (digitalRead(BUTTON_P2) == HIGH) {
digitalWrite(LED_P2, HIGH); // Зажигаем лампочку игрока 2
digitalWrite(CENTER_LED, LOW); // Гасим центральную лампу
gameActive = false; // Завершаем раунд
delay(3000); // Показываем победителя 3 секунды
return; // Выходим из функции
}
}

а почему это плохо работает, и один игрок получит преимущества над другим, это может подскажет кто то еще…

Бабос, скучно с Вами. ИИ и мы дрюкать умеем.

```

#include <Arduino.h>

// Абстрактный класс Игрок
class Player
{
protected:
	int ledPin;
	int buttonPin;
	bool ledState;

public:
	Player(int ledPin, int buttonPin)
		: ledPin(ledPin), buttonPin(buttonPin), ledState(false)
	{
		pinMode(ledPin, OUTPUT);
		pinMode(buttonPin, INPUT);
		digitalWrite(ledPin, LOW);
	}

	virtual ~Player() {}

	// Проверить состояние кнопки 
	virtual bool isButtonPressed() const
	{
		return digitalRead(buttonPin) == HIGH;
	}

	// Включить светодиод игрока
	virtual void lightUp()
	{
		digitalWrite(ledPin, HIGH);
		ledState = true;
	}

	// Выключить светодиод игрока
	virtual void lightOff()
	{
		digitalWrite(ledPin, LOW);
		ledState = false;
	}

	bool isLit() const
	{
		return ledState;
	}
};

// Игрок 1 
class Player1 : public Player
{
public:
	Player1(int ledPin, int buttonPin) : Player(ledPin, buttonPin) {}
};

// Игрок 2
class Player2 : public Player
{
public:
	Player2(int ledPin, int buttonPin) : Player(ledPin, buttonPin) {}
};

// Класс игры
class ReactionGame
{
private:
	const int centerLedPin;
	Player &player1;
	Player &player2;
	bool gameActive;
	unsigned long reactionStartTime;
	const unsigned long maxReactionTime;

public:
	ReactionGame(int centerPin, Player &p1, Player &p2, unsigned long maxTime = 3000)
		: centerLedPin(centerPin), player1(p1), player2(p2),
		  gameActive(false), reactionStartTime(0), maxReactionTime(maxTime)
	{
		pinMode(centerLedPin, OUTPUT);
		digitalWrite(centerLedPin, LOW);
	}

	void startNewRound()
	{
		// Выключаем все LED
		digitalWrite(centerLedPin, LOW);
		player1.lightOff();
		player2.lightOff();

		// Случайная задержка 3-8 секунд
		delay(random(3000, 8000));

		// Зажигаем центральный LED
		digitalWrite(centerLedPin, HIGH);
		reactionStartTime = millis();
		gameActive = true;
	}

	void checkButtons()
	{
		// Проверяем кнопку игрока 1
		if (player1.isButtonPressed())
		{
			player1.lightUp();
			digitalWrite(centerLedPin, LOW);
			gameActive = false;
			delay(3000);
		}
		// Проверяем кнопку игрока 2
		else if (player2.isButtonPressed())
		{
			player2.lightUp();
			digitalWrite(centerLedPin, LOW);
			gameActive = false;
			delay(3000);
		}
	}

	void update()
	{
		if (!gameActive)
		{
			startNewRound();
		}
		else
		{
			checkButtons();

			if (millis() - reactionStartTime > maxReactionTime)
			{
				// Время вышло, завершаем раунд
				gameActive = false;
				delay(1000); // Пауза перед следующим раундом
			}
		}
	}
};

// Создаем игроков и игру
Player1 p1(12, 10);
Player2 p2(13, 11);
ReactionGame game(9, p1, p2);

void setup()
{
	randomSeed(analogRead(A0)); // Инициализируем генератор случайных чисел
}

void loop()
{
	game.update();
}

А вопрошающему нужно было сказать, что его программа просто не ждёт нажатия кнопки.

Читеры, даете приоритет при опросе, нада порт читать, а уж потом с пинами разбираться.

2 лайка

думаете надо было freertos использовать ?)))