5. 가위바위보

HumbleMincho·2024년 7월 2일

2021.04.30
소스코드: rsp.html


플로우


배운 개념

  1. style.background
  2. setInterval
  3. 버그 해결
    - 가정
    - 해결 방법

style.background

computer.style.background=url(computer.style.background = `url({IMG_URL}) 0 0`;
스타일의 background는 이미지 X좌표 Y좌표값을 입력할 수 있다.

const rspX = {
  scissors: "0",
  rock: "- 230px",
  paper: "-440px",
};

위와 같이 공통된 속성을 지닌 변수의 모임은 객체로 묶어주는 것이 현명하다.

$computer.style.background = `url(${IMG_URL}) ${rspX[computerChoice]} 0`;
$computer.style.backgroundSize = "auto 200px";

rspX.computerChoice하면 안된다. 왜냐하면 rspX객체엔 computerChoice라는 문자열 속성이 없기 때문에 rspX[computerChoice]로 선택해야 한다.

background를 수정할 때마다 size도 초기화되기 때문에 항상 background와 backgroundSize는 붙어있어야 한다.


setInterval(함수,반복간격(ms));

setInterval함수는 return값이 존재한다. 그 값은 타이머에 대한 아이디(숫자)로 해당 값을 사용하여 타이머를 제거할 수 있다.
setInterval을 취소할 수 있는 방법으로 clearInterval을 제공한다.
let ID= setInterval(함수,ms)
setTimeout함수도 clearTimeout으로 제거할 수 있지만 setTimeout함수 내의 인수로 넣은 함수가 실행되기 전에 clearTimeout을 호출해야 한다.

버그

const clickButton = () => {
  //버튼을 눌렀을 때
  clearInterval(intervalId); // 타이머 멈춤.
  //점수 계산 및 화면 표시
  setTimeout(() => {
    intervalId = setInterval(changeComputerHand, 50); //타이머를 만들 때마다 변수에 저장한 후에 clearInterval해야 한다.
  }, 1000); //1초 뒤에 다시 setInterval.
};
$rock.addEventListener("click", clickButton);
$scissors.addEventListener("click", clickButton);
$paper.addEventListener("click", clickButton);
  • setTimeout설정값 1초 내에 여러 번 클릭하면 그림이 빠르게 돌아간다. 그 후에 버튼을 클릭하면 그림이 멈추지 않는다. 버튼을 클릭할 떄마다 각각 setTimeout타이머가 여러 개 실행되기 때문이다.
  • 버튼클릭을 하면 clearInterval을 수행하므로 문제없다고 생각할 수도 있다.
    하지만 버튼은 setInterval을 멈추는 clearInterval을 수행할 뿐 setTimeout을 멈추는 clearTimeout을 수행하지는 않아서 버튼을 누른 횟수만큼 setTimeout타이머가 실행되고 각각1초 뒤에 setInterval을 하게 되어 그림이 빠르게 돌아가는거다.

- 가정

  1. clickButton을 1초 내에 10번을 눌렀다.
  2. interval의 ID인덱스로 따지면 10개가 생기지만 덮어씌우는 방식이기 때문에 마지막 인덱스를 intervalID변수에 넣고 있다.
  3. 1초 뒤에 버튼을 클릭하면 마지막 인덱스만 클리어된다.

- 해결 방법

  1. clearInterval함수 한번 더 사용.(추천) clickButton이 실행되는 최초에 한번 클리어하고 1초 뒤 실행되는 setTimeout에 한번 더 클리어를 하면 1초루프동안마다 클리어가 반복되므로 해결됨.
const clickButton = () => {
  clearInterval(intervalId);

  setTimeout(() => {
    clearInterval(intervalId); //추가.
    intervalId = setInterval(changeComputerHand, 50);
  }, 1000);
};
$rock.addEventListener("click", clickButton);
$scissors.addEventListener("click", clickButton);
$paper.addEventListener("click", clickButton);
  1. removeEventListener메서드 사용(비추천: 실수하기 쉬움)
    이유: func() !== func()라는(객체 참조관계) 개념을 사용하여 addEventListener와 removeEventListener내의 해결 법: 함수가 같아야 제거가 되는데 같지 않기 때문에 제거가 안되는 점을 놓치기 때문.
    func() === func()값이 false를 반환하기 때문에 객체(함수)를 번수에 넣으면 비교할 수 있다.
    참고) 참조관계를 유지하고 싶으면 변수에 넣으면 된다!
const clickButton = () => {
  $rock.removeEventListener("click", clickButton); //추가.
  $scissors.removeEventListener("click", clickButton); //추가.
  $paper.removeEventListener("click", clickButton); //추가.
  //clickButton이 실행되는 최초에 한번 제거

  setTimeout(() => {
    $rock.addEventListener("click", clickButton); //추가.
    $scissors.addEventListener("click", clickButton); //추가.
    $paper.addEventListener("click", clickButton); //추가.
    //1초 뒤 실행되는 setTimeout마다 실행
    intervalId = setInterval(changeComputerHand, 50);
  }, 1000);
};
$rock.addEventListener("click", clickButton);
$scissors.addEventListener("click", clickButton);
$paper.addEventListener("click", clickButton);
  1. 플레그 변수 사용(추천)
let clickable = true; //추가.
const clickButton = () => {
  if (clickable) {
    clearInterval(intervalId);
    clickable = false; //추가.
    setTimeout(() => {
      clickable = true; //추가.
      intervalId = setInterval(changeComputerHand, 50);
    }, 1000);
  }
};
  • diff === '고양이' || diff === '사자' || diff === '강아지' || diff === '거북이'
    위와 같은 경우는 아래와 같이 바꿀 수 있다.
    ['고양이','사자','강아지','거북이']. includes(diff)
    또는
    ['고양이','사자','강아지','거북이']. indexOf(diff) > -1
profile
최고의 효율을 창출하기 위해 겸손히 노력합니다.

0개의 댓글