このSIMONというゲームをArduinoを使って電子工作してみました。
同じように作りたいという人のために
説明編と
回路図編とプログラム編に分けて、今回の電子工作を公開しています。
このブログはプログラム編です。
#define LED_RED 0
#define LED_GREEN 1
#define LED_BLUE 2
#define LED_YELLOW 3
#define FAILURE 9
#define LED_RED_PIN 10
#define LED_GREEN_PIN 11
#define LED_BLUE_PIN 12
#define LED_YELLOW_PIN 13
#define RELAY 4
#define BUTTON_RED_PIN 6
#define BUTTON_GREEN_PIN 7
#define BUTTON_BLUE_PIN 8
#define BUTTON_YELLOW_PIN 9
#define TIME_LIMIT 300
#define MOVE_TO_WIN 8
#define MARK_OF_LOST false
#define MARK_OF_WIN true
int moves[32];
int nmoves = 0;
int leave_counter;
void setup() {
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
pinMode(LED_BLUE_PIN, OUTPUT);
pinMode(LED_YELLOW_PIN, OUTPUT);
pinMode(BUTTON_RED_PIN, INPUT);
pinMode(BUTTON_GREEN_PIN, INPUT);
pinMode(BUTTON_BLUE_PIN, INPUT);
pinMode(BUTTON_YELLOW_PIN, INPUT);
pinMode(RELAY,OUTPUT);
digitalWrite(RELAY,HIGH);
play_winner(3);
randomSeed(analogRead(0));
}
void loop() {
delay(1000);
if (game_mode() == MARK_OF_WIN){
play_winner(10);
}else{
play_loser();
}
}
void led_all_switch_on(){
for ( int i = 0 ; i <= 25 ; ++i){
for ( int j = 0 ; j<= 3 ; ++j){
set_leds(j);
delay(1);
}
}
}
void play_loser(){
for (int i = 0; i <=5 ;++ i){
led_all_switch_on();
set_leds(4);
delay(100);
}
}
void play_winner(int count){
for ( int i = 0 ; i <= count ; ++i){
set_leds(0);
delay(80);
set_leds(1);
delay(80);
set_leds(3);
delay(80);
set_leds(2);
delay(80);
set_leds(4);
}
}
//問題を表示する
void play_moves(){
for (int c_move = 0 ; c_move < nmoves ; ++c_move){
set_leds(moves[c_move]);
delay(200);
set_leds(4);
delay(200);
}
}
//新しい色を加える
void add_to_moves(){
int new_button;
moves[nmoves] = random(4);
++nmoves;
}
// ボタンが押されるか、タイムアウトまで待つ。返り値は0から3までの色かFAILURE=9のどれか。
int wait_for_button(){
int old_button = FAILURE;
int time_limit = TIME_LIMIT;
while( time_limit > 0){
int button;
button = check_button();
if (((old_button == 0)||(old_button == 1)||(old_button == 2)||(old_button == 3))&&(button == FAILURE)){
return old_button;
}
old_button = button;
delay(10);
--time_limit;
}
return FAILURE;
}
//ゲームのメインサブルーチン
boolean game_mode(){
nmoves= 0;
while ( nmoves < MOVE_TO_WIN){
add_to_moves();
play_moves();
for ( int c_move = 0 ; c_move < nmoves ; ++c_move){
int choice = wait_for_button();
if (choice == FAILURE) {
//リレーを操作 auto power off
if (nmoves == 1) {
++leave_counter ;
if (leave_counter >= 5) digitalWrite(RELAY,LOW);
}else leave_counter =0;
//
return MARK_OF_LOST;
}
set_leds(choice);
delay(200);
if (choice != moves[c_move]) return MARK_OF_LOST;
set_leds(4);
}
delay(1000);
}
return MARK_OF_WIN;
}
//ボタンをチェック。0~3の色かFAILURE=9の返り値
int check_button(){
int i = FAILURE;
if (digitalRead(BUTTON_RED_PIN) == HIGH){
delay(10);
i = LED_RED;
}
if (digitalRead(BUTTON_GREEN_PIN) == HIGH){
delay(10);
i = LED_GREEN;
}
if (digitalRead(BUTTON_BLUE_PIN) == HIGH){
delay(10);
i = LED_BLUE;
}
if (digitalRead(BUTTON_YELLOW_PIN) == HIGH){
delay(10);
i = LED_YELLOW;
}
return i;
}
//LEDの表示。返り値なし
void set_leds(int leds){
digitalWrite(LED_RED_PIN,LOW);
digitalWrite(LED_GREEN_PIN,LOW);
digitalWrite(LED_BLUE_PIN,LOW);
digitalWrite(LED_YELLOW_PIN,LOW);
switch (leds){
case 0:
digitalWrite(LED_RED_PIN,HIGH);
break;
case 1:
digitalWrite(LED_GREEN_PIN,HIGH);
break;
case 2:
digitalWrite(LED_BLUE_PIN,HIGH);
break;
case 3:
digitalWrite(LED_YELLOW_PIN,HIGH);
break;
}
}