슬라이딩 퍼즐이라는 대중적인 퍼즐이 있다. 사각형 격자에 배치된 타일을 이리저리 밀며 제자리를 찾아주는 퍼즐이다. 원래는 1부터 15까지의 수를 순서대로 배열하는 퍼즐인데 이걸 어떻게 변행해 볼 수 있을까? 내 선택은 숫자 대신 알파벳을 배치해서 퍼즐의 정답을 없애 버리는 것이었다. 규칙은 간단하지만 정답이 없으니 아무 생각 없이 누르기 좋을 것이고, 여전히 퍼즐을 풀고 싶은 사람은 자기만의 룰을 정해서 풀어볼 수도 있다. 알파벳 순서로 배열한다든지, 특정 단어를 만든다든지.
처음에 좌표 설정만 직접 해주면 돼서 약간 귀찮을 뿐 전혀 어렵지는 않았다.
const moveTile = (number) => {
if (
(positions[number][0] == blank[0] &&
Math.abs(positions[number][1] - blank[1]) == 1) ||
(positions[number][1] == blank[1] &&
Math.abs(positions[number][0] - blank[0]) == 1)
) {
const temp = [...blank];
blank = [...positions[number]];
positions[number] = temp;
}
};
타일을 클릭했을 때 빈 칸과 인접한 타일이라면 자리를 바꾸도록 했다.
const setTiles = () => {
// for (let i = 0; i < 8; i++) {
// tiles[i].style.transform = `translate(${positions[i][0] * UNIT}px, ${
// positions[i][1] * UNIT
// }px)`;
// }
tiles.forEach(
(tile, i) =>
(tile.style.transform = `translate(${positions[i][0] * UNIT}px, ${
positions[i][1] * UNIT
}px)`)
);
};
타일을 배치하는 것은 transform을 이용해서 자연스럽게 애니메이션이 이루어지도록 했다. 처음에 forEach를 썼다가 잘 안 돼서 for 문으로 직접 반복하는 방식으로 완성했다가, 이후에 다시 forEach를 사용하도록 리팩토링했다.
transition: all 0.6s cubic-bezier(0.66, -0.24, 0.34, 1.24);
타일을 움직이는 애니메이션에 약간의 생동감을 더해주기 위해서 베지어 함수를 이용했다. 원하는 개형의 함수를 간편하게 베지어 곡선으로 변환해주는 사이트가 있으므로 단순한 애니메이션을 구현하기 좋다.
알파벳은 영어에서 가장 많이 등장한다는 ETAOINSH...에서 따왔다. 그런데 너비가 3칸밖에 안 돼서 단어를 만드는 건 어려웠다.