슬라이딩 퍼즐 게임 만들기 #4/4 (완성 및 리팩토링)

천둥상어

·

2024. 1. 12. 13:02

반응형

슬라이딩퍼즐_썸네일

정답 확인 함수 생성

타일 객체는 answerIndex 와

currentIndex 변수를 가지고 있다.

 

answerIndex는 init() 함수에서 타일 생성시

for문의 i값을 넣어주고 있는데

이 값이 자신의 정위치 인덱스 값이다.

 

currentIndex는 현재 타일의 인덱스 값이므로

answerIndex와 currentIndex의 값이 동일하다면

해당 타일은 정위치에 있다고 볼 수 있다.

 

위 조건으로 모든 타일이 정위치에 있는지

체크 하는 함수를 하나 만들었다.

함수명은 checkAnswer 이다.

 

로직은 단순하다.

bClear 란 이름의 boolean 타입 변수를 선언한다.

디폴트 값은 true 이다.

 

그 다음 for문에서는 각 타일이 정위치 인지 판단한다.

만약 하나라도 정위치가 아니라면 for문을 빠져나오고

bClear 값을 false로 갱신 할 것이다.

 

마지막 if 문에서는 bClear 값이 true 라면

퍼즐을 푼 것으로 판단하고 조건문을 실행한다.

 

  checkAnswer()
  {
    let bClear = true;
    for (let i = 0; i < this.TOTAL_CELL; i++) {
      // 각 타일이 정위치에 있는지 확인
      // 만약 하나라도 정위치가 아니라면 bClear는 false 하고
      // for문 빠져나갈 것.
    }

    // bClear 가 true라면 모든 타일 정위치
    if(bClear)
    {
      console.log('Game Clear');
    }
  }

 

타일 클래스에 정위치인지 판단후 돌려주는 함수 추가

타일이 정위치 인지 판단해서 값을 돌려주는

함수를 Tile 클래스에 생성한다.

tile.js

자신의 anwerIndex 와 currentIndex 를 비교해서

동일하면 true를 반환하고 아니면 false를 반환한다.

  getIsCorrectPosition()
  {
    const bool = (this.answerIndex === this.currentIndex)? true : false;
    return bool;
  }

 

checkAnswer 함수 로직 완성 및 호출

cheackAnwer 의 for문 안에서 각 타일의 정위치를 값을 받아오자.

만약 하나라로 false가 나오면

bClear값을 false 처리 후 for문을 빠져나간다.

하나라면 정위치가 아니면 그 다음 타일의 정위치 여부는

더 이상 판단할 필요가 없기 때문이다.

for문 코드 추가

for (let i = 0; i < this.TOTAL_CELL; i++) {
      // 각 타일이 정위치에 있는지 확인
      // 만약 하나라도 정위치가 아니라면 bClear는 false 하고
      // for문 빠져나갈 것.
      const tile = this["tile_" + i];
      const bool = tile.getIsCorrectPosition();
      if(!bool)
      {
        bClear = false;
        break;
      }
    }

if문 코드 추가

모든 타일이 정위치에 있다면 bClear 값은 바뀌지 않고

true 상태일 것이다.

true라면 비어 있는 타일을 보여주자.

    // bClear 가 true라면 모든 타일 정위치
    if(bClear)
    {
      this["tile_" + this.emptyIndex].setVisible(true);
      console.log('Game Clear');
    }

함수 호출

함수는 타일 클릭시 호출하면 된다.

hnClick 함수 제일 아래에 추가한다.

  hnClick(evt)
  { 
    // 생략
    this.checkAnswer();
  }

 

이제 실행해서 퍼즐을 풀면

비어 있는 타일이 보여지게 된다.

퍼즐을 풀면 비어 있는 타일이 보여진다.

 

코드 리팩토링

슬라이딩 퍼즐의 로직은 모두 구현 되었다.

하지만 최적화가 필요한 부분이 있다.

 

moveTile 함수에서 타일의 재배치가 일어나는 부분과

checkAnswer를 호출하는 부분이다.

 

moveTile 리팩토링

지금 로직은 타일에 이동이 발생하면

모든 타일을 재배치 하고 있다.

 

위치를 바꾸는 두 타일만 자리를 바꾸도록

코드 개선한다.

 

기존의 for문을 이용한 재배치 코드는

주석 처리 한다.

 

타일의 currentIndex값을 알면

퍼즐내 자신의 위치를 계산 할 수 있다.

곱해주는 100은 타일의 너비, 높이 값이다.

  • x값
    currentIndex 가 row(0~3)보다 작다면 currentIndex * 100 을 해주고
    그 외에는 나머지 값에(currentIndex % row)에 * 100을 해주면 된다.
  • y값
    currentIndex 가 row(0~3)보다 작다면 가장 윗줄이므로 0을 주고
    그 외에는 몫의 버림값에 (Math.trunc(currentIndex/column)) * 100을 해주면 된다.

y값의 경우 아래 조건 하나만 적용해도 상관 없다.

    // 비어 있는 타일 인덱스를 갱신한다
    this.emptyIndex = currentIndex;

    const currentTile = this.tileArr[currentIndex];
    currentTile.x = 
    (currentTile.currentIndex < this.row)? currentTile.currentIndex * 100 : currentTile.currentIndex % this.row * 100;

    currentTile.y = 
    (currentTile.currentIndex < this.row)? 0 : Math.trunc(currentTile.currentIndex / this.column) * 100;

    const emptyTile = this.tileArr[emptyIndex];
    emptyTile.x = 
    (emptyTile.currentIndex < this.row)? emptyTile.currentIndex * 100 : emptyTile.currentIndex % this.row * 100;

    emptyTile.y = 
    (emptyTile.currentIndex < this.row)? 0 : Math.trunc(emptyTile.currentIndex / this.column) * 100;
    
    /*
    // 변경된 배열순으로 타일을 재배치 한다.
    let posX = 0; //타일 x값
    let posY = 0; //타일 y값

    for (let i = 0; i < this.TOTAL_CELL; i++) {
      const tile = this.tileArr[i];
      tile.position.set(posX, posY);
      posX += 100;

      if ((i + 1) % this.row == 0) {
        posX = 0;
        posY += 100;
      }
    }
    */

 

checkAnswer 호출 리팩토링

해당 함수는 클릭시

항상 호출하게 되어 있다.

 

checkAnswer는 for문을 돌면서

모든 타일의 정위치 여부를 판단하기에

클릭시마다 호출하는건 성능상 좋지 않다.

 

적어도 이동된 타일의 참/거짓 여부를

판단하고 호출한다면

불필요한 코드 호출을 막을 수 있다.

 

다음과 같이 이동된 타일의 위치가

정위치인 경우에만 checkAnswer를 

호출하도록 개선한다.

 hnClick(evt)
 
    //this.checkAnswer();
    const currentTile = this.tileArr[emptyIndex];
    console.log(currentTile.getIsCorrectPosition());
    if(currentTile.getIsCorrectPosition()) this.checkAnswer();
  }

 

마무리

슬라이딩 퍼즐 게임 만들기는 여기까지다.

알고리즘만 적용했기에 게임으로서 완성도는 부족하다.

살을 붙이는 작업은 pixi.js에 대한 이해가 필요하기에

pixi.js에 대한 포스팅을 어느 정도 진행하고 하는 게 맞을 것 같다.

 

작업한 코드는 아래 주소에서 확인 할 수 있다.

반응형