[JS] 가위바위보

게코젤리·2022년 9월 30일
0
post-custom-banner

개요

가위바위보 게임, 객체리터럴, setInterval
강의 : https://youtu.be/5aIQ7EAfosc

순서도

html

<div id="computer"></div>
<div>
  <button id="scissors" class="btn">가위</button>
  <button id="rock" class="btn">바위</button>
  <button id="paper" class="btn"></button>
</div>
<div id="score">0</div>

javascript

  1. 0.05초마다 computerChoice의 가위바위보 값을 바꾸고 그 값을 화면에 표시
  • 객체 값을 가져올 때 주의할 점
$computer.style.background = `url(${IMG_URL}) ${rspX[computerChoice]} 0`;
// 이 부분에서 rspX.computerChoice로 쓸 경우 rspX."rock"이 된다. rspX[computerChoice]는 rspX["rock"]이 되기 때문에 후자로 쓰는 게 맞다.
  • setInterval은 setTimeout로 바꿀 수 있다.(하지만 setInterval 쓰는 게 나을 듯)
// setInterval
setInterval = (() => {
	console.log('hi')
}, 1000);
// setTimeout으로 바꾸기!
const hi = () => {
	console.log('hi');
	setTimeout(hi, 1000);
}
setTimeout(hi, 1000);
const $computer = document.querySelector("#computer");
const $scissors = document.querySelector("#scissors");
const $rock = document.querySelector("#rock");
const $paper = document.querySelector("#paper");
const $score = document.querySelector("#score");
const IMG_URL = "./rsp.png";
$computer.style.background = `url(${IMG_URL}) 0 0`;
$computer.style.backgroundSize = `auto 200px`;

const rspX = {
  scissors: '0',
  rock: '-220px',
  paper: '-440px'
};

let computerChoice = 'scissors';
const changeComputerHand = () => {
  if(computerChoice === 'scissors'){
    computerChoice = 'rock';
  } else if(computerChoice === 'rock'){
    computerChoice = 'paper';
  } else if(computerChoice === 'paper'){
    computerChoice = 'scissors';
  }
  $computer.style.background = `url(${IMG_URL}) ${rspX[computerChoice]} 0`;
  $computer.style.backgroundSize = `auto 200px`;
}

let intervalId = setInterval(changeComputerHand, 50);
  1. 가위바위보 버튼 클릭했을 때 돌아가는 값, 그림 멈추기
  • clearInterval, clearTimeout:
    setTimeout, setInterval은 숫자로 된 id값을 반환한다.
    clearInterval, clearTimeout를 활용하면 그 값을 인자로 사용해 각각의 코드를 제거할 수 있다.
  • 아래 코드의 경우 에러가 생길 수 있다. 예를 들어 유저가 1초안에 버튼을 5번 연달아 클릭하면 clickBtn 함수 안에 있는 setTimeout과 setInterval이 5개 생기고 각각의 id를 갖는다. 하지면 변수 intervalid에 저장된 값은 마지막 id 하나뿐이기 때문에 5번째 setInerval만 삭제되고 나머지 4는 삭제되지 않고 영원히 실행된다.
const clickBtn = () => {
  clearInterval(intervalId);
  setTimeout(() => {
    intervalId = setInterval(changeComputerHand, 50);
  }, 1000);
}

$scissors.addEventListener('click', clickBtn);
$rock.addEventListener('click', clickBtn);
$paper.addEventListener('click', clickBtn);
  1. 오류 고치기
    clickable이라는 변수를 생성해 그 값의 true, false에 따라 동작이 구분되도록 했다. 그리고 두 가지 방법을 더 적어두었다.
    1) setTimeout 안에서 한번 더 clearInterval -> 1초 사이에 작동되었을 setInterval을 제거
const clickBtn = () => {
  clearInterval(intervalId);
  setTimeout(() => {
    clearInterval(intervalId);
    intervalId = setInterval(changeComputerHand, 50);
  }, 1000);
}

2) removeEventListener를 활용 -> 1초 사이에 연달아 클릭해도 이벤트가 작동되지 않음(오류 가능성이 높기 때문에 권장하지 않음.)

const clickBtn = () => {
  clearInterval(intervalId);
  $scissors.removeEventListener('click', clickBtn);
  $rock.removeEventListener('click', clickBtn);
  $paper.removeEventListener('click', clickBtn);
  setTimeout(() => {
    intervalId = setInterval(changeComputerHand, 50);
    $scissors.addEventListener('click', clickBtn);
    $rock.addEventListener('click', clickBtn);
    $paper.addEventListener('click', clickBtn);
  }, 1000);
}
// 내부코드가 실행되지 않게
let clickable = true;
const clickBtn = () => {
  if (clickable) {
    clearInterval(intervalId);
    clickable = false;
    setTimeout(() => {
      clickable = true;
      intervalId = setInterval(changeComputerHand, 50);
    }, 1000);
  }
}
  1. 승부 판단
  • includes()를 활용한 조건문
if(diff === 1 || diff === -2){}
//
if ([1, -2].includes(diff)) {}
const clickBtn = (e) => {
  if (clickable) {
    clearInterval(intervalId);
    clickable = false;
    const myChoice =
          e.target.textContent === "바위" ?
          "rock" :
    event.target.textContent === "가위" ?
          "scissors" :
    "paper";

    const scoreTable = {
      rock: 0,
      scissors: 1,
      paper: -1,
    };

    const diff = scoreTable[myChoice] - scoreTable[computerChoice];
    let message;

    if ([2, -1].includes(diff)) {
      message = "승리";
      myScore += 1;
    } else if ([-2, 1].includes(diff)) {
      message = "패배";
      computerScore += 1;
    } else if (diff === 0) {
      message = "무승부";
    }

    if (myScore >= 3) {
      $score.textContent = `나의 승리 ${myScore}:${computerScore}`;
    } else if (computerScore >= 3) {
      $score.textContent = `컴퓨터의 승리 ${myScore}:${computerScore}`;
    } else {
      $score.textContent = `${message} ${myScore}:${computerScore}`;

      setTimeout(() => {
        clickable = true;
        intervalId = setInterval(changeComputerHand, 50);
      }, 1000);
    }
  }
post-custom-banner

0개의 댓글