PJH's Game World - 로또뽑기

박정호·2022년 12월 18일
0

Game Project

목록 보기
8/13
post-thumbnail

🚀 Start

로또 숫자 맞추기 게임이다. 유저가 로또 숫자 선택, 랜덤 로또 숫자 6개 출력, 일치/불일치 판별, 입력 input 유효성 검사, 모달창 구현을 하였다. 목업 툴을 통해 대략적으로 구상해본 화면이다.



✔️ 로또 숫자 입력

1️⃣ form : 1 ~ 45 중의 숫자를 입력.

2️⃣ myLottoList.length < 6 : 로또 숫자는 6개까지 입력 가능.

  • !myLottoList.includes(parseInt(value)) : 아직 입력하지 않은 숫자라면...
    • setMyLottoList: myLottoList 배열에 입력 숙자 저장.

3️⃣ myLottoList 배열 안의 입력된 숫자들을 오름차순 정렬하여 하나씩 출력.

  const [myLottoList, setMyLottoList] = useState<number[]>([]);
    ...
  const onSubmitForm = useCallback<(e: React.FormEvent) => void>(
    e => {
      e.preventDefault();

      if (myLottoList.length < 6) { // 2️⃣ 번
        if (!myLottoList.includes(parseInt(value))) {
          setMyLottoList(myLottoList.concat(parseInt(value)));
        } else {
          setWarning('숫자가 중복됩니다');
        }
      } else {
        setWarning('로또번호는 6개까지입니다');
      }

      setValue('');
    },
    [value]
  );


<form onSubmit={onSubmitForm}> // 1️⃣ 번
   <input ... min="1" max="45"/>
   <button type="submit" disabled={!value}></button>
</form>

...

{myLottoList // 3️⃣ 번
          .sort((a, b) => a - b)
          .map((lotto, i) => {
            return (
              <div className="mx-auto">
                <Ball key={`${i + 1}차 시도 : ${lotto}`} number={lotto} />
              </div>
            );
          })}

✔️ input 유효성검사

1️⃣ onlyNumber: 입력된 숫자가 0에서 9 사이의 숫자를 만족해야 한다는 정규식을 가진 replace된 문자열

2️⃣ setWarning: onlyKorean의 조건을 만족 못할 경우 경고 문자 출력.

3️⃣ disabled : 빈값 제출을 막기 위해 value값이 존재할 경우 제출되게 설정.

const [warning, setWarning] = useState('');
...

const onChangeValue = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const onlyNumber = e.target.value.replace(/[^0-9]/g, '');
      if (onlyNumber === '0' || onlyNumber > '45') {
        setWarning('1부터 45 범위 안에서 입력하세요');
      }
      if (!onlyNumber) {
        setWarning('숫자를 입력해주세요');
      }

      setValue(onlyNumber);
    },
    []
  );
...
<button type="submit" disabled={!value}></button>


✔️ 난수 생성

유저가 맞출 로또 숫자 6개 랜덤 생성.

1️⃣ 유저가 숫자 6개를 모두 입력하였다면, 당첨확인 버튼 클릭.

2️⃣ startLotto: 1초에 하나씩 랜덤 숫자 출력.

const lottoNumbers = useMemo(() => getWinNumbers(), []);
const [winNumbers] = useState(lottoNumbers);

...

 const startLotto = () => { // 2️⃣ 번
    for (let i = 0; i < winNumbers.length - 1; i++) {
      timeouts.current[i] = window.setTimeout(() => {
        setWinBalls(prevBalls => [...prevBalls, winNumbers[i]]);
        ...
      }, (i + 1) * 1000);
    }
    return () => {
      timeouts.current.forEach(v => {
        clearTimeout(v);
      });
    };
  };

...
{myLottoList.length === 6 && ( // 1️⃣ 번
      <button onClick={() => {startLotto(); ...}}
          {buttonText ? '당첨숫자' : '당첨 확인'}
       </button>
)}

랜덤생성기

const getWinNumbers = () => {
  const candidate = Array(45)
    .fill(null)
    .map((v, i) => i + 1);
  const shuffle = [];
  while (candidate.length > 0) {
    shuffle.push(
      candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0]
    );
  }
  const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);
  return [...winNumbers];
}


✔️ 일치/불일치 판별

만약 내가 입력한 숫자들이 담긴 myLottoList에 랜덤으로 생성된 숫자(winNumbers[i])가 포함되어있다면 result를 1씩 증가.

const startLotto = () => {
  		...
	myLottoList.includes(winNumbers[i]) &&
    setResult(prevResult => (prevResult += 1));
}

✔️ Ball 출력

const Ball: FC<{ number: number }> = ({ number }) => {
  let background;
  if (number <= 10) {
    background = '#ff6380';
  } else if (number <= 20) {
    background = '#fca272';
  } else if (number <= 30) {
    background = '#fff894';
  } else if (number <= 40) {
    background = '#1773ac';
  } else {
    background = '#acc383';
  }
  return (
    <div style={{ background }}> {number} ![](https://velog.velcdn.com/images/pjh1011409/post/03041fb5-0674-4623-bf8a-e6c54a37fc77/image.gif)
</div>
  );
};

export default Ball;


🖥 실제 구현 화면

profile
기록하여 기억하고, 계획하여 실천하자. will be a FE developer (HOME버튼을 클릭하여 Notion으로 놀러오세요!)

0개의 댓글