로또 시뮬레이션 제작 회고

안녕하세요 뭐라도 만드는 오물개입니다.

이번엔 스벨트로 만든 두 번째 서비스로 만만한 로또 시뮬레이션을 만들었음.

역시나 바로 시작.


제작배경

인간은 간사한 동물임. 새롭고 어려운 길을 택하기 보단, 알고 있는 쉬운 길을 택하는게 인간임.

나 역시 인간이라 뭐 만들 지 고민 하다 새로운 언어를 배우면 매 번 만드는 로또 시뮬레이션을 선택 함.

아 전에는 단순 로또 번호 추출기 정도만 만들었는데 이번엔 시뮬레이션 기능을 추가했음.


기획

  1. 로또번호를 생성하자.
  2. 사용자가 생성한 로또 번호를 기준으로 시뮬레이션을 하자.
  3. 느리면 답답하니 배속 기능을 넣자
  4. 숫자로 적으면 가독성이 떨어지니 한국식으로 표기하자.
  5. 나름 구색을 갖춰야 하니 역대 로또 번호를 보여주자.

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개를 만드는 방법은 몇 가지 있다.

  1. 뽑은 숫자 배열에 넣기전 includes 함수를 사용해 중복 여부 확인하고 넣기
  2. 뽑은 숫자를 Set에 담아 6개 될 때 까지 넣기
  3. 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 };
 
}

간단하게 코드 설명함.

  1. numbers라는 배열을 [1, 2, 3, …, 45] 이렇게 만듬.
  2. shuffle(numbers)로 1~45 숫자를 무작위 순서로 섞음. 이때 Fisher-Yates 알고리즘 사용함.
  3. 섞인 numbers 중 앞의 6개(winningNumbers)를 당첨 번호로 뽑고, 7번째 수(bonus)를 보너스 번호로 씀.
  4. 이 당첨번호들이 몇 개 들어있는지(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 + "";
	}
}

이건 뭐 설명이 필요 한가?

더 쓰고 싶어도 쓸 게 없다.


후기

스벨트를 접한 후 이것 저것 만들고 있음.

로또 시뮬레이션 간단하지만 그 안에서도 개선할 요지가 있겠지?

물론 수요와 개선요청이 없다면 수정하지 않겠지만