はじめに
あの古典的なサイモンセイズゲームを覚えていますか?これはArduinoで配列、ステートマシン、ユーザー入力処理を学ぶのに最適なプロジェクトです。このチュートリアルでは、4つのLEDと4つのプッシュボタンを使った完全に機能するサイモンセイズゲームを、すべてブラウザ上のVelxioでシミュレーションしながら構築します。ハードウェアは不要です!

回路の解説
コンポーネントとその接続方法を見てみましょう。
コンポーネント
| コンポーネント | ID | 目的 |
|---|---|---|
| Arduino Uno | arduino-uno | ゲームの頭脳 |
| 赤色LED | led-red | 赤色シーケンスの出力 |
| 緑色LED | led-green | 緑色シーケンスの出力 |
| 青色LED | led-blue | 青色シーケンスの出力 |
| 黄色LED | led-yellow | 黄色シーケンスの出力 |
| 赤色ボタン | button-red | 赤色のユーザー入力 |
| 緑色ボタン | button-green | 緑色のユーザー入力 |
| 青色ボタン | button-blue | 青色のユーザー入力 |
| 黄色ボタン | button-yellow | 黄色のユーザー入力 |
配線
各LEDのアノード(A)はArduinoのデジタルピンに接続し、カソード(C)は電流制限抵抗(内部でシミュレーション)を介してGNDに接続します。ボタンは、一方の端子(1.l)をデジタルピンに、もう一方の端子(2.l)をGNDに配線し、Arduinoの内部プルアップ抵抗を使用します。
- 赤色LED: ピン8(赤色ワイヤ)をアノードに、カソードをGND(黒色ワイヤ)に接続。
- 緑色LED: ピン9(緑色ワイヤ)をアノードに、カソードをGNDに接続。
- 青色LED: ピン10(青色ワイヤ)をアノードに、カソードをGNDに接続。
- 黄色LED: ピン11(黄色ワイヤ)をアノードに、カソードをGNDに接続。
- 赤色ボタン: ピン2(水色ワイヤ)を1.lに、2.lをGNDに接続。
- 緑色ボタン: ピン3(水色ワイヤ)を1.lに、2.lをGNDに接続。
- 青色ボタン: ピン4(水色ワイヤ)を1.lに、2.lをGNDに接続。
- 黄色ボタン: ピン5(水色ワイヤ)を1.lに、2.lをGNDに接続。
すべてのグランド接続はArduinoのGNDピンを共有します。
コードの解説
Velxioでコードエディタを開いて、完全なスケッチを確認してください。

定数と変数
const int LED_PINS[] = {8, 9, 10, 11};
const int BUTTON_PINS[] = {2, 3, 4, 5};
const int NUM_LEDS = 4;
int sequence[100];
int sequenceLength = 0;
int currentStep = 0;
配線に合わせてLEDとボタンピンの配列を定義します。sequenceはランダムなパターン(最大100ステップ)を保存します。sequenceLengthはプレイヤーが繰り返す必要のあるステップ数を追跡し、currentStepはプレイヤーの進行状況を追跡します。
セットアップ
void setup() {
Serial.begin(9600);
for (int i = 0; i < NUM_LEDS; i++) {
pinMode(LED_PINS[i], OUTPUT);
pinMode(BUTTON_PINS[i], INPUT_PULLUP);
}
randomSeed(millis());
newGame();
}
LEDピンを出力に、ボタンピンを内部プルアップ付きの入力に設定します(これにより、ボタンが押されたときにLOWを読み取ります)。randomSeed(millis())により、ゲームごとに異なるシーケンスが生成されます。newGame()で最初のラウンドを開始します。
ゲームロジック
newGame()はシーケンス長を1にリセットし、ランダムなステップを追加して、シーケンスを再生します。
void newGame() {
sequenceLength = 1;
currentStep = 0;
addToSequence();
playSequence();
}
void addToSequence() {
sequence[sequenceLength - 1] = random(0, NUM_LEDS);
}
void playSequence() {
for (int i = 0; i < sequenceLength; i++) {
flashLED(sequence[i]);
delay(500);
}
}
void flashLED(int led) {
digitalWrite(LED_PINS[led], HIGH);
delay(300);
digitalWrite(LED_PINS[led], LOW);
}
playSequence()は保存されたシーケンスを反復処理し、各LEDを300ms点灯させ、500msの間隔を空けます。
メインループ
void loop() {
for (int i = 0; i < NUM_LEDS; i++) {
if (digitalRead(BUTTON_PINS[i]) == LOW) {
flashLED(i);
if (i == sequence[currentStep]) {
currentStep++;
if (currentStep == sequenceLength) {
delay(1000);
sequenceLength++;
currentStep = 0;
addToSequence();
playSequence();
}
} else {
// 間違ったボタン - ゲームオーバー
for (int j = 0; j < 3; j++) {
for (int k = 0; k < NUM_LEDS; k++) {
digitalWrite(LED_PINS[k], HIGH);
}
delay(200);
for (int k = 0; k < NUM_LEDS; k++) {
digitalWrite(LED_PINS[k], LOW);
}
delay(200);
}
newGame();
}
delay(300);
while (digitalRead(BUTTON_PINS[i]) == LOW);
}
}
}
ループはすべてのボタンを継続的にチェックします。ボタンが押されると(LOW)、対応するLEDを点滅させます。押されたボタンが期待されるステップ(sequence[currentStep])と一致すれば、進行します。プレイヤーがシーケンスを完了すると、新しいステップを追加して、より長いシーケンスを再生します。間違った場合は、すべてのLEDが3回点滅し、新しいゲームが開始されます。
重要な概念
- 配列: ピン番号とゲームシーケンスを保存するために配列を使用することで、コードがスケーラブルでクリーンになります。
- 内部プルアップ抵抗:
INPUT_PULLUPにより外部抵抗が不要になり、ボタンが押されたときにLOWを読み取ります。 - デバウンス:
delay(300)とwhile(digitalRead(...)==LOW)ループにより、シンプルなデバウンスを実現します。 - ランダム性:
randomSeed(millis())とrandom()により、予測不可能なシーケンスが生成されます。 - ステートマシン: ゲームは
currentStepとsequenceLengthを追跡して進行状況を管理します。
よくある問題とデバッグのヒント
- ボタンが反応しない? ボタンピンが
INPUT_PULLUPに設定され、正しく配線されているか(1.lをピンに、2.lをGNDに)確認してください。 - LEDが点灯しない? LEDピンが
OUTPUTに設定され、アノード/カソードの接続が正しいか確認してください。 - シーケンスが速すぎる?
flashLED()とplaySequence()のdelay()値を調整してください。 - ゲームが予期せずリセットされる?
randomSeed(millis())がsetup()内で一度だけ呼び出されていることを確認してください。 - シリアルモニタを使用する:
Serial.println()文を追加して、シーケンス値をデバッグしてください。
推奨拡張機能
- ブザーを追加する: LEDの色ごとに音を鳴らします。
- 難易度レベル: シーケンスが長くなるにつれて速度を上げます。
- ハイスコア: 達成した最長シーケンスを記録します。
- マルチプレイヤー: 2人のプレイヤーで交互にターンを交代します。
- 視覚的フィードバック: 異なるLEDの明るさやパターンを使用します。
自分で試してみよう!
プレイする準備はできましたか?Velxioでライブサンプルを開いて、シミュレーションを開始してください。ボタンを押してシーケンスを繰り返しましょう。どこまで進めるでしょうか?
楽しい制作を!