6주차 반응 속도 게임

아두위키 : Arduwiki

6주차에서 우리는 도트 매트릭스와 버튼을 이용해 반응 속도 게임기를 만들어 볼 것 입니다.

반응 속도 게임기는 두 사람이 함께 하는 게임입니다.

도트 매트릭스에 "O" 모양이 뜨는 순간 버튼을 누르고 먼저 누른 사람 쪽으로 화살표 모양을 출력하는 게임입니다.

누가 반응 속도가 더 빠른지 게임을 통해 확인해봅시다!

1. 도트 매트릭스로 동그라미, 화살표 모양 출력하기

1-1. [실습]동그라미 모양 출력하는 함수 만들기

우리는 저번 시간 도트 매트릭스를 이용해 다양한 모양을 출력해보았습니다.

일단 도트 매트릭스에 동그라미 모양을 출력하는 함수를 만들고 실행해봅시다.

단, 도트매트릭스가 세로로 조립되어야하기 때문에 아래 사진처럼 도트매트릭스를 두고 동그라미 모양을 출력하도록 만들어봅시다.

1-2. [실습] 왼쪽 화살표 만들기

bool left[8][8] =
{
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

위의 2차원 리스트에 화살표로 표시할 부분을 1로 채워 왼쪽 화살표 모양이 표시될 수 있도록 코딩해봅시다.

1-3. [실습] 오른쪽 화살표 만들기

bool right[8][8] =
{
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

위의 1-2 실습을 참고하여 오른쪽 화살표를 출력하는 함수도 만들어 실행해봅시다.

2. random() 함수 사용하기

아두이노에서 random() 함수를 사용해봅시다.

random() 함수를 사용하는 이유는 동그라미 모양을 무작위 시간에 띄울 수 있도록 코딩하기 위함입니다.

random(min, max)로 사용할 수 있으며 min~(max-1)사이의 값을 랜덤으로 얻을 수 있습니다.

예를 들어, random(1, 10)라면 1~9 사이의 랜덤 값를 반환할 수 있고 만약 1~10 사이의 값을 얻고자 한다면 random(1, 11)로 설정해주어야 합니다.

2-1. 랜덤 값 시리얼 모니터에 출력해보기

랜덤 함수를 이용해 그 값을 출력하고 그만큼 delay() 함수를 이용해 코드 진행을 지연시켜 봅시다.

void setup() {
  Serial.begin(9600);
}

void loop() {
  int time = random(1000, 5000);
  Serial.println(time);
  delay(time);
}

2-2. [실습] 랜덤 값을 이용해 동그라미 모양 출력하기

이번에는 그럼 랜덤 시간으로 동그라미 모양을 출력하는 코드를 작성해 봅시다.

동그라미 모양은 1초만 켜고 1~10초 사이 랜덤의 시간 동안 도트 매트릭스가 꺼졌다가 다시 동그라미를 출력하는 프로그램을 작성해봅시다.


#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;

LedControl lc = LedControl(din, clk, cs, 1); 

bool O[8][8] =
{
  {0,1,1,1,1,1,1,0},
  {1,1,1,1,1,1,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,1,1,1,1,1,1},
  {0,1,1,1,1,1,1,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
}

void loop() 
{
  //code..
}

void show_O() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, O[col][row]);
    }
  }
}

3. 반복문 while 학습과 작품 완성하기

3-1. [반복문 while] 학습.

while 반복문에 대해서 배워봅시다.

while 반복문은 if 조건문과 굉장히 비슷한 형태입니다. [조건식]이 참인 동안 문장을 계속 반복합니다. 조건식의 결과에 따라 수행될 코드의 수행 여부를 판단합니다.

조건식이 참인 경우 코드를 수행하고 거짓인 경우 반복문이 종료됩니다.

while (조건식) {
    //code..
}

우리가 앞서 배운 내용을 기반으로 while문의 구조를 이해해 봅시다.

while(1) {
    Serial.println("hello");
}

