

이 테트리스 게임은 단일 HTML 파일로 구성된 웹 애플리케이션이며, 다음 기능을 포함합니다:
반응형 디자인: Tailwind CSS를 사용하여 다양한 화면 크기(데스크톱, 태블릿, 모바일)에 맞춰 게임 보드와 UI 요소가 적절히 조정됩니다.
게임 보드: HTML <canvas> 요소를 사용하여 게임 보드와 블록을 그립니다. 보드는 10x20 그리드로 설정되어 있습니다.
블록 생성:
총 7가지 표준 테트리스 블록(테트로미노)이 정의되어 있으며, 각각 고유한 색상을 가집니다.
게임 시작 시 또는 블록이 바닥에 쌓이면, 새로운 블록이 상단 중앙에서 무작위로 생성됩니다.
새로운 블록이 생성될 공간이 없으면 게임 오버가 됩니다.
블록 이동 및 회전:
좌우 이동: 키보드의 왼쪽/오른쪽 방향키로 블록을 좌우로 움직일 수 있습니다.
블록 회전: 키보드의 위쪽 방향키로 블록을 시계 방향으로 회전시킬 수 있습니다.
수직 낙하 (하드 드롭): 키보드의 아래쪽 방향키를 누르면 블록이 즉시 바닥으로 떨어집니다.
모든 이동 및 회전은 게임 보드 경계와 이미 쌓인 블록과의 충돌을 확인하여 유효한 경우에만 수행됩니다.
라인 삭제 및 점수 계산:
한 줄이 블록으로 완전히 채워지면 해당 줄이 삭제됩니다.
삭제된 줄 위의 블록들은 아래로 떨어집니다.
점수:
1줄 삭제: 1점
2줄 삭제: 3점
3줄 삭제: 5점
4줄 삭제: 8점
5줄 삭제: 11점
(점수가 10점씩 올라가면 블록이 내려오는 시간이 더 빨라지도록 구현, 41점 부터는 임의의 공간에 블록 1칸이 생성(시점은 블록이 바닥에 떨어짐과 동시에)
0-10점: 기본 낙하 속도 (500ms)
11-20점: 400ms
21-30점: 300ms
31-40점: 200ms
41점부터: 150ms (가장 빠른 속도)
41점부터 : 블록 1칸 생성(가장 높이 쌓인 블록의 바로 위칸 또는 위 2번째 칸"에 무작위로 생성, 만약 보드가 아직 비어 있거나, 블록이 너무 높이 쌓여서 지정된 위치에 공간이 없을 경우, 가장 상단의 비어있는 유효한 칸에 생성)
1칸짜리 블록 생성 위치 변경:
51점 이상: 가장 높이 쌓인 블록의 바로 위 2번째 칸 또는 위 3번째 칸에 생성됩니다.
두 경우 모두, 해당 위치에 블록을 생성할 수 없을 경우 가장 상단의 비어 있는 유효한 칸에 생성됩니다.
새로운 수평 블록 생성 (61점 이상):
점수가 61점 이상일 때, 블록 5개가 바닥에 쌓일 때마다 (정확히는 새 블록이 생성될 때마다 droppedPiecesCount가 증가하고 5의 배수가 될 때) 최하단에 1칸의 공백이 생긴 수평 블록(쓰레기 줄)이 생성됩니다.
71점 이상: 블록 5개가 바닥에 쌓일 때마다 최하단에 1칸 공백이 생긴 수평 블록이 생성됩니다. (이 규칙은 61점 이상 규칙보다 우선 적용됩니다.)
이때 기존에 쌓인 블록들은 자동으로 한 칸씩 위로 밀려 올라갑니다.
이로 인해 가장 상단 줄(0번째 줄)에 블록이 생성되면 게임 오버가 됩니다.
게임 상태 관리:
게임 오버: 새로운 블록이 생성될 수 없을 때 게임이 종료되며, 오버레이 메시지가 표시됩니다.
게임 시작/다시 시작: "게임 시작" 및 "다시 시작" 버튼을 통해 게임을 시작하거나 리셋할 수 있습니다.
커스텀 메시지 박스: alert() 대신 사용자에게 정보를 전달하기 위한 커스텀 메시지 박스를 구현했습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>테트리스 게임</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* Chosen Palette: Warm Neutral Harmony */
body {
font-family: 'Inter', sans-serif;
background-color: #f5f5f4;
color: #292524;
}
.game-container {
position: relative;
width: 100%;
max-width: 400px;
margin-left: auto;
margin-right: auto;
border-radius: 0.75rem;
overflow: hidden;
}
canvas {
background-color: #1c1c1c;
display: block;
width: 100%;
height: 100%;
border-radius: 0.75rem;
}
.message-box {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
border: 1px solid #e7e5e4;
border-radius: 0.75rem;
padding: 1.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
z-index: 1000;
display: none;
text-align: center;
}
.message-box button {
margin-top: 1rem;
padding: 0.5rem 1rem;
background-color: #ef4444;
color: white;
border-radius: 0.5rem;
font-weight: 600;
transition: background-color 0.2s ease-in-out;
}
.message-box button:hover {
background-color: #dc2626;
}
</style>
</head>
<body class="flex flex-col items-center justify-center min-h-screen p-4 sm:p-6 lg:p-8">
<!-- Application Structure Plan: This SPA is designed as a single game screen. The information architecture prioritizes direct interaction with the game itself. The main components are the game canvas, score display, control instructions, and game status messages. This linear, focused structure is chosen for usability in a game, allowing users to immediately understand and engage with the core objective: playing Tetris. Key interactions are keyboard-based movement, rotation, and hard drop. The score updates dynamically. -->
<!-- Visualization & Content Choices:
- Game Board: Goal -> Play -> Canvas rendering (2D blocks) -> Keyboard input for control -> Direct engagement with core gameplay -> Canvas API.
- Score Display: Goal -> Inform -> Text display -> Automatic update on line clear -> Clear feedback on progress -> HTML text, JS variable updates.
- Control Instructions: Goal -> Guide -> Static Text -> No interaction needed -> Clear guidance for new users -> HTML text.
- Game Over/Start Messages: Goal -> Inform/Engage -> Dynamic Text overlay -> Triggered by game state changes -> Clear game state feedback -> HTML text, JS display logic.
- Block Colors: Goal -> Distinguish -> Unique color per block type -> Visual identification of blocks -> Enhanced readability -> Canvas drawing with specific fillStyle.
- Scoring Logic: Goal -> Reward/Motivate -> Numeric score calculation -> Real-time update based on line clears -> Incentive for efficient play -> JS calculation and HTML update.
CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
<div class="message-box" id="messageBox">
<p id="messageText" class="text-lg font-semibold mb-4"></p>
<button id="messageButton">확인</button>
</div>
<div class="w-full max-w-xl bg-white rounded-xl shadow-lg p-6 flex flex-col items-center border border-stone-200">
<h1 class="text-3xl sm:text-4xl font-bold mb-4 text-stone-800 text-center">테트리스</h1>
<div class="flex justify-between w-full max-w-sm mb-4 p-2 bg-stone-50 rounded-lg border border-stone-200 shadow-sm">
<span class="text-lg font-medium text-stone-700">점수:</span>
<span id="score" class="text-lg font-bold text-blue-600">0</span>
</div>
<div class="game-container mb-4 aspect-[1/2]">
<canvas id="tetrisCanvas" width="200" height="400"></canvas>
<div id="gameOverlay" class="absolute inset-0 bg-black bg-opacity-75 flex flex-col items-center justify-center rounded-xl text-white text-2xl font-bold text-center p-4" style="display: none;">
<p id="overlayMessage"></p>
<button id="startButton" class="mt-4 px-6 py-3 bg-green-500 hover:bg-green-600 text-white font-semibold rounded-lg shadow-md transition transform hover:scale-105">
게임 시작
</button>
<button id="resetButton" class="mt-2 px-6 py-3 bg-red-500 hover:bg-red-600 text-white font-semibold rounded-lg shadow-md transition transform hover:scale-105" style="display: none;">
다시 시작
</button>
</div>
</div>
<div class="w-full max-w-sm text-center mb-6 p-4 bg-stone-50 rounded-lg border border-stone-200 shadow-sm">
<h2 class="text-xl font-semibold mb-2 text-stone-700">컨트롤</h2>
<div class="grid grid-cols-2 gap-2 text-stone-600">
<div class="flex items-center justify-start"><span class="font-bold text-2xl mr-2">←</span> 키보드 좌우 이동</div>
<div class="flex items-center justify-start"><span class="font-bold text-2xl mr-2">→</span></div>
<div class="flex items-center justify-start"><span class="font-bold text-2xl mr-2">↑</span> 키보드 블록 회전</div>
<div class="flex items-center justify-start"><span class="font-bold text-2xl mr-2">↓</span> 키보드 수직 낙하</div>
<div class="flex items-center justify-start col-span-2 text-stone-700 text-base font-semibold mt-2">--- 모바일 터치 컨트롤 ---</div>
<div class="flex items-center justify-start col-span-2"><span class="font-bold text-2xl mr-2">터치 좌측 30%</span> 좌 이동</div>
<div class="flex items-center justify-start col-span-2"><span class="font-bold text-2xl mr-2">터치 우측 30%</span> 우 이동</div>
<div class="flex items-center justify-start col-span-2"><span class="font-bold text-2xl mr-2">터치 중앙 40% (한 번)</span> 회전</div>
<div class="flex items-center justify-start col-span-2"><span class="font-bold text-2xl mr-2">터치 중앙 40% (길게 누르기)</span> 수직 낙하</div>
</div>
</div>
</div>
<script>
let ...![[펌] 출처 미상 작자 미상](https://image.fmkorea.com/files/attach/new5/20250425/8295412122_192159903_34675b04486b9c815eeb7484746278c2.png)