xmi1e-vir.log

[Dreamhack] wargame 'Carve Party' write-up 본문

WARGAME/WEB

[Dreamhack] wargame 'Carve Party' write-up

eunee22 2025. 9. 7. 22:35
🌱 Biginner
문제링크
할로윈 파티를 기념하기 위해 호박을 준비했습니다!
호박을 10000번 클릭하고 플래그를 획득하세요!

 

📌문제 파악

정말로 호박을 10000번 클릭하는 문제이다.

코드에서 클릭해야 하는 부분은 #jack-target 부분이다.

코드를 좀 더 자세히 살펴보자.

1. 변수 초기화

  • pumpkin는 최종적으로 표시 될 텍스트 데이터를 암호화 해놓은 숫자 배열이다.
  • counter는 클릭 횟수를 추적한다.
  • pie는 연산에 사용되는 키 값으로, 동적으로 변한다.
var pumpkin = [ 124, 112, 59, 73, 167, 100, 105, 75, 59, 23, 16, 181, 165, 104, 43, 49, 118, 71, 112, 169, 43, 53 ];
var counter = 0;
var pie = 1;

 

2. 화면이 변하는 과정을 구현

  • 클릭수에 따라서 얼굴의 각 요소 투명도를 조절하고,
    정해진 수인 10000번이 넘으면 flag를 그리는 역할을 한다.
조건(counter 값) 동작 내용
counter ≤ 1000  #jack-nose의 투명도를 0%에서 100%로 점진적으로 증가
1000 < counter ≤ 3000 왼쪽 눈 #jack-left의 투명도를 0%에서 100%로 증가
3000 < counter ≤ 5000 오른쪽 눈 #jack-right의 투명도를 0%에서 100%로 증가
5000 < counter ≤ 10000  #jack-mouth의 투명도를 0%에서 100%로 증가
counter > 10000 캔버스에 텍스트 애니메이션을 그림
그 외 남은 클릭 수(10000 - counter)를 #clicks 요소에 표시
function make() {
  if (0 < counter && counter <= 1000) {
    $('#jack-nose').css('opacity', (counter) + '%');
  }
  else if (1000 < counter && counter <= 3000) {
    $('#jack-left').css('opacity', (counter - 1000) / 2 + '%');
  }
  else if (3000 < counter && counter <= 5000) {
    $('#jack-right').css('opacity', (counter - 3000) / 2 + '%');
  }
  else if (5000 < counter && counter <= 10000) {
    $('#jack-mouth').css('opacity', (counter - 5000) / 5 + '%');
  }
  else if (10000 < counter) {
    // 캔버스 애니메이션 코드  }
  else {
    $('#clicks').text(10000 - counter);
  }
}

 

위에서 생략된 캔버스 애니메이션 코드는 pumpkin 배열을 ASCII 문자로 변환해 문자열(txt)로 만드는 역할을 한다.
캔버스에 한 글자씩 점선 효과로 그림을 그리면(strokeText), 점선이 점차 채워지며 글자가 완성된다(fillText).

var ctx = document.querySelector("canvas").getContext("2d"),
dashLen = 220, dashOffset = dashLen, speed = 20,
txt = pumpkin.map(x=>String.fromCharCode(x)).join(''), x = 30, i = 0;

 

3. 클릭 이벤트

  • #jack-target 요소 즉, 호박이 클릭 될때마다 발생하는 이벤트이다.
  • 세부적으로 하는 일은 아래와 같다.
    • counter 값 증가
    • XOR 계산
    • pie 값 업데이트
    • 앞서 설명한 make() 함수를 호출하여 UI를 알맞게 업데이트
$(function() {
  $('#jack-target').click(function () {
    counter += 1;
    if (counter <= 10000 && counter % 100 == 0) {
      for (var i = 0; i < pumpkin.length; i++) {
        pumpkin[i] ^= pie;
        pie = ((pie ^ 0xff) + (i * 10)) & 0xff;
      }
    }
    make();
  });
});

📌풀이 방법

내가 알아낸 풀이는 총 2가지가 있다.

1. 10000번 자동클릭

  • 가장 단순하게 풀수 있는 방법이다.
  • html에 다음과 같이 호박 요소를 10000번 자동 클릭하는 함수를 작성하여 호출한다.
function autoClick() {
  for (let i = 0; i < 10000; i++) {
    counter += 1;
    if (counter <= 10000 && counter % 100 === 0) {
      for (let j = 0; j < pumpkin.length; j++) {
        pumpkin[j] ^= pie;
        pie = ((pie ^ 0xff) + (j * 10)) & 0xff;
      }
    }
    make();
  }
  counter += 1;
  make();
}
autoClick();

2. XOR 연산

  • 그 다음으로 counter가 100의 배수일 때마다 실행되는 XOR 연산을 100번 반복하는 코드를 작성해 pumpkin 배열을 최종 상태로 만드는 방법이다.
  • 앞보다 (컴퓨터 입장에서) 더 간단하다.
pumpkin = [ 124, 112, 59, 73, 167, 100, 105, 75, 59, 23, 16, 181, 165, 104, 43, 49, 118, 71, 112, 169, 43, 53 ]
pie = 1
for i in range(100):
      for i in range(len(pumpkin)):
        pumpkin[i] ^= pie
        pie = ((pie ^ 0xff) + (i * 10)) & 0xff
print("".join(map(chr, pumpkin)))