여전히 숫자야구게임 만드는 중.
다른 숫자 세 개로 이뤄진 세 자리 숫자를 생성해야 함.
Math.floor(Math.random()*1000);
처음에 이렇게 시도해 봤으나 숫자가 중복되고 두 자리 숫자도 나와서 다른 방법 찾기로.
이 방법 저 방법 시도하고 찾아보다가 스택오버플로우에서 배열 순서를 무작위로 섞는 함수를 찾아냄.
피셔-예이츠 셔플이라고 함. 음악앱이 노래를 무작위한 순서로 재생하도록 만들 때 사용하는 방법이라고.
직접 만들어내진 못했으니 코드를 들고 와서 어떻게 배열을 섞는지 분석이나 해보려 함.
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
변수는 currentIndex와 temporaryValue, randomIndex 세 개. currentIndex는 최초에 매개변수인 배열의 길이로 설정.
while 구문으로 currentIndex가 0일 아닐 때, 즉 배열의 첫 번째 요소를 뽑지 않은 한 코드블럭을 계속 실행. (뭔가를 반복할 때 지금까지 for loop을 주로 사용했는데 while도 한 번씩 생각해봐야겠다.)
Math.random()은 0 이상 1 미만인 숫자를 출력하므로 Math.floor(Math.random() * currentIndex);는 0 이상 currentIndex 미만인 값, 즉 아무 인덱스 출력. 이 값을 randomIndex에 담고 currentIndex -1.
temporaryValue에 array[currentIndex], 즉 배열의 마지막 요소를 담음. 그리고 배열 제일 끝에 array[randomIndex], 즉 조금 전에 뽑은 아무 값을 넣음. 아무 값이 있던 자리에 다시 temporaryValue를 담음. => 아무 자리의 값과 가장 뒷자리 값을 맞바꿈.
뒤로 밀린 값을 제외하고 이 과정을 반복.
피셔-예이츠 셔플을 더 자세하게 설명하고 시각적 자료까지 제공하는 사이트: https://bost.ocks.org/mike/shuffle/
어쨌든 나는 0에서 9 사이 숫자 가운데 무작위로 세 개를 뽑아야 함.
처음 생각한 방법은 0~9로 이뤄진 배열을 피셔-예이츠 셔플에 넣은 뒤 slice로 뒤쪽은 잘라내기.
var randomNum;
function create() {
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
randomNum = shuffle(arr).slice(0, 3);
return randomNum;
}
randomNum = create;
그런데 생각해보니 비효율적. 셔플을 끝까지 진행할 필요가 없고 while 안의 코드블럭을 세 번만 돌린 다음 배열의 가장 뒤에 있는 요소 세 개만 내보내면 됨.
function create() {
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function shuffle(array) {
var currentIndex, temporaryValue, randomIndex;
for (currentIndex = array.length - 1; currentIndex >= array.length - 3; currentIndex--) {
randomIndex = Math.floor(Math.random() * currentIndex);
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
randomNum = shuffle(arr).slice(-3);
return randomNum;
}
randomNum = create;
아무 인덱스를 뽑은 다음에 빈 배열에 push하는 방법도 있을 듯.
'TIL > 자바스크립트' 카테고리의 다른 글
addEventListener와 for, 이벤트리스너가 마지막 반복 결과값에만 붙는 문제 [자바스크립트] (0) | 2020.06.21 |
---|---|
querySelectorAll getElementsByClassName 등 복수 선택 메소드와 addEventListener [자바스크립트] (0) | 2020.06.13 |
함수를 실행하고 결과값을 담는 위치 및 시점 [자바스크립트] (0) | 2020.06.11 |
배열 slice와 splice [자바스크립트] (0) | 2020.06.06 |
변수를 정의하는 위치, 그리고 함수 [자바스크립트] (0) | 2020.06.05 |