工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduinoでメモリーゲーム (Simonクローン) を作ろう – ステップバイステップチュートリアル

必要な部品と材料

部品名 数量 備考
Arduino UNO 1 メインボード
330Ω 抵抗 4 LED電流制限用
10kΩ 抵抗 4 ボタンプルダウン用
LED (赤・青・緑・黄 など異色4個) 4 ゲーム表示用
ミニスピーカー (圧電ブザー等) 1 効果音用 (省略可)
ブレッドボード (フルサイズ) 1
ジャンパーワイヤー 1式
タクトスイッチ (4個) 4 ボタン入力用 (LEDと同色推奨)

使用ツール

プロジェクト概要

1970〜80年代に大流行した電子ゲーム「Simon (サイモン)」を覚えていますか? 4色のボタンが順番に光り、そのシーケンスを記憶して繰り返すゲームです。筆者も子供の頃夢中になりましたが、引っ越しの際に紛失してしまいました。

大人になってArduinoを知り、失われた友を蘇らせるチャンス到来! このチュートリアルでは、Arduino Unoと少数の部品で同等のゲームを製作します。回路はシンプルですが、プログラムは初心者には少し複雑かもしれません。コード内に詳細なコメントを入れていますので、読み解きながら理解を深めてください。

最短で動かす手順

  1. 回路図通りに配線する (ワイヤーの色は任意)
  2. ソースコードをArduino IDEに貼り付け、ボードに書き込む
  3. 遊ぶ!

動作の流れ

  1. 起動後約3秒で、全LEDがゆっくり5回点滅 (ゲーム開始合図)
  2. ランダムに1つのLEDが点灯 → 対応するボタンを押す
  3. 正解なら、同じLEDが再点灯後、新しいLEDが追加されて2手目に
  4. これを繰り返し、シーケンスが長くなっていく
  5. 間違える、または2秒以内に押せないとゲームオーバー (全LED高速点滅)
  6. 最後の正解シーケンスが再生され (スコア確認用)、再び5回点滅でリスタート

Arduinoでメモリーゲーム (Simonクローン) を作ろう – ステップバイステップチュートリアル

Arduinoでメモリーゲーム (Simonクローン) を作ろう – ステップバイステップチュートリアル

トラブルシューティング

難易度調整・拡張

コーディングの小ネタ


void setup() {
  delay(3000); // 起動直後の3秒待機
  Serial.begin(9600);
  Reset();
}

setup() 先頭に delay(3000) を入れておくと、暴走ループで書き込み不能になった際、リセット→即書き込みで復旧しやすくなります。

ソースコード (完全版)


#define PLAYER_WAIT_TIME 2000  // ボタン入力猶予 2秒
byte sequence[100];            // シーケンス格納 (最大100手)
byte curLen = 0;               // 現在のシーケンス長
byte inputCount = 0;           // 今回のターンで正解した入力数
byte lastInput = 0;            // 最後に押されたボタン
byte expRd = 0;                // 期待される正解ボタン (LEDピン番号)
bool btnDwn = false;           // ボタン押下中フラグ
bool wait = false;             // プレイヤー入力待ちフラグ
bool resetFlag = false;        // ゲームオーバーフラグ
byte soundPin = 5;             // スピーカー出力ピン
byte noPins = 4;               // LED/ボタン数
byte pins[] = {2, 13, 10, 8};  // 各LED/ボタンのピン番号 (LED出力兼ボタン入力)
long inputTime = 0;            // 入力開始時刻 (タイムアウト判定用)

void setup() {
  delay(3000);
  Serial.begin(9600);
  Reset();
}

// 全ピンの方向一括設定
void setPinDirection(byte dir) {
  for (byte i = 0; i < noPins; i++) pinMode(pins[i], dir);
}

// 全LED一括点灯/消灯
void writeAllPins(byte val) {
  for (byte i = 0; i < noPins; i++) digitalWrite(pins[i], val);
}

// ビープ音 (PWMで簡易トーン)
void beep(byte freq) {
  analogWrite(soundPin, 2);
  delay(freq);
  analogWrite(soundPin, 0);
  delay(freq);
}

// 全LED点滅 (freq小→高速, 大→低速)
void flash(short freq) {
  setPinDirection(OUTPUT);
  for (int i = 0; i < 5; i++) {
    writeAllPins(HIGH); beep(50); delay(freq);
    writeAllPins(LOW);  delay(freq);
  }
}

// ゲーム状態リセット
void Reset() {
  flash(500);  // 低速5回点滅
  curLen = 0; inputCount = 0; lastInput = 0; expRd = 0;
  btnDwn = false; wait = false; resetFlag = false;
}

