Study/프로젝트

카드 짝 맞추기 게임 Project 4 (기능3 : 재시작 기능 수정과 카드 뒤집기)

zzinLee 2023. 8. 17. 16:26

재시작 기능 수정의 필요성

기존 코드에는 재시작 버튼을 누르면 화면의 요소들을 숨기거나 보여주기만 했다.

하지만 이제 기능이 도입되고, 게임화면이 복잡해졌으므로

재시작을 누름과 동시에 기능과 게임화면을 모두 처음으로 초기화 해주어야 한다.

따라서 앞으로도 기능이 추가됨에 따라 재시작 기능은 수정되어야 할 부분이 늘어날 것!

 

우선 현재까지의 추가된 기능과 변화는 우선 타이머시간초과 기능, 카드덱 랜덤 배열 기능,

div#timer, div#carddeck, div#gameover의 생성 및 소멸에 관련된 html요소 변화들이 있다.

(이때 카드덱 랜덤 배열 기능은 시작 버튼 클릭 시 새로 호출되는  turnIntoGame() 을 통해 자동적으로 발생. 재시작 버튼과 관련이 없다.)

 

재시작 버튼을 누르는 경우의수는 3가지 이다.

1. 게임 도중 재시작버튼을 누르는 경우 :

40초에서 0초로 향하는 인터벌이 진행되고 있으므로, 해당 인터벌 삭제해야 함.

또한 40초후에 게임오버 화면을 띄우는 셋타임아웃이 있으므로, 해당 타임아웃도 삭제해야 함.

이때 게임 도중 생겨난 해프닝이므로, turnIntoGame() 에서 재시작버튼에 이벤트리스너를 한번 더 할당해주어야 한다.

 

function turnIntoGame(){

  //1초 마다 시간을 체크
  let t=0;
  const updatetime = () => {
    lefttime.innerHTML = `${40-t}초`;
    t++;
  }
  //키자마자 타이머 시작
  updatetime();
  const updateTime = setInterval(updatetime, 1000);

  //40초 후 타임오버 되면 실행할 함수
  const timeout = () => {
    clearInterval(updateTime);
    lefttime.innerHTML = "0초";
    
    timeover.style.display = SHOW;
    carddeck.style.display = NOSHOW;
  }
  //setTimeout설정하기
  const timeOut = setTimeout(timeout, 40000);

  //카드를 랜덤배치
  shakingCard();

  //재시작 버튼 기능 추가(인터벌 타임아웃 초기화)
  restartbutton.addEventListener('click', function(){
    clearInterval(updateTime);
    clearTimeout(timeOut);
  })
}

 

2. 게임 성공 화면 이후 버튼을 누르는 경우: 아직 구현되지 않음.

 

3. 시간초과로 인한 게임 종료 화면 이후 버튼을 누르는 경우:

시간 초과 시, div#timer는 그대로 존재하고 div#carddeck 대신 div#timeover가 화면에 보여지고 있다.

따라서 재시작 버튼을 누르고 다시 시작 버튼을 눌러 게임화면이 등장하면,

div#timer는 정상적으로 보여지지만 div#carddeck은 보여지지 않고, div#timeover가 보여지고 있어 게임은 불가능하다.

 

다시 게임화면을 보여주어야 한다. 다시 카드덱을 보여주고, 타임오버 화면을 없애주어야 한다.

이는 어떤 시점에 재시작을 눌러도 실행되어야 하므로 기존 gameStart(event) 함수의

재시작 버튼에 이벤트리스너를 함수를 수정한다. 

 

function gameStart(event){
  const buttonId = event.target.id;
  switch(buttonId){
    case START:
      {
        startbutton.style.display = NOSHOW;
        beforegame.style.display = NOSHOW;
      
        restartbutton.style.display = SHOW;
        game.style.display = SHOW;
        
        turnIntoGame();//게임으로 진입

        break;
      }
    case RESTART:
      {
        startbutton.style.display = SHOW;
        beforegame.style.display = SHOW;
        
        restartbutton.style.display = NOSHOW;
        game.style.display = NOSHOW;

        timeover.style.display = NOSHOW;
        carddeck.style.display = SHOW;
        break;
      }
  }
}

 

현재 구현 상태 

 

게임화면흐름

 

 

 

카드를 클릭하면 커버가 제거되는 기능 (카드 뒤집기)

 

게임에 진입한 후 (turnIntoGame() 함수 내에)

40초 타이머(timeOut, updateTime), 카드 랜덤 배치(shakingCard()), 재시작버튼 기능을 구현하였다.

이 기능들과 더불어 카드덱 영역의 카드를 선택했을 때 카드의 뒷면이 카드의 앞면을 보여주는 기능을 구현하려고 한다.

turnIntoGame() 함수 내에 카드덱에 이벤트리스너를 할당한다.

 

turnIntoGame(){
/* ... 앞의 코드들 유지 */
  carddeck.addEventListener('click', fliptheCard);
}

 

fliptheCard(event){...}

우선 클릭한 부분이 div#carddeck 이므로, 이벤트 버블링에 의해 커버이미지가 선택될 것이다.

이때 클릭된 event.target이 카드 앞면의 이미지여서도 안되고, 카드들 사이의 구간이어서도 안된다.

따라서 1. event.target이 coverImg인지 확인해야 한다.

그리고 2. coverImg 이면, 카드를 뒤집어 앞면을 보이도록 한다.

즉, 커버이미지를 제거하고 카드이미지를 보이게 한다. 이때 z-index를 사용한다.

 

//커버인지 아닌지 확인할 수 있는 클래스 명을 변수로 추가
const COVER = 'coverImg';

function fliptheCard(event){
  const clickedcover = event.target;
  if(!clickedcover.classList.contains(COVER)) return;//커버가 아니면 함수 반환
	
  //클릭하면 그 커버는 cardImg보다 뒤로 가도록 쌓는다.
  clickedcover.style.zIndex = 0;
}

 

 

이 기능을 구현하고 나면, 문제가 하나 생긴다. 해결해보자. 

페이지를 reload 하지 않는 경우, 재시작/시작 버튼을 누른 게임화면에는 뒤집은 카드덱이 그대로 노출된다.

따라서 재시작 버튼을 눌렀을 때 이 앞면을 보이는 카드들 모두 뒷면으로 다시 뒤집어 주어야 한다.

즉 전부 커버이미지로 씌워야 한다는 것이다. 재시작 버튼의 기능을 하나 더 추가해야한다.

 

case RESTART:
      {
        startbutton.style.display = SHOW;
        beforegame.style.display = SHOW;
        
        restartbutton.style.display = NOSHOW;
        game.style.display = NOSHOW;

        timeover.style.display = NOSHOW;
        carddeck.style.display = SHOW;
		
        /* 카드 초기화 (뒷면으로) */
        for(const cover of covers){
          cover.style.zIndex = 1;
        }
        break;
      }

 

다음에 할 것

다음에 본격적으로, 카드를 뒤집고 쌍이 맞으면 앞면을 유지 쌍이 맞지 않으면 다시 뒷면으로 뒤집는 기능을 구현해보자.

이 기능이 구현되면, 쌍이 맞는 카드를 세는 기능

카드 쌍을 모두 맞추었을 때(쌍이 맞는 카드 : 8장) 게임 성공화면을 띄우는 기능을 구현할 수 있다.