잠깐 딴짓하기 좋은 게임 모음 — 천하삼분 · 꿈마을 · 오목 · 장기 · 리버시 · 윷놀이 · 스도쿠 · 지뢰찾기 · 노노그램 · 솔리테어 · 테트리스 · 벽돌깨기 · 2048 · 꼬들
서버도 계정도 없습니다. 진행 상황과 기록은 브라우저(localStorage)에만 저장되고, 한 번 열어 본 뒤에는 네트워크 없이도 실행됩니다(PWA).
/ 게임 네비게이터(허브)
/games/omok/ 오목 /games/minesweeper/ 지뢰찾기 /games/tetris/ 테트리스
/games/janggi/ 장기 /games/nonogram/ 노노그램 /games/breakout/ 벽돌깨기
/games/reversi/ 리버시 /games/solitaire/ 솔리테어 /games/2048/ 2048
/games/yut/ 윷놀이 /games/sudoku/ 스도쿠 /games/kkodle/ 꼬들
/games/samguk/ 천하삼분(삼국지 전략 시뮬레이션)
/games/growup/ 꿈마을(Dream Town, 진로 육성 시뮬레이션)
허브에서 분류(전략 · 육성 · 보드 · 퍼즐 · 액션 · 데일리)로 걸러 볼 수 있고, 키보드가 있으면 숫자키로 바로 들어갑니다
(숫자키·방향키 안내는 마우스·키보드가 있는 기기에서만 보이고, 터치 화면에서는 숨깁니다 — base.css의 .kbd-only/.touch-only).
| 게임 | 분류 | 특징 |
|---|---|---|
| 천하삼분 | 전략 | 『삼국지』 III·V풍 역사 전략 시뮬레이션. 그림(표제·고지도·전장·생성형 장수 초상)은 모두 코드로 그림. 190~280년 시나리오 7개, 53개 도시, 정사 기반 실존 인물 711명. 내정·인사·외교·계략, 육각 칸 공성전(화계·혼란·일기토), 역사 이벤트, 핫시트. 기획 지시서는 docs/samguk/PROMPT.md. |
| 꿈마을 | 육성 | 초1부터 고3까지 12년(144달) 진로 육성 시뮬레이션. 위에서 내려다본 블록 마을 지도(픽셀 그림·사람·소품 모두 코드로 그림)에서 구역 4개(집·학교·동네·시내)·장소 15곳을 아이가 길 따라 걸어 다니고, 장소에 들어가면 그곳이 크게 보입니다. 학년이 오르면 공사 중이던 곳이 열립니다. 한 달은 4주로 나뉘어 주마다 결과가 나고, 프린세스 메이커식 대화창(초상 + 한마디)으로 진행합니다. 계절·실제 시각·기분(비)이 풍경에 드러나고, 친구 4명과 친해지기·친구 사건이 있습니다. 교육 장치: 4주 동안 주마다 활동과 이어진 지식 하나(분야 22개 — 운동 규칙·역사, 요리·안전, 과학, 한국사, 경제 등), 어학원의 영어·한자·고사성어·속담·바른 우리말, 배운 것이 쌓이면 분야별 인증 시험(초급·중급·고급, 진로 점수에 반영, 실제 자격증 안내), 배운 것 퀴즈·직업 퀴즈, 학년 돌아보기(용돈 기입장·조언), 졸업 꿈 보고서(관심 유형 그래프·어울리는 직업·모자랐던 것) — docs/growup/DESIGN.md. 직업 29가지(취업·창업·프리랜서·연구)가 세 등급으로 갈립니다. 화면 글은 초등학생 눈높이의 쉬운 말로 씁니다(예: 스트레스→짜증, 능력치→실력). 초상은 프리셋 · 16src/games/growup/portraits/). 엔진(engine.ts·flow.ts)은 화면과 분리돼 있고 모든 화면이 버튼 ①growup:input · 신호 growup:bridge)를 나중에 붙일 수 있습니다. |
| 오목 | 보드 | 15×15, 좌표 표시, 착수 미리보기, 승리 라인 강조. AI는 즉승/즉방 + 열린형태 평가로 최대 10수를 읽습니다(1.6초). |
| 장기 | 보드 | 차림 4종·진영 선택, 점수제(한 덤 1.5), 기보. AI는 MVV-LVA 정렬 + 정지탐색으로 최대 5수(2.5초). |
| 리버시 | 보드 | 착수 가능 위치 표시, 모서리·기동력·확정석 평가, 종반 16칸 완전탐색(2.5초). |
| 스도쿠 | 퍼즐 | 유일해 보장 생성, 메모·자동메모·되돌리기·힌트, 실수 제한. |
| 지뢰찾기 | 퍼즐 | 추측이 필요 없는 판만 출제 — 생성한 배치를 솔버로 끝까지 풀어 보고 통과한 것만 내보냅니다. |
| 노노그램 | 퍼즐 | 줄 논리만으로 풀리는 문제만 출제 — 유일해가 보장됩니다. 밀어서 칠하기, 되돌리기. |
| 솔리테어 | 퍼즐 | 클론다이크. 한 장/세 장 뽑기, 두 번 눌러 자동 이동, 되돌리기, 자동 완성. |
| 테트리스 | 액션 | SRS 회전 + 월킥, 7-bag, 홀드, 고스트, 락 딜레이, T-스핀/백투백/콤보. |
| 윷놀이 | 보드 | 도개걸윷모와 뒤도, 지름길·업기·잡기까지. 모서리에 정확히 멈춰야 지름길을 탑니다. AI 3단계와 2인 대국. |
| 벽돌깨기 | 액션 | 패들 어디에 맞느냐로 각이 갈리고, 빠른 공도 벽돌을 뚫지 않습니다. 아이템 3종과 판마다 다른 배치. |
| 2048 | 액션 | 타일이 미끄러지는 연출, 되돌리기, 최고 타일 기록, 2048 이후 계속하기. |
| 꼬들 | 데일리 | 두 글자 한글 낱말을 자모 단위로 채점. 하루 한 문제 + 무한 모드, 연속 일수 기록. IME 없이도 되는 한글 조합 자판 내장. |
오늘의 문제는 꼬들·스도쿠·노노그램·지뢰찾기 네 곳에 있습니다. 서버가 없으므로 기기 날짜를 시드로 삼아 만들며, 같은 날이면 누가 열어도 같은 문제가 나옵니다.
모든 게임에 튜토리얼(첫 방문 자동 · 이후 ? 키) 과 서사가 있고,
진행 중인 대국은 자동 저장되어 허브에서 “이어하기”로 돌아갈 수 있습니다.
모바일 퍼스트로 만들었습니다. 기본 레이아웃이 세로 화면 기준이고, 넓은 화면에서 사이드 패널이 열립니다.
터치 목표는 최소 44~52px, 하단 조작부는 env(safe-area-inset-bottom)을 반영합니다.
게임끼리 공유하는 코드는 src/shared/(공통 레이어)에 모여 있습니다.
| 모듈 | 역할 |
|---|---|
registry.ts |
게임 목록·메타데이터·서사. 허브와 각 게임이 같은 정의를 참조 |
storage.ts |
games:<gameId>:<key> 네임스페이스 localStorage 래퍼 (저장 실패해도 게임은 계속 동작) |
progress.ts |
“이어하기” 요약 — 허브 카드에 표시 |
records.ts |
최고 기록 (점수형/시간형 모두 지원) |
stats.ts |
AI 대전 전적 |
prefs.ts |
전역 설정(효과음) — 모든 게임이 공유 |
sound.ts |
WebAudio 합성 효과음. 오디오 파일 없음 |
tutorial.ts |
튜토리얼 자료형 + 최초 1회 자동 표시 여부 |
daily.ts |
날짜 시드로 정하는 오늘의 문제 + 연속 일수 기록 |
color.ts |
색 밝기·투명도 (캔버스 그러데이션용) |
react/GameShell.tsx |
공통 상단바(허브 링크·제목·도움말·효과음) + 튜토리얼 |
react/GameMark.tsx |
게임마다 하나씩 있는 표식(SVG). 허브 카드와 상단바가 같은 그림을 씁니다 |
react/useKeys.ts |
전역 단축키 |
dom/shell.ts, dom/tutorial.ts |
React를 쓰지 않는 게임(스도쿠)용 같은 기능 |
pwa.ts |
서비스 워커 등록 |
게임을 새로 추가하는 방법은 docs/ADDING_A_GAME.md, 외부 라이브러리(MediaPipe 등) 반입 규칙은 docs/THIRD_PARTY_ASSETS.md를 보세요.
npm install
npm run dev # 개발 서버 (허브: /, 게임: /games/<id>/)
npm test # 규칙 엔진 테스트 (vitest, 220여 개)
npm run typecheck
npm run build # dist/ 생성 (허브 + 게임 14개 + 서비스 워커)
npm run previewGitHub Pages는 꺼져 있습니다(gh-pages 브랜치는 예전 배포본이라 쓰지 않습니다).
블로그 저장소(yjworks/yjworks.github.io)의 hugo.yml이 빌드해 Cloudflare Pages(dibrain.dev/games/)에 올립니다.
이 저장소의 ci.yml은 타입 검사·테스트·빌드를 보고, main에서 통과하면 hugo.yml을 바로 실행시킵니다
(저장소 secret DEPLOY_TOKEN — 블로그 저장소 하나만, Actions: Read and write 권한의 fine-grained 토큰. 없으면 건너뜀).
블로그 저장소의 30분 예약 점검은 보조입니다.
릴리스: v로 시작하는 태그(예: v1.0.0)를 올리거나, Actions에서 Release를 수동 실행(태그 이름 입력)하면 release.yml이 검사·빌드 후 GitHub Release를 만들고 빌드본(games-v1.0.0.zip)을 붙입니다.
base가 상대 경로(./)라서 계정 이름이나 저장소 이름이 바뀌어도 그대로 동작합니다.
서비스 워커의 경로도 전부 상대 경로입니다.
앱이 도는 데 필요한 주소는 매니페스트의 id(/games/) 하나뿐입니다(링크 미리보기용
canonical·og:url에는 https://dibrain.dev/games/...가 적혀 있어, 주소를 옮기면 같이 고칩니다). 앱 식별자는 설치된 앱을
가리키는 이름이라 고정돼 있어야 합니다 — 빼 두면 start_url에서 파생되는데, 그러면
start_url을 손대는 순간 다른 앱이 되어 홈 화면에 아이콘이 두 개 생깁니다.
/games/가 아닌 경로로 옮긴다면 이 값도 같이 옮겨야 합니다.
기록은 주소(오리진)에 매여 있습니다. 배포 주소를 옮기면 localStorage가 새로 시작하고 설치해 둔 PWA도 따로 잡힙니다 — 옮기기 전에 알아 둘 것.
- 서비스 워커가 빌드 산출물 전체를 미리 캐시합니다(
vite.config.ts의pwaPlugin). - 두 번째 방문부터는 네트워크 없이 실행되고, 홈 화면에 설치하면 앱처럼 열립니다.
- 외부 CDN을 쓰지 않습니다. 폰트·아이콘·효과음까지 전부 저장소 안에 있습니다.
- 글꼴 Pretendard는
public/vendor/fonts/에 있습니다.pretendard.css만 미리 캐시하고, 조각 파일(woff2 92개)은 화면에 필요한 것만 처음 쓸 때 받아games-fonts-v1캐시에 둡니다(다음부터 네트워크를 보지 않음). - 같은 주소(dibrain.dev)를 쓰는 다른 앱의 캐시는 건드리지 않습니다. 옛 캐시를 지울 때
games-로 시작하는 것만 지웁니다.