[JS] Day 30 - Whack A Mole

jiseong·2021년 9월 16일
0

T I Learned

목록 보기
71/291
post-custom-banner

demo:

demo사이트

github:

Danji-ya


Day 30 - Whack A Mole

🎯 기능 요구사항

  • 두더지 잡기 게임을 구현한다.
  • 두더지가 랜덤하게 구멍에서 출현해야한다.
  • 각각의 두더지의 출몰 시간은 달라야한다.
  • 두더지를 클릭하면 점수가 올라야한다.
  • 게임 제한시간은 10초로 정하며 게임이 종료되면 다시 원래대로 돌아가야한다.

🚀 배운 점

Math.random()

우선, 각 각의 두더지가 랜덤하게 구멍에서 출현하고 출몰 시간을 달리하기 위해서 Math.random() 함수를 이용했다.

게임 시작시, randomTimer 함수가 작동되며 두더지의 출몰시간을 랜덤하게 정한다.

const random = Math.floor(Math.random() * (max - min) + min);

randomHole 함수 내부에서 동일한 구멍에서 나오지 않도록 반복하여 돌려 출몰장소를 정한 뒤 클래스를 추가하여 우선적으로 두더지가 나오게 했다.

function randomHole() {
  const idx = Math.floor(Math.random() * holes.length);

  if(idx === lastIdx) return randomHole();

  lastIdx = idx;
  return idx;
}

const idx = randomHole();
upMole(idx);

그 후, 정해진 출몰시간이 지나고나면 나와있던 두더지를 숨기고 다음 두더지를 출몰시키는 방식으로 구현하였다.

이러한 방식으로 작성해야 한마리 씩 출몰하고 어떤 두더지가 올라오고 바로내려가는 반면, 어떤 두더지는 올라오고 조금있다 내려가는 방식을 구현할 수 있었다.

function randomHole() {
  const idx = Math.floor(Math.random() * holes.length);

  if(idx === lastIdx) return randomHole();

  lastIdx = idx;
  return idx;
}

function randomTimer(min, max) {
  const random = Math.floor(Math.random() * (max - min) + min);
  const idx = randomHole();

  upMole(idx);

  timer = setTimeout(function(){
    downMole(idx);

    return randomTimer(minTime, maxTime);
  }, random);
}

isTrusted

event.isTrusted를 사용하면 이벤트가 스크립트를 통해 생성된 이벤트인지 ‘진짜’ 사용자 액션을 통해 생성된 이벤트인지 알 수 있기 때문이 해당 방식을 이용하여 두더지를 잡았는지 판별할 수 있다.

function getScore(e) {
  if(!e.isTrusted) return;

  this.parentNode.classList.remove('up');
  scoreBoard.textContent = ++score;
}

[...moles].map(mole => mole.addEventListener("click", getScore));

💻 최종코드

(function(){
    const holes = document.querySelectorAll('.hole');
    const scoreBoard = document.querySelector('.score');
    const moles = document.querySelectorAll('.mole');
    const startBtn = document.querySelector('button');

    const minTime = 300;
    const maxTime = 800;
    const spendTime = 10000;

    let timer;
    let finishTimer;
    let lastIdx;
    let score = 0;

    function randomHole() {
        const idx = Math.floor(Math.random() * holes.length);

        if(idx === lastIdx) return randomHole();

        lastIdx = idx;
        return idx;
    }

    function randomTimer(min, max) {
        const random = Math.floor(Math.random() * (max - min) + min);
        const idx = randomHole();

        upMole(idx);

        timer = setTimeout(function(){
            downMole(idx);

            return randomTimer(minTime, maxTime);
        }, random);
    }

    function downMole(idx) {
        holes[idx].classList.remove('up');
    }

    function upMole(idx) {
        holes[idx].classList.add('up');
    }

    function startGame() {
        if(timer) clearGame();
        
        randomTimer(minTime, maxTime);

        finishTimer = setTimeout(function(){
            console.log('시간 끝');
            clearGame();
        }, spendTime);
    }

    function clearGame() {
        downMole(lastIdx);
        clearTimeout(timer);
        clearTimeout(finishTimer);

        scoreBoard.textContent = 0;
        score = 0;
    }

    function getScore(e) {
        if(!e.isTrusted) return;

        this.parentNode.classList.remove('up');
        scoreBoard.textContent = ++score;
    }

    startBtn.addEventListener("click", startGame);
    [...moles].map(mole => mole.addEventListener("click", getScore));
})();
post-custom-banner

0개의 댓글