2048 게임 스크립트 심층 분석: 프론트엔드 알고리즘과 구현 전략

웹 기반 게임 개발은 단순히 로직을 짜는 것을 넘어, 브라우저의 특성과 사용자 경험(UX)을 모두 고려해야 하는 정밀한 작업입니다. 2048 게임의 실제 코드를 통해 핵심 알고리즘을 분석해 보겠습니다.

1. 효율적인 타일 이동 로직: 방향의 일반화

2048 게임에서 가장 복잡한 부분은 상하좌우 네 방향으로의 이동과 숫자 병합입니다. 이를 각각 구현하면 코드가 비대해지고 유지보수가 힘들어집니다.

// 핵심 아이디어: 모든 이동을 '왼쪽 이동'으로 치환하여 처리
function processMove(direction) {
  let moved = false;
  for (let i = 0; i !== 4; i++) {
    let line = [];
    for (let j = 0; j !== 4; j++) {
      // 방향에 따라 r, c 인덱스를 계산하여 라인 추출
      let r = (direction === 'L' || direction === 'R') ? i : (direction === 'U' ? j : 3 - j);
      let c = (direction === 'U' || direction === 'D') ? i : (direction === 'L' ? j : 3 - j);
      if (g2048_board[r][c]) line.push(g2048_board[r][c]);
    }
    // 추출된 line을 왼쪽으로 미는 로직(slideAndMerge) 하나로 통일
    // ... 후속 처리
  }
}
  • 알고리즘 분석: 위 코드는 방향에 상관없이 4×4 행렬에서 특정 방향의 ‘한 줄’을 뽑아내는 추상화가 핵심입니다.
  • 엔지니어링 의도: 중복 코드를 제거(DRY 원칙)하고, 이동 로직의 버그를 한 곳에서만 수정하면 모든 방향에 적용되도록 설계되었습니다.

2. Slide & Merge 알고리즘: 2단계 처리

타일이 합쳐질 때는 두 가지를 고려해야 합니다. 중간에 빈칸이 없어야 하고, 같은 숫자는 한 번의 이동에서 한 번만 합쳐져야 합니다.

function slideAndMerge(line) {
  let result = [];
  let moved = false;
  for (let i = 0; i !== line.length; i++) {
    // 인접한 두 타일의 값이 같고, 아직 합쳐지지 않았다면 병합
    if (i !== line.length - 1 && line[i].val === line[i + 1].val && !line[i].merged) {
      let t1 = line[i];
      t1.val *= 2; // 값 업데이트
      result.push(t1);
      i++; // 다음 타일은 건너뜀
      moved = true;
    } else {
      result.push(line[i]);
    }
  }
  return { newLine: result, moved: moved };
}
  • 알고리즘 분석: 탐욕 알고리즘(Greedy Algorithm)적 접근을 사용합니다. 앞에서부터 순차적으로 검사하며 최선의 병합을 즉시 수행합니다.
  • 엔지니어링 의도: merged 플래그를 사용하여 2-2-2-2가 한 번에 8이 되는 현상을 방지하고, 게임의 오리지널 규칙을 정확히 구현합니다.

3. 확률 기반의 난수 생성 (Spawn Logic)

게임의 밸런스를 결정하는 새로운 타일 생성 로직입니다.

function addRandomTile() {
  var empty = [];
  for (var r = 0; r !== 4; r++) {
    for (var c = 0; c !== 4; c++) {
      if (!g2048_board[r][c]) empty.push({r: r, c: c});
    }
  }
  if (empty.length !== 0) {
    var pos = empty[Math.floor(Math.random() * empty.length)];
    // 90% 확률로 2, 10% 확률로 4 생성
    var val = Math.random() < 0.9 ? 2 : 4; 
    // ... 타일 생성 및 DOM 추가
  }
}
  • 알고리즘 분석: 빈 공간(null)을 먼저 전수조사한 뒤, 그중 하나를 무작위로 선택하는 샘플링(Sampling) 기법을 사용합니다.
  • 엔지니어링 의도: 단순 랜덤 좌표 생성이 아니라 ‘빈칸 중 하나’를 보장함으로써 연산 횟수를 줄이고 무한 루프를 방지합니다.

4. 워드프레스 호환성 최적화 (Environment Adaption)

이 게임의 가장 독특한 점은 배포 환경에 따른 코드 수정입니다.

// 표준 방식: for (let i = 0; i < 4; i++)
// 수정 방식: for (var r = 0; r !== 4; r++)
  • 문제 해결: 워드프레스의 HTML 파서가 < 기호를 태그로 인식해 코드를 파괴하는 현상을 막기 위해 모든 비교 연산자를 !== (Not Equal)로 교체했습니다.
  • 엔지니어링 의도: 프론트엔드 개발자는 코드가 돌아가는 Runtime 환경을 이해해야 합니다. 플랫폼의 제약 사항을 우회하기 위해 표준 문법을 변형하는 것도 중요한 실무 능력입니다.

📝 마치며

2048 게임 구현은 배열(Array) 조작, 조건부 렌더링, 그리고 브라우저 이벤트 처리에 대한 프론트엔드 실무 능력을 기르기에 매우 좋은 프로젝트입니다. studyformyself에 적용된 이 코드들은 실제 배포 과정에서의 트러블슈팅 경험까지 녹아 있습니다.

전체 소스 코드와 알고리즘의 동작 과정을 직접 확인해 보고 싶으시다면 아래 링크를 참조해 주세요.

👉 2048 게임 하러가기


1. 다른 게임 로직도 궁금하신가요? 이전에 분석했던 스도쿠 게임의 백트래킹(Backtracking) 알고리즘과 비교해 보면 더욱 흥미롭습니다. 👉 studyformyself 스도쿠 알고리즘 보러 가기

2. 코드 리팩토링 제안 현재 코드에서 성능을 더 높이거나 가독성을 높일 수 있는 함수형 프로그래밍 방식의 도입이 궁금하시다면 의견 남겨주세요!

2 thoughts on “2048 게임 스크립트 심층 분석: 프론트엔드 알고리즘과 구현 전략”

Leave a Comment