// ゲームオーバー演出 (高速点滅)
void Lose() { flash(50); }

// シーケンス再生 (覚えるフェーズ / ゲームオーバー時の答え合わせ)
void playSequence() {
  for (int i = 0; i < curLen; i++) {
    Serial.print("Seq: "); Serial.print(i); Serial.print(" Pin: "); Serial.println(sequence[i]);
    digitalWrite(sequence[i], HIGH); delay(500);
    digitalWrite(sequence[i], LOW);  delay(250);
  }
}

// 敗北処理
void DoLoseProcess() {
  Lose(); delay(1000);
  playSequence(); // 最後のシーケンス再生 (スコア確認)
  delay(1000);
  Reset();        // 新ゲーム開始
}

void loop() {
  if (!wait) {
    // ===== Arduinoのターン: シーケンス生成・提示 =====
    setPinDirection(OUTPUT);
    randomSeed(analogRead(A0));           // 乱数シード (ノイズ利用)
    sequence[curLen] = pins[random(0, noPins)]; // ランダムに1手追加
    curLen++;
    playSequence();                       // 全シーケンス再生
    beep(50);                             // 合図音
    wait = true;                          // プレイヤーのターンへ
    inputTime = millis();                 // タイムアウト計測開始
  } else {
    // ===== プレイヤーのターン: 入力受付 =====
    setPinDirection(INPUT);
    
    // タイムアウト判定
    if (millis() - inputTime > PLAYER_WAIT_TIME) { DoLoseProcess(); return; }

    if (!btnDwn) {
      expRd = sequence[inputCount];       // 期待される正解
      Serial.print("Expected: "); Serial.println(expRd);
      
      // 誤入力チェック (正解以外のボタンが押されたか)
      for (int i = 0; i < noPins; i++) {
        if (pins[i] == expRd) continue;
        if (digitalRead(pins[i]) == HIGH) {
          lastInput = pins[i];
          resetFlag = true;  // 不正解
          btnDwn = true;
          Serial.print("Read (wrong): "); Serial.println(lastInput);
        }
      }
    }

    // 正解ボタンが押されたか
    if (digitalRead(expRd) == HIGH && !btnDwn) {
      inputTime = millis();      // タイムアウトリセット
      inputCount++;              // 正解カウント
      btnDwn = true;
      Serial.print("Read (correct): "); Serial.println(expRd);
    } else {
      // ボタン離した瞬間の処理
      if (btnDwn && digitalRead(lastInput) == LOW) {
        btnDwn = false;
        delay(20); // チャタリング対策
        if (resetFlag) { DoLoseProcess(); } // 不正解だった
        else {
          if (inputCount == curLen) { // 全手正解
            wait = false;             // 次はArduinoのターン
            inputCount = 0;
            delay(1500);              // 少し間を置く
          }
        }
      }
    }
  }
}

回路図 (Fritzing)

Arduinoでメモリーゲーム (Simonクローン) を作ろう – ステップバイステップチュートリアル

各LEDのアノードをピン (2, 13, 10, 8) に、カソードを330Ω抵抗経由でGNDへ。各ボタンの一端を同じピンに、もう一端を10kΩ抵抗経由でGND (プルダウン)、さらにもう一端を5Vへ。スピーカーはピン5とGND間に接続。

発展アイデア

携帯型にする、LEGOと連携させる (参考: Lego Mini Memory Game)、スコアをEEPROMに保存してハイスコア機能を付ける、などさらに発展させるアイデアは無限大です。楽しんでください!

製造プロセス

  1. Arduinoで作るモニター用Ambilightシステム:没入感アップの自作ガイド
  2. Arduino NanoとMPU-6050で作るリアルタイムジャイロスコープゲーム
  3. NeoPixelリングとArduinoで作るインタラクティブジャイロスコープLEDディスプレイ
  4. Arduino UNOとOLEDディスプレイでクラシックPongゲームを自作:ステップバイステップチュートリアル
  5. DIY Arduino USBゲームコントローラー - 高性能ゲームパッドを自作
  6. Arduinoタッチブレークアウトゲーム:2.4インチTFT LCDでクラシックアーケードを再現
  7. Pixie: Arduino Pro Miniで作るNeoPixel腕時計 - アナログとデジタル融合のDIY光る時計
  8. Pixel Chaser: Arduino Nanoで作るワンタップLEDゲーム
  9. Arduinoで自動化するChrome恐竜ゲーム – LDRとPythonで障害物を検知してジャンプ
  10. 携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築
  11. スマート手話グローブ:ジェスチャーをテキスト/音声に変換