
「테트리스 만들어줘」라는 한마디만으로 SRS 회전 법칙까지 구현된 이야기
요약
Claude Code와 Claude 3.5 Sonnet(Fable 5)을 활용하여 단 한 줄의 프롬프트만으로 완성도 높은 테트리스 게임을 구현한 사례를 리뷰합니다. 단순 작동을 넘어 SRS 회전 법칙, 7-bag 랜덤 시스템, 락 지연 등 테트리스의 핵심 메커니즘이 정교하게 포함되었습니다.
핵심 포인트
- 단 한 줄의 프롬프트로 1분 30초 만에 완결된 코드 생성
- SRS(Super Rotation System) 및 벽 차기 로직 자동 구현
- 7-bag 방식의 랜덤 미노 생성 시스템 반영
- Lock Delay 메커니즘을 통한 게임 조작감 확보
전제: 블로그에서 AI 모델 검증 기사를 자주 쓰고 있습니다
Claude Code를 사용하여 개인 블로그를 운영하고 있으며, 새로운 AI 모델이 나올 때마다 간단한 앱을 만들게 하여 실력을 확인하는 작업을 하고 있습니다. 이번에는 Claude Fable 5에게 「테트리스 만들어줘」라고만 전달했을 때의 결과를 구현 내용까지 리뷰해 보겠습니다.
부탁한 것은 실질적으로 한마디뿐
Claude Code의 모델을 Fable 5로 전환하여 던진 프롬프트는 이것뿐입니다.
자, 그럼 테트리스
요건도 사양도 전달하지 않았습니다. 1분 30초 만에 HTML/CSS/JavaScript 1개 파일로 완결되는 테트리스가 돌아왔고, 심지어 수정 없이 바로 작동했습니다.
놀라운 것은 소요 시간보다 내용이었습니다. 「작동만 하는 테트리스」가 아니라, 테트리스라는 게임으로서 올바른 구현이 여러 개 포함되어 있었기에 코드를 살펴보겠습니다.
SRS 회전 법칙(벽 차기)이 구현되어 있었다
테트리스의 미노(떨어지는 블록)를 회전시킬 때, 벽 근처나 다른 블록에 접해 있는 경우 단순한 회전으로는 부딪혀서 돌릴 수 없습니다. 이를 회피하기 위해 현재의 테트리스 가이드라인에는 **SRS (Super Rotation System)**라는 「회전이 안 된다면, 정해진 패턴으로 살짝 움직여서 재도전한다」는 메커니즘이 있습니다. 이것이 이른바 「벽 차기 (Wall Kick)」입니다.
생성된 코드에는 회전 패턴별 움직임 방식(Kick Table)이 제대로 정의되어 있었습니다.
const KICKS_JLSTZ = {
'0>1': [[0,0],[-1,0],[-1,1],[0,-2],[-1,-2]],
'1>0': [[0,0],[1,0],[1,-1],[0,2],[1,2]],
...
키 값인 '0>1'은 「방향 0에서 방향 1로의 회전」을 의미하며, 값인 배열은 「먼저 움직이지 않고 시도 → 안 되면 1칸 오른쪽으로 → 안 되면 오른쪽 위로...」라는 5가지 패턴의 후보입니다. 게다가 I자 미노만 별도의 킥 테이블 (KICKS_I)이 필요하다는 SRS의 세세한 사양까지 반영되어 있었습니다. 이 정도로 정확하게 수행할 줄은 몰랐기에, 소소하게 가장 놀란 포인트입니다.
7종 1순환 (7-bag) 방식의 랜덤 생성
테트리스의 미노는 완전 랜덤일 경우 「같은 모양만 연속해서 나오는」 등 경험이 나빠지기 때문에, 공식 가이드라인에서는 7종류를 1세트로 하여 그 안에서 셔플하여 순서대로 내보내는 (7-bag 시스템) 방식을 사용합니다.
function newBag() {
const types = ['I','O','T','S','Z','J','L'];
for (let i = types.length - 1; i > 0; i--) {
...
내용은 Fisher-Yates 셔플입니다. 「7종류를 매번 전부 다 사용한 뒤에 다음 백(bag)으로」라는 테트리스의 랜덤성 규칙까지, 이것도 요청하지 않았는데 구현되어 있었습니다.
락 지연 (Lock Delay)으로 스트레스를 줄임
미노가 바닥에 착지하는 순간 즉시 고정되면, 「한계까지 움직여서 미세 조정하는」 테트리스 특유의 조작감을 잃게 됩니다. 그래서 많은 구현에서는 착지한 후 일정 시간 동안만 이동·회전을 허용하는 **락 지연 (Lock Delay)**이라는 메커니즘이 들어 있습니다.
if (isGrounded() && lockDelayTimer !== null) {
clearTimeout(lockDelayTimer);
lockDelayTimer = setTimeout(() => { lockDelayTimer = null; lockPiece(); }, 500);
...
착지 판정 후, setTimeout으로 500ms 기다린 뒤 고정 처리(lockPiece)를 호출하는 심플한 구현이지만, 이것이 없으면 「착지 즉시 고정」되는 답답한 조작감이 됩니다. 사소하지만 체감되는 쾌적함에 직결되는 부분입니다.
무엇이 놀라웠는가
이것들은 전부 제가 일절 지정하지 않았습니다. 「테트리스를 만들어줘」라는 한마디로부터 SRS, 7-bag, 락 지연이라는, 테트리스 클론을 만드는 데 있어 정석적인 설계 패턴을 자발적으로 선택하여 구현해 왔다는 점이 이번에 가장 큰 수확이었습니다.
단순히 「작동하는 게임이 빠르게 나오는 것」뿐만 아니라, 장르별 암묵적인 베스트 프랙티스 (Best Practice)를 어디까지 가져오는가라는 관점에서 AI 코딩의 실력을 살펴보면 또 다른 발견이 있습니다.
조금 더 자세한 경위 및 실제로 플레이 가능한 링크는 블로그에
측정한 소요 시간의 내역이나 동작 확인 방법, 이전의 지뢰찾기 (Minesweeper)와의 비교, 실제로 플레이 가능한 페이지로의 링크는 운영 중인 블로그에 정리해 두었습니다.
Claude Code의 실전 팁 (Tips)을 여러 개 작성해 두었으니, 괜찮으시다면 그쪽도 확인해 보세요.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기