2048 게임 만들기 - 타일 병합 로직

지은·2023년 7월 4일
0

🚂 토이 프로젝트

목록 보기
7/10
post-custom-banner

타일 병합 로직

tile.js

타일을 이동시키는 것까지 구현했고, 이제 두 타일이 숫자가 같은 경우 병합시키는 부분을 구현할 차례다.

먼저 nextPosition라는 변수를 만들어준다. 이 변수는 두 타일이 병합되어 하나의 타일이 되었을 때 그 타일의 위치가 될 것이다.

기본 로직은 현재 타일과 이전 타일이 같은 줄에 있다면

isOnSameLine 변수는 현재 타일과 이전 타일이 같은 행/열에 있는지 확인하고 true/false를 가진다.

  • 수직 이동이라면 같은 열에 있는지(= 같은 x 값을 가지는지) 확인하고,
  • 수평 이동이라면 같은 행에 있는지(= 같은 y 값을 가지는지) 확인한다.

만약 nextPosition이 0이 아니고, 두 타일이 같은 줄에 있다면,

  • 수직 이동의 경우, 현재 타일의 y값을 nextPosition으로 변경한다.
  • 수평 이동의 경우, 현재 타일의 x 값을 nextPosition으로 변경한다.
  • 그러고나서 nextPosition의 값을 1씩 증감시킬 건데, 위/왼쪽 이동이라면 + 1을, 아래/오른쪽 이동이라면 -1을 해준다.
export function slideTile(x, y, { tileList, setTileList }) {
	// 생략..
  	let nextPosition = 0;
    const newTileList = [...sortedTileList]; // `sortedTileList`를 복사해 `newTileList`를 만들어준다.

    for (let i = 0; i < newTileList.length; i++) {
      const currentTile = newTileList[i];  // 현재 타일
      const prevTile = newTileList[i - 1]; // 이전 타일
      const nextTile = newTileList[i + 1]; // 다음 타일
      
      const isOnSameLine = isVerticalMove ? currentTile.x === prevTile?.x : currentTile.y === prevTile?.y;

    if (nextPosition && isOnSameLine) {
      if (isVerticalMove) {
        currentTile.y = nextPosition;
      } else {
        currentTile.x = nextPosition;
      }
      isMinus ? nextPosition += 1 : nextPosition -=1;
    } else {
      nextPosition = 0;
    }
    // ...

isMergable 변수는 현재 타일과 다음 타일의 value를 비교해 같은 값인지 확인하고, 두 타일이 같은 줄에 있는지 확인한다.
isMergabletrue라면, 새로운 타일을 만들어 현재 타일과 같은 위치에(같은 x, y 할당) 현재 타일의 value를 2배로 하여 새로운 타일리스트에 푸쉬해준다.
그리고 기존의 두 타일은 isDisabled 속성을 true로 바꿔주어 화면에 렌더링되지 않도록 해준다.

그리고 두 타일이 병합될 때, nextPosition의 값을 업데이트해줘야 한다.

  • 수직 이동인 경우, nextPosition을 다음 타일의 y값으로,
    그리고 다음 타일은 현재 타일와 겹치게 되므로 y값을 현재 타일의 y값으로 변경해준다.
  • 수평 이동인 경우, nextPosition의 값을 다음 타일의 x 값으로 업데이트해준다.
    다음 타일의 x값도 현재 타일의 x값으로 변경해준다.
	// ...
    const isMergable = 
          currentTile.value === nextTile?.value && 
          isVerticalMove ? currentTile.x === nextTile?.x : currentTile.y === nextTile?.y;

    if (isMergable) {
      const tile = makeTile(newTileList);
      tile.x = currentTile.x;
      tile.y = currentTile.y;
      tile.value = currentTile.value * 2;
      newTileList.push(tile);

      currentTile.isDisabled = true;
      nextTile.isDisabled = true;
    }
	
	if (isVerticalMove) {
        nextPosition = nextTile.y;
        nextTile.y = currentTile.y;
    } else {
      nextPosition = nextTile.x;
      nextTile.x = currentTile.x;
    }
  }

  setTileList(newTileList);
}


타일 이동시 타일 추가

마지막으로 유저가 타일을 이동할 때마다 새로운 타일이 추가되게 해야 한다.
기존의 useHandleKeyboard 훅을 아래처럼 변경하여 slide한 후에 새로운 타일을 만들어 setTileList 함수에 전달했다.

useHandleKeyboard.js

function moveUp() {
    slideAndAdd({ x: 0, y: -1 });
  }

  function moveDown() {
    slideAndAdd({ x: 0, y: 1 });
  }
  function moveLeft() {
    slideAndAdd({ x: -1, y: 0 });
  }
  function moveRight() {
    slideAndAdd({ x: 1, y: 0 });
  }

  function slideAndAdd({ x, y }) {
    const slidedTileList = slideTile({ x, y, tileList });
    const newTile = makeTile(slidedTileList);
    slidedTileList.push(newTile);
    setTileList(slidedTileList);
  }

profile
블로그 이전 -> https://janechun.tistory.com
post-custom-banner

4개의 댓글

comment-user-thumbnail
2023년 7월 5일

기대가 됩니다 ~~

답글 달기
comment-user-thumbnail
2023년 7월 8일

오 완성인가용 !!! 고생하셨습니다 ㅎㅎ

답글 달기
comment-user-thumbnail
2023년 7월 9일

너무 재밌어서 저도 모르게 계속 하고 있네요 ㅋㅋㅎㅎ

답글 달기
comment-user-thumbnail
2023년 7월 9일

잘만드셨네요! 좋은 기획같습니다 ㅎㅎ

답글 달기