주사위 게임(아두이노)
주사위 게임(아두이노)
- 온라인 가상시뮬레이터 : AUTODESK CIRCUITS
- 출처 : 랜덤함수-https://www.arduino.cc/reference/ko/language/functions/random-numbers/random/
LED 응용편으로 주사위 게임의 원리를 배워 보도록 하겠습니다. 주사위는 1~6까지 총 6가지의 숫자가 랜덤으로 나와야 합니다. 난수가 나오기 위해서는 랜덤함수라는 걸 사용합니다.
그런데 랜덤함수 알고리즘은 규칙적으로 숫자가 나오기 때문에 프로그램상에서는 난수가 절대 나올 수 없습니다. 난수가 나오기 위해서 초기값으로 C언어에서는 현재 시간값을 난수알고리즘 계산식에 더해서 난수처럼 숫자를 만들어 냅니다.
아두이노의 경우는 칩에 전류가 공급되면 미세하게 핀에 전류가 흐르기 때문에 노이즈(잡음)이라고 불리우는 이 전류를 아날로그 입력핀에서 읽어오게 합니다. 즉, 전류가 미세하게 랜덤의 전류값이 읽어지니깐 그 값을 초기값으로 해서 random()함수에 대입해서 난수를 만들어내게 됩니다.
사설이 좀 길었습니다. 이해가 안가면 random()함수로 난수를 만드는구나 정도만 이해하시면 됩니다.
1. 랜덤함수
- 랜덤함수 : https://www.arduino.cc/reference/ko/language/functions/random-numbers/random/
- 함수 : random(최대값), random(최소값, 최대값)
random()함수로 인자값이 하나면 최대값이 되고, 인자가 두개면 최소값~최대값 사이의 숫자를 추출하게 됩니다.
예)
random(100) 이면 0~99사이 값이 출력
random(2~10) 이면 2~9사이 값이 출력
2. 랜덤함수 코딩
** https://www.arduino.cc/reference/ko/language/functions/random-numbers/random/** 소스를 그대로 인용합니다.
int randNumber;
void setup()
{
Serial.begin(9600);
pinMode(7,INPUT_PULLUP);
randomSeed(analogRead(A0));
}
void loop()
{
if(digitalRead(7)==0){
randNumber = random(1,7);
Serial.println(randNumber);
delay(50);
}
}
}
첫번째 :
여기서 아두이노 IDE의 시리얼모니터로 결과값을 찍기 위해서 두개의 함수 Serial.begin(9600), Serial.println(출력값)을 사용합니다.
9600은 시리얼통신속도인데 보통 9600을 잡는다 따로 다른 값으로 사용하는 경우도 있긴 하지만 이부분은 9600bps로 사용하구나 정도만 이해하세요.
시리얼 통신을 시작 => Serial.begin(9600)을 선언
시리얼 모니터 출력 =>Serial.println(난수값); 이렇게 표현하면 이 함수의 인자값이 시리얼모니터에 출력됩니다.
두번째 :
난수함수를 사용하기 위해서 randomSeed(),random()함수 두개만 아시면 됩니다.
난수의 초기값 선언 => randomSeed(초기값)으로 선언합니다. 초기값은 한번만 수행해도 되니깐 setup()함수에 선언하면 되겠죠.
여기서 초기값은 analogRead(A0)로 A0핀의 전류값을 입력했는데 아까 설명한것 처럼 아두이노핀에 흐르는 노이즈 전류값을 난수의 초기값으로 합니다.
초기값이 세팅된 상태에서 loop()안에서 random(1,7)하면 1~6사이의 난수가 호출 될때마다 생성됩니다.
randomSeed(analogRead(A0)); //랜덤함수 초기화
random(1,7); //1~7사이 난수 발생
이 두함수만 머리속에서 담아두시면 다 배웠습니다.
결과
0.05초 단위로 시리얼모니터로 1~6사이의 난수를 출력이 됩니다.

3. 주사위 게임 회로도
- 준비물 : 스위치버턴 1개, led 7개, 저항 220옴 7개, 아두이노우노, 뻥판
- 내용 : 간단히 스위치 버턴을 누르면 주사위 LED에 난수가 출력되게 한다.
좀 회로도가 지져분하네요. 생각나는대로 배치하다 보니간 지져분해 보이네요.
뻥판에 이쁘게 배치해야하는데 귀찮고 원리를 설명하는게 목적이니 여러분들이 한번 이쁘게 배치를 해보세요.

