로또 시뮬레이션 제작 회고
안녕하세요 뭐라도 만드는 오물개입니다.
이번엔 스벨트로 만든 두 번째 서비스로 만만한 로또 시뮬레이션을 만들었음.
역시나 바로 시작.
제작배경
인간은 간사한 동물임. 새롭고 어려운 길을 택하기 보단, 알고 있는 쉬운 길을 택하는게 인간임.
나 역시 인간이라 뭐 만들 지 고민 하다 새로운 언어를 배우면 매 번 만드는 로또 시뮬레이션을 선택 함.
아 전에는 단순 로또 번호 추출기 정도만 만들었는데 이번엔 시뮬레이션 기능을 추가했음.
기획
- 로또번호를 생성하자.
- 사용자가 생성한 로또 번호를 기준으로 시뮬레이션을 하자.
- 느리면 답답하니 배속 기능을 넣자
- 숫자로 적으면 가독성이 떨어지니 한국식으로 표기하자.
- 나름 구색을 갖춰야 하니 역대 로또 번호를 보여주자.
SIMPLE IS BEST
구현
내용이 간단하니 적을게 없지만 포스팅 구색을 갖춰야하니 꾸역꾸역 적어보겠음.
1. 로또 번호 생성
// 랜덤 번호 뽑기
function generateRandomTicket() {
const nums = [];
// 6개 넣자.
while (nums.length < 6) {
const num = Math.floor(Math.random() * 45) + 1; //1부터 45까지 랜덤 숫자 뽑자
if (!nums.includes(num)) nums.push(num); // nums 중복 체크
}
return nums.sort((a, b) => a - b); // 오름차순 정렬
}
로또 번호 6개를 만드는 방법은 몇 가지 있다.
- 뽑은 숫자 배열에 넣기전 includes 함수를 사용해 중복 여부 확인하고 넣기
- 뽑은 숫자를 Set에 담아 6개 될 때 까지 넣기
- 1 ~45 숫자 목록을 미리 만들고 말 그대로 진짜 뽑아 쓰기
여러가지 방법이 있겠지만 알아서 하면 됨.
더 효율적인 방법 있으면 댓글 달아주길.
2. 배속 기능 구현
function setSpeed(newSpeed) {
speed = newSpeed;
if (isRunning)
clearInterval(intervalId);
intervalId = setInterval(() => {
for (let i = 0; i < speed; i++) {
simulateDraw();
}
}, 1);
}
}
1ms 당 speed번 만큼 simulateDraw() 함수를 실행함.
조금 생각하는 사람이라면 1ms에 진짜 저만큼 수행할 수 있을까? 싶을거임.
// 1초마다 count 값을 찍고, 다시 0으로 초기화
const checkIntervalId = setInterval(() => {
console.log(`실제로 ${count}번 호출됨`);
count = 0;
}, 1000);
그래서 위 테스트를 해봄.
잘된다.
이건 테스트하는 기기 환경 마다 달라질 수 있다.
콘디숀에 따라 다르다.
3. 번호 뽑고 당첨 확인
// 추첨 결과 판정
function checkDraw() {
const numbers = Array.from({ length: 45 }, (_, i) => i + 1);
shuffle(numbers);
const winningNumbers = numbers.slice(0, 6).sort((a, b) => a - b);
const bonus = numbers[6];
const matchCount = playerTicket.filter((n) =>
winningNumbers.includes(n),
).length;
const bonusMatch = playerTicket.includes(bonus);
let prize = "꽝";
if (matchCount === 6) prize = "1등";
else if (matchCount === 5 && bonusMatch) prize = "2등";
else if (matchCount === 5) prize = "3등";
else if (matchCount === 4) prize = "4등";
else if (matchCount === 3) prize = "5등";
return { prize, winningNumbers, bonus, matchCount, bonusMatch };
}
간단하게 코드 설명함.
- numbers라는 배열을 [1, 2, 3, …, 45] 이렇게 만듬.
- shuffle(numbers)로 1~45 숫자를 무작위 순서로 섞음. 이때 Fisher-Yates 알고리즘 사용함.
- 섞인 numbers 중 앞의 6개(winningNumbers)를 당첨 번호로 뽑고, 7번째 수(bonus)를 보너스 번호로 씀.
- 이 당첨번호들이 몇 개 들어있는지(matchCount), 보너스 번호가 들어있는지(bonusMatch) 확인해서 등수를 매김(1등~5등 or 꽝).
저 shuffle이 뭐하는 거지 궁금하면 Fisher-Yates 셔플 알고리즘 이 문서 확인하시길.
4. 숫자 한글 표기
function formatKoreanCurrency(amount) {
if (amount >= 100000000) {
return (amount / 100000000).toFixed(2) + "억";
} else if (amount >= 1000000) {
return (amount / 1000000).toFixed(0) + "백만";
} else if (amount >= 1000) {
return (amount / 1000).toFixed(0) + "천";
} else {
return amount + "";
}
}
이건 뭐 설명이 필요 한가?
더 쓰고 싶어도 쓸 게 없다.
후기
스벨트를 접한 후 이것 저것 만들고 있음.
로또 시뮬레이션 간단하지만 그 안에서도 개선할 요지가 있겠지?
물론 수요와 개선요청이 없다면 수정하지 않겠지만