一款极简的每日益智移动应用:每天打开,系统会在 数独、8×8 二进制谜题(Takuzu / Binairo)、8×8 数绘(Nonogram / Picross) 与 7×7 数回(Slitherlink) 中随机分配一局。玩完或认怂后,用带点毒舌的文案收尾;第二天 0 点自动换新题。
无社交、无排行榜、无填格提示——专注「今天这一局」。
给 AI / 协作者: 生产约束与分层规则见 AGENTS.md;验证、CR、手测清单见 docs/DEVELOPMENT.md 与 docs/TESTING.md;GSD 工作流见 CLAUDE.md。
| 能力 | 说明 |
|---|---|
| 每日一题 | 按本地自然日 + 种子确定题型与盘面,同一天多次打开内容一致 |
| 数独 | 9×9 标准数独,冲突高亮,完成 / 认怂 |
| 二进制谜题 | 8×8,每行每列各 4 个 0 与 4 个 1,禁止三连、行列不重复 |
| 数绘 | 8×8 Nonogram,行列提示填格,完成后校验,结果页揭示图案 |
| 数回 | 7×7 Slitherlink,点边画闭合单环,冲突高亮,结果页揭示回路 |
| 离线优先 | 谜题在设备端生成与校验,无需联网 |
| 进度持久化 | AsyncStorage 保存今日状态,杀进程后可续玩 |
| 结果页 | 随机搞笑文案 + Reanimated 入场动效、「明天再来」提示 |
| 本局计时 | 游戏页显示 MM:SS 用时;前后台切换与系统时间校正(防计时回跳) |
| 规则说明 | 游戏页标题旁 ? 弹窗查看玩法 |
| v1.1 emoji 战报 | 结果页「拷贝战报」:emoji 网格 + 用时/连签,写入剪贴板(expo-clipboard) |
| v1.1 结果统计卡 | 今日用时、本周完成天数、历史最长连签(三列小卡) |
| v1.1 评分引导 | 通关后按门槛延迟唤起系统应用商店评分(expo-store-review,可关闭、不阻塞流程) |
| v1.1 防御性保障 | 每日选题可解性校验 + 内置 fallback;快照损坏修复;completed 与残缺棋盘矛盾时剥离 playState |
| v1.2 系统语言 | 跟随设备 zh / en(英文品牌 Brainfool);双语隐私政策;无正式版应用内语言设置 |
| v2.0 数回 | 7×7 Slitherlink 加入每日随机;边线三态画环、冲突高亮、结果页揭示回路(无剧透战报) |
| v2.0 连签护盾 | 每周自动发放 1 张护盾(最多堆叠 2);漏玩 1 天时打开 App 自动消耗护盾续连签 |
| v2.0 昨日错过召回 | 漏玩且未触发护盾时,游戏页标题下显示召回副文案(与护盾生效文案互斥) |
仍不包含: 登录账号、每日推送提醒(规划 v2.1)、个人统计页(规划 v2.1)、填格提示、社交/排行榜/好友(见 路线图)。
- Expo SDK 54 + expo-router(文件路由)
- React Native 0.81 · React 19 · TypeScript
- NativeWind v4(Tailwind CSS)
- react-native-reanimated(结果页动效)
- @react-native-async-storage/async-storage(本地存储)
- 谜题逻辑:纯 TypeScript(
lib/puzzles/),含生成器、求解器与校验
支持 iOS、Android(托管工作流,未提交 ios/ / android/ 原生目录)。
- Node.js 22 LTS(与 CI 一致;仓库根目录
.nvmrc为22) - npm 11+(与 CI 一致;本项目以
package-lock.json为准,请用npm ci安装) - iOS:Xcode + 模拟器(仅 macOS),或 Expo Go
- Android:Android Studio 模拟器,或真机 + Expo Go
# 克隆仓库
git clone https://github.com/moyunzero/foolish-you.git
cd foolish-you
# 安装依赖
npm install
# 启动开发服务器
npm start在终端按 i 打开 iOS 模拟器,按 a 打开 Android 模拟器,或扫码用 Expo Go 连接。
若修改过 babel.config.js(如 Reanimated 插件)或原生依赖,请清缓存后启动:
npx expo start -c| 命令 | 说明 |
|---|---|
npm start |
启动 Expo 开发服务器 |
npm run ios |
在 iOS 模拟器/设备上运行(需预构建或 dev client) |
npm run android |
在 Android 上运行 |
npm run web |
Web 预览(非主要目标平台) |
npm test |
运行 Jest 单元 + RTL 测试(谜题、存储、Context、屏幕) |
npm run test:migration |
仅跑存储迁移黄金样例(与 CI 一致) |
npm run typecheck |
TypeScript 严格检查(tsc --noEmit) |
npm run lint |
ESLint(expo lint) |
完整目录与「新代码放哪」见 docs/DEVELOPMENT.md § Code layout。架构与数据流见 docs/ARCHITECTURE.md。
foolish-you/
├── app/ # expo-router 页面(无谜题算法)
├── components/
│ ├── grid/ # SudokuGrid、BinaryGrid、NonogramGrid、SudokuNumpad
│ ├── slitherlink/ # SlitherlinkBoard(边三态交互)
│ ├── game/ # 各题型 Section、Header/Footer、规则弹窗
│ ├── result/ # 徽章、统计卡、战报、数绘/数回揭示卡
│ ├── ui/ · legal/ · dev/
├── contexts/ # DailyGameContext、DevToolsUiContext
├── hooks/ # 各题型 board hooks、useGameBoardSession、useElapsedTimer
├── lib/
│ ├── date/ · daily/ · puzzles/ · storage/ · streak/ · completion/
│ ├── share/ · stats/ · rating/ · time/ · copy/ · i18n/ · dev/ · platform/
├── locales/ # zh / en
├── constants/ # config、design、dev、legal
└── __tests__/ # lib/ · contexts/ · hooks/ · components/ · screens/
- 启动 →
DailyGameContext读取或创建「今日档案」(dateKey+seed+gameType+ 盘面)。 - 选题 →
lib/puzzles/dailySelectorSafe.ts(可解性校验 + 必要时 fallback)根据日期种子在数独 / 二进制 / 数绘 / 数回间稳定随机,并生成可解盘面。 - 游玩 →
app/game.tsx根据gameType渲染对应网格与底栏;进度防抖写入本地。 - 结束 → 完成或认怂 →
app/result.tsx展示文案与动效;次日dateKey变化后自动新局。
开发模式下(__DEV__)可在首页使用 开发者面板(重开今日、强制题型、设置占位预览语言等),配置见 constants/dev.ts。
// constants/dev.ts
export const DEV_FORCE_GAME_TYPE: GameType | null = 'sudoku'; // null = 与线上一致随机;可选 'binary' | 'nonogram' | 'slitherlink'正式 Release 构建不会包含该面板。
npm test当前覆盖:日期工具、RNG、每日选题与 safe 选题、数独/二进制/数绘/数回生成与校验、存储迁移/恢复、完成历史、战报与统计、评分门槛、连签、i18n(含 en-smoke)、Context 与主要屏幕 RTL(402 项)。另含 npm run test:migration 迁移黄金样例。UI 动效与真机布局以手测为主。
使用 EAS Build 或本地预构建:
# 需先安装 eas-cli 并登录 Expo 账号
npx eas build --platform ios
npx eas build --platform androidapp.json 中已配置应用名 傻了么、Bundle ID com.moyunzero.foolish-you、深色界面。发布前请自行替换图标、签名与商店元数据。
详见内部
.planning/ROADMAP.md。
- 离线优先:
dateKey + seed决定盘面,永不远程下发 - 一天一局:不变成「每日 3 题」,今天的张力来自唯一性
- 不做:排行榜、好友、IM、IAP、广告、提示按钮、可堆叠超过 2 的护盾
- 毒舌幽默是品牌护城河,所有文案都要过这一关
| 阶段 | D1 | D7 | D30 | 评分 | 完成 → 分享率 |
|---|---|---|---|---|---|
| v1.0(已上架基线) | — | — | — | 已公测 | 0%(无入口) |
| v1.1 目标(≈ 3 月) | 32% | 12% | 5% | ≥ 4.4 | ≥ 3% |
当前 v2.0(2.0.0,代码已交付) |
待公测 | 待公测 | 待公测 | 目标 ≥ 4.5 | 目标 ≥ 5% |
| v2.0 后 ≈ 6 月 | 35%+ | 15%+ | 7%+ | ≥ 4.5 | ≥ 5% |
| 12 月目标 | 38% | 18% | 9% | 4.6 | 7% |
目标是把「傻了么」从 Puzzle 子类中位推进到 Top 25%(行业 35/15/5 基准)。
| 版本 | 状态 | 范围 | 关键押注(数据锚点) |
|---|---|---|---|
| v1.0 | 已发布 | 每日数独 / 二进制 / 数绘(不含数回)、本地进度、连签、结果动效、计时、规则弹窗 | — |
| v1.1 | 已发布(1.1.x) |
① 结果页 emoji 战报拷贝(lib/share/ + expo-clipboard);② 评分引导(通关 + 完成局数等门槛,expo-store-review);③ 结果页三数据小卡(今日用时 / 本周完成 / 历史最长连签,historicalMax);④ 防御:selectDailyGameSafe、快照 recoverSnapshot、计时校正、迁移 + recovery 单测、Dev 恢复日志 |
Wordle 90→300K DAU 来自一键 emoji 分享 |
| v1.2 | 已发布(1.2.0) |
系统语言 zh/en(expo-localization);英文品牌 Brainfool;locales/ + useI18n;双语隐私;DevTools 设置占位(不写存储,Release 无入口) |
海外可读性 + 商店合规 |
| v2.0 | 当前(2.0.0,代码已交付;商店发版收口见 closeout) |
✅ 数回 7×7(Slitherlink:生成器、边线 UI、揭示卡/战报);✅ Streak Freeze(每周 1 张、最多堆 2、漏 1 天自动消耗);✅「昨日错过」召回副文案;⏳ 每日提醒 → v2.1;⏳ 个人统计页 → v2.1 | Duolingo:streak 寿命 +48%;7 天 streak 用户次日留存 2.4× |
| v2.1 | 规划中 | 周节奏难度(仍每天 1 局);本月日历;月度数绘图鉴长图;每日提醒(原 v20-02);个人统计页(原 v20-03) | NYT Mini/Midi 节奏 |
| v3.0 | 规划中 | iCloud / Google 端到端同步或 QR 导入导出;30 天历史归档 | 避免与「离线优先 / 无社交」冲突 |
| v4.0 | 规划中 | 匿名挑战码;Year in 傻了么 年终长图 | 朋友间话题,无好友列表 |
完整决策依据、AB 实验设计与对照取舍见 .planning/ROADMAP.md(已加入 .gitignore,不随仓库公开)。
视觉与交互约定见本地 DESIGN.md(已加入 .gitignore,不随 GitHub 公开)。
尚未指定开源许可证。若你 fork 或二次发布,请先与仓库维护者确认授权。
谜题算法与产品灵感来自经典数独与 Takuzu/Binairo 规则;由 Expo 与 React Native 生态驱动交付。
- 启动 App →
app/index.tsx根据今日档案跳转到app/game.tsx。 - 游戏页顶栏
GameScreenHeader显示日期、本局用时、题型标题、连签副文案(streakLine),以及可选的护盾/召回副行(GameStreakSubline,护盾生效与昨日错过互斥)。 - 填完盘面后点底栏 完成今日(
GameScreenFooter)→ 校验通过则进入结果页;认怂不计入连签。 - 结果页可点 拷贝战报(需保留有效
playState;恢复后若棋盘已剥离则仅展示文案与统计)。 - 次日本地
dateKey变更后自动换新题。
- 仅通关计入连签,认怂不调用
applyCheckIn(见contexts/DailyGameContext.tsx)。 - 逻辑:
lib/streak/streakLogic.ts(连续自然日 +1,断档归零);持久化:lib/storage/streakStorage.ts(键@foolish-you/streak-v1,schema v3,含historicalMax、freezeCount等)。 - 护盾(Streak Freeze):
lib/streak/freezeLogic.ts— 每周 ISO 周首次打开发放 1 张(上限 2);若距上次入账恰好漏 1 天且无真实完成记录,hydrate 时自动消耗 1 张续连签。 - 昨日错过召回:
lib/streak/missedYesterdayBanner.ts— 漏玩且未消耗护盾时,游戏页标题下显示召回文案(与护盾生效行互斥)。 - 文案:顶栏连签
lib/copy/streak.ts;护盾/召回lib/copy/freeze.ts、lib/copy/missedYesterday.ts;结果统计卡护盾后缀见locales/*/copy.ts。
GitHub Actions 工作流 .github/workflows/ci.yml 在 main / master 的 push 与 PR 上执行:
npm run typecheck # tsc --noEmit
npm test # Jest:unit(*.test.ts)+ rtl(*.test.tsx)
npm run test:migration # 存储迁移黄金样例
npm run lint # expo lint
npm run lockfile:verify-eas # npm 10 ci,EAS 构建前建议跑可选拆分:
npm run test:unit # 谜题、存储、连签等纯逻辑
npm run test:rtl # Context 与屏幕级 RTL 测试| 文档 | 说明 |
|---|---|
| AGENTS.md | AI/协作者:生产约束、分层规则、验证入口 |
| docs/ARCHITECTURE.md | 架构、数据流、离线优先与持久化 |
| docs/GETTING-STARTED.md | 安装与首次运行 |
| docs/DEVELOPMENT.md | 日常开发、CI 校验、DevTools |
| docs/TESTING.md | Jest 双项目与手测清单 |
| docs/CONFIGURATION.md | app.json、EAS、常量与存储键 |