위의 코드는 실행하면 화면에 "hello"가 무한하게 출력됩니다. 조건식이 거짓이 되는 경우가 없기 때문에 무한하게 반복되어 프로그램이 종료되지 않습니다.

while(0) {
    Serial.println("hello");
}

위의 코드는 실행하면 Serial.println("hello") 코드가 실행되지 않습니다. 0은 거짓이므로 반복문 안의 코드가 수행되지 않습니다.

int n = 1;
while(n<=10) {
    Serial.println(n);
    n+=1;
}
// n이 1, 2, 3, 4, 5, 6, 7, 8, 9, 10를 반복함.
// n이 11이 되는 순간 while문 조건식이 거짓이 되어 반복문이 종료됨.

반복문을 정해진 횟수만큼 수행하기 위해서는 위와 같은 코드를 작성할 수 있습니다.

3-2. [반복문 제어 구문 break]

break는 반복문을 벗어날 때 사용하는 명령어입니다. 반복문이 실행되다가 특정 조건에서 반복문을 벗어날 수 있도록 코드를 작성할 수 있습니다.

n=1
while(1) {
    if (n==20) {
        Serial.println("20!!!!");
        break;
    }
    n+=1;
}
// n이 1씩 증각하다가 20이 되는 순간 if 조건문이 실행됩니다.
// if 조건문의 println() 함수가 실행되고 break 명령어를 만나 while 반복문을 벗어납니다.

3-3. [실습]반응 속도 게임기 프로그램 완성하기.

자. 이제 배운 문법을 이용해 반응 속도 게임기 프로그램을 완성해봅시다.

  1. 1~10초 사이 무작위 시간을 기다리다가 "O" 모양이 도트 매트릭스에 출력되게 만들어주세요.
  2. while 반복문을 이용해 버튼 2개 중 어떤 버튼이 눌릴 때까지 반복하도록 만들어주세요.
    1. while 반복문 안에서 버튼이 눌리는지 확인합니다.
    2. 왼쪽 버튼이 눌린다면 "왼쪽 화살표" 모양을 도트 매트릭스에 출력한 후 1초 기다렸다가 반복문을 탈출합니다.
    3. 오른쪽 버튼이 눌린다면 "오른쪽 화살표" 모양을 도트 매트릭스에 출력한 후 1초 기다렸다가 반복문을 탈출합니다.
  3. 반복문 탈출 후 모든 도트 매트릭스의 LED를 꺼주세요.
#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;
int btn1 = 2;
int btn2 = 3;

LedControl lc = LedControl(din, clk, cs, 1); 

bool O[8][8] =
{
  {0,1,1,1,1,1,1,0},
  {1,1,1,1,1,1,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,1,1,1,1,1,1},
  {0,1,1,1,1,1,1,0}
};

bool left[8][8] =
{
  {0,0,0,1,1,0,0,0},
  {0,0,1,1,1,1,0,0},
  {0,1,1,1,1,1,1,0},
  {1,1,0,1,1,0,1,1},
  {1,0,0,1,1,0,0,1},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0}
};

bool right[8][8] =
{
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {1,1,0,1,1,0,1,1},
  {0,1,1,1,1,1,1,0},
  {0,0,1,1,1,1,0,0},
  {0,0,0,1,1,0,0,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
  pinMode(btn1, INPUT_PULLUP);
  pinMode(btn2, INPUT_PULLUP);
}

void loop() 
{
  show_O();
  while(1) {
    // code..
  }
  //code..
}

void show_O() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, O[col][row]);
    }
  }
}

void show_right() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, right[col][row]);
    }
  }
}

void show_left() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, left[col][row]);
    }
  }
}

실습 참고하기

1-1. [실습] 동그라미 모양 출력하는 함수 만들기

#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;

LedControl lc = LedControl(din, clk, cs, 1); 