스위치는 내부풀업저항을 이용하기 때문에 지난시간에 원리를 설명했으며 대충 보시면 저항이 없는 스위치면은 내부풀업저항 모드를 사용했군하고 떠올라야 겠죠.
4. 주사위 게임 코딩
코딩을 하기 위해서는 우선 7개의 Led를 사용했습니다. 그러면 7개의 핀이 필요하겠죠. 회로도에서 13부터 순차적으로 7개핀을 사용하기로 했으니깐 우선 배열변수로 7개의 핀을 저장합니다.
int ledpin[7] = {13,12,11,10,9,8,7};
이제 7개의 Led가 숫자에 맞게 불이 들어오게 하기 위해서 어떻게 해야 할까요. 만약 1을 출력한다면 회로도 배치에 따르면 4번째 정중안 Led만 불이 들어와야겠죠.
0001000
대충 이런 느낌이겠죠.
2을 출력한다면, 3번째와 5번째 led만 불이 들어와야겠죠.
0010100
대충 이런 느낌이겠죠.
0과 1로 각 자리가 Led의 불이 들어오게 하는 위치라고 생각하고 0과 1로 표현을 해보세요.
0001000 //1
0010100 //2
0011100 //3
1010101 //4
1011101 //5
1110111 //6
대충 이렇게 나열되겠죠.
배열로 1을 출력하기 위해서 7핀 상태를 나타낸다면 아래와 같이 배치 되겠죠.
a[7]={0,0,0,1,0,0,0};
하지만 7핀의 6가지의 패턴이 있기 때문에 이걸 한번에 배열변수로 표현할려면 2차배열변수를 사용해야 합니다.
행과 열로 1열은 주사위 숫자의 불켜기 행은 숫자의 패턴이렇게 나타내면 되겠죠.
int number[6][7] = {
{0,0,0,1,0,0,0}, //1
{0,0,1,0,1,0,0}, //2
{0,0,1,1,1,0,0}, //3
{1,0,1,0,1,0,1}, //4
{1,0,1,1,1,0,1}, //5
{1,1,1,0,1,1,1}, //6
};
6가지의 숫자의 7개핀의 led 출력을 이렇게 2차배열로 나타냅니다.
위에서 배운 랜덤함수 코딩을 수정하면
int randNumber;
void setup()
{
for(int i=0;i<7;i++){
pinMode(ledpin[i], OUTPUT);
}
pinMode(6,INPUT_PULLUP);
randomSeed(analogRead(A0));
}
for문으로 ledpin[i]로 i는 0~6까지 ledpin[]배열에 저장된 핀 (13,12,11,10,9,8,7)들을 출력모드로 순차적으로 선언합니다.
그리고 스위치버턴(6번핀)을 내부풀업저항을 사용한다고 선언했습니다.
그다음 랜덤함수를 사용하기 위해 랜덤함수 초기화함수 randomSeed()를 선언했습니다.
void loop()
{
if(digitalRead(6)==0){
randNumber = random(0,6);
for(int i=0;i<7;i++){
digitalWrite(ledpin[i],number[randNumber][i]);
}
delay(50);
}
}
복습 차원으로 내부풀업저항모드일때 회로도 처럼 배치하면 초기상태는 1입니다. 스위치를 누르면 0이 됨으로 if문으로 스위치를 누를때 digitalRead(6)핀이 0이 됨으로 0과 같다면 참이 되어 내부 처리명령문들을 수행합니다.
randNumber에 랜덤함수에서 0~5사이의 숫자가 추출됩니다. 0번째 즉 1이되고 5번째는 6이 됩니다. 배열변수는 위치가 0이 첫번째 위치입니다. 즉, a[3]이란 배열이 있으면 a[0], a[1], a[2] 이렇게 3개의 저장공간에 값이 저장됩니다. 그래서 0~5사이의 난수를 추출하고 그 위치값인 0이 1, 1이2... 이렇게 표현된다는 점을 혼동하시면 안돼요.
주사위 Led 출력
random(0,6)에서 0~5의 값이 출력
주사위(난수)값을 통해 for문을 통해서 0~6까지 7개의 핀에 led를 제어합니다.
digitalWrite(led핀번호,led2차배열변수에 저장된 값);
13~7번핀까지 for문으로 통해 순차적으로 출력시키는데 number[randNumber][i]을 통해
주사위[난수값][i]로 number[2][i] 이면
3번째 위치의 열값들을 출력한다고 생각 하시면 됩니다.
{0,0,1,1,1,0,0} 이 값들이 for문을 통해 순차적으로 digitalWrite()함수로 전류 제어하게 됩니다.
number[0][i]이면 => 1번째 {0,0,0,1,0,0,0}
number[5][i]이면 => 6번째 {1,1,1,0,1,1,1}
어떤 느낌이신지 아시겠지요.
그래서 코딩이
int ledpin[7] = {13,12,11,10,9,8,7};
int number[6][7] = {
{0,0,0,1,0,0,0}, //1
{0,0,1,0,1,0,0}, //2
{0,0,1,1,1,0,0}, //3
{1,0,1,0,1,0,1}, //4
{1,0,1,1,1,0,1}, //5
{1,1,1,0,1,1,1}, //6
};
int randNumber;
void setup()
{
for(int i=0;i<7;i++){
pinMode(ledpin[i], OUTPUT);
}
pinMode(6,INPUT_PULLUP);
randomSeed(analogRead(A0));
}
void loop()
{
if(digitalRead(6)==0){
randNumber = random(0,6);
for(int i=0;i<7;i++){
digitalWrite(ledpin[i],number[randNumber][i]);
}
delay(50);
}
}
5. 주사위 게임 결과
마무리
랜덤함수를 사용하기 위해서 랜덤함수 초기화 randomSeed(analogRead(A0))를 시키고 random(0,6) 함수로 0~5까지의 난수를 발생한다는 원리만 이해하시면 오늘 배운 내용이 전부입니다.
이 두함수를 사용하기 위해서 지난 시간의 배운것들을 종합해서 응용해 보았습니다.
아두이노공식홈페이지에서 제공되는 랜덤함수 예제가 깔끔해서 거기에 맞게 주사위 패턴과 사용될 주사위 핀을 배열변수로 선언한것만 좀 복잡하게 보일 뿐이죠.
원리는 참 간단한데 뭔가 스토리 내용을 코딩하다보면 코딩량이 늘어나니깐 복잡해 보였을 꺼에요. 하지만 랜덤함수를 사용하기 위한 두개의 함수만 제대로 이해하셨다면 다 배운거고요.
주사위는 복잡해 보일뿐 배열변수와 for문의 원리를 이해한다면 어렵지 않을꺼에요.
최대한 코딩량을 줄이기 위해서 하나의 행동인 버턴을 누르면 랜덤 주사위 led가 켜진다만 했지만 여기에 추가할 것이 많습니다.
어린시절에 문반구점에서 작은 오락기계를 아실꺼에요 가위바위보 게임과 주사위 게임이 떠오를 꺼에요. 동전을 넣고 게임이 시작하면 무작위로 멜로디처럼 led가 여러 패턴의 숫자 모양을 나타내다가 버턴을 누르면 그때 숫자가 나오잖아요.
그런식으로 로직을 좀 더 디테일적으로 구현도 가능합니다. 지난 시간에 피에조부저를 다뤘습니다. 간단한 멜로디를 피에주부저를 추가해서 스위치 버턴을 누르면 멜로디가 나오면서 여러패턴의 숫자 모양이 출력되다가 난수 숫자가 최종적으로 출력되는 표현도 생각할 수 있겠죠.
그리고, 주사위 대신에 가위바위보도 3가지 패턴을 만들면 쉽게 구현 되겠죠.
랜덤함수 하나로 재밌는 표현이 가능하니깐 한번 상상의 나래를 펼쳐 보세요.
스스로 홍보하는 프로젝트에서 나왔습니다.
오늘도 좋은글 잘 읽었습니다.
오늘도 여러분들의 꾸준한 포스팅을 응원합니다.
오늘도 방문해주셔서 감사합니다.
엇.... 다양하게 재미있네요.. .근데 오락실에 그 가위바위보 게임은 아무래도 우리가 누르고 나서.... 기계가 선택한다는 느낌이라... 꽤 돈을 날렸던 기억이.... 아직도 기억나네요 가위 바위 보 졌고 근데 기계가 일본 기계라 그런지 이기면 얏다네... 이런 소리를 들었던 기억이 있네요
그건 확률식이 추가로 들어가서 그래요.
온라인 게임에서 강화 확률이나 아템 드랍 확률처럼 성공할 난수가 확률에 덮어져서 계산되어서 나오기 때문인거죠.
버턴을 누르면 그 순간 컴퓨터는 계산을 인간이 인지이 할 수 없고 수많은 반복 수행할 수 있어요.
확률식으로로 제한을 걸어 높으니 이기는것도 한정되어 있지요
문돌이인 저는 그저 문송합니다..ㅜㅜ
비전공 분들이 가지고 노는것이 아두이노고요
오늘은 주사위게임을 하기 위해서 좀 코딩부분이 들어 갔네요.
부품 핀 연결하는 것하고 함수 몇개만 아시면 쉽게 다룰 수 있어요
역시나 저에게는 어려운.ㅠ
공부 하시는 분들에게는 많은 도움이 되겠어요^^
스토리 코딩이 들어가서 코딩량이 좀 많고 led 갯수가 좀 많아서 약간 어렵게 느껴졌을 수도 있겠네요.
함수 몇개 안되고 이걸 스토리 만들어 표현한거라 총 함수가 6개 의미만 이해하시면 이 의미로 스토리를 짜내면 됩니다.
함수단위로 대부분 만들어져 있어서 엑셀처럼 함수의 의미만 이해하고 한수 안에 인자값만 잘 넣으시고 뭘 표현할지 스토리만 설계하시면 돼요
@resteemator is a new bot casting votes for its followers. Follow @resteemator and vote this comment to increase your chance to be voted in the future!
즐거운 스티밋!
힘내세요 빠샤!
즐거운 스티밋!