bool O[8][8] =
{
  {0,1,1,1,1,1,1,0},
  {1,1,1,1,1,1,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,1,1,1,1,1,1},
  {0,1,1,1,1,1,1,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
}

void loop() 
{
  show_O();
  delay(1000);
  lc.clearDisplay(0);   
  delay(1000);
}

void show_O() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, O[col][row]);
    }
  }
}

1-2. [실습] 왼쪽 화살표 만들기

#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;

LedControl lc = LedControl(din, clk, cs, 1); 

bool left[8][8] =
{
  {0,0,0,1,1,0,0,0},
  {0,0,1,1,1,1,0,0},
  {0,1,1,1,1,1,1,0},
  {1,1,0,1,1,0,1,1},
  {1,0,0,1,1,0,0,1},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
}

void loop() 
{
  show_left();
  delay(1000);
  lc.clearDisplay(0);   
  delay(1000);
}

void show_left() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, left[col][row]);
    }
  }
}

1-3. [실습] 오른쪽 화살표 만들기

#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;

LedControl lc = LedControl(din, clk, cs, 1); 

bool right[8][8] =
{
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {1,1,0,1,1,0,1,1},
  {0,1,1,1,1,1,1,0},
  {0,0,1,1,1,1,0,0},
  {0,0,0,1,1,0,0,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
}

void loop() 
{
  show_right();
  delay(1000);
  lc.clearDisplay(0);   
  delay(1000);
}

void show_right() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, right[col][row]);
    }
  }
}

2-2. [실습] 랜덤 값을 이용해 동그라미 모양 출력하기

#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;

LedControl lc = LedControl(din, clk, cs, 1); 

bool O[8][8] =
{
  {0,1,1,1,1,1,1,0},
  {1,1,1,1,1,1,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,1,1,1,1,1,1},
  {0,1,1,1,1,1,1,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
}

int time;

void loop() 
{
  show_O();
  delay(1000);
  lc.clearDisplay(0);   
  time = random(1000, 10001);
  delay(time);
}

void show_O() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, O[col][row]);
    }
  }
}

3-3. [실습] 반응 속도 게임기 프로그램 완성하기.

#include "LedControl.h"

int din = 12;
int cs = 11;
int clk = 10;
int btn1 = 2;
int btn2 = 3;

LedControl lc = LedControl(din, clk, cs, 1); 

bool O[8][8] =
{
  {0,1,1,1,1,1,1,0},
  {1,1,1,1,1,1,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,0,0,0,0,1,1},
  {1,1,1,1,1,1,1,1},
  {0,1,1,1,1,1,1,0}
};

bool left[8][8] =
{
  {0,0,0,1,1,0,0,0},
  {0,0,1,1,1,1,0,0},
  {0,1,1,1,1,1,1,0},
  {1,1,0,1,1,0,1,1},
  {1,0,0,1,1,0,0,1},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0}
};

bool right[8][8] =
{
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {1,1,0,1,1,0,1,1},
  {0,1,1,1,1,1,1,0},
  {0,0,1,1,1,1,0,0},
  {0,0,0,1,1,0,0,0}
};

void setup() {
  lc.shutdown(0, false);    
  lc.setIntensity(0, 8);   
  lc.clearDisplay(0);   
  pinMode(btn1, INPUT_PULLUP);
  pinMode(btn2, INPUT_PULLUP);
}

void loop() 
{
  show_O();
  while(1) {
    if (digitalRead(btn1) == LOW) {
      show_left();
      delay(1000);
      break;
    }
    if (digitalRead(btn2) == LOW) {
      show_right();
      delay(1000);
      break;
    }
  }
  lc.clearDisplay(0);   
  int time = random(1000, 10001);
  delay(time);
}

void show_O() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, O[col][row]);
    }
  }
}

void show_right() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, right[col][row]);
    }
  }
}

void show_left() {
  for(int col=0; col<8; col+=1) {
    for(int row=0; row<8; row+=1) {
      lc.setLed(0, col, row, left[col][row]);
    }
  }
}