1
This commit is contained in:
@@ -253,6 +253,11 @@ function resolvePuzzleGridSize(clearedLevelCount: number): 3 | 4 {
|
||||
|
||||
1. 单块拖到单块位置:执行交换。
|
||||
2. 合并块拖到任意目标锚点:保持内部相对布局整体重排。
|
||||
3. 若合并块整体平移后覆盖到多个单块,被覆盖单块必须与合并块腾出的原格子做一对一交换,禁止把多个单块回填到同一个源格。
|
||||
4. 一对一交换必须满足:
|
||||
- 每个被覆盖单块只移动一次。
|
||||
- 每个被腾出的源格只接收一个被覆盖单块。
|
||||
- 若腾出的源格数量与被覆盖单块数量不一致,本次拖动视为非法,不更新棋盘。
|
||||
3. 单块拖到合并块占据位置:先拆分目标合并块,再执行交换,最后重算合并。
|
||||
|
||||
### 7.5 通关
|
||||
@@ -382,3 +387,58 @@ finalScore = tagSimilarityScore * 0.7 + sameAuthorScore * 0.3;
|
||||
### 10.4 冻结说明
|
||||
|
||||
截至本次验收,拼图玩法已满足 PRD 要求的最小产品闭环;未继续扩展排行榜、提示、体力、异形拼块、倒计时、前端本地裁决等超出本轮需求的能力。
|
||||
|
||||
## 11. 2026-04-26 运行态机制补齐记录
|
||||
|
||||
本次按 PRD 第 9 章补齐拼图运行态的未完成机制,落点保持在 `server-rs/crates/module-puzzle` 领域层;前端本地兜底只同步表现和离线闭环,不改变后端真相源。
|
||||
|
||||
### 11.1 棋盘初始化
|
||||
|
||||
1. `build_initial_board_with_seed` 使用种子化洗牌生成初始棋盘,不再固定左移一格。
|
||||
2. 正式 run 的种子由 `runId + profileId + levelIndex + gridSize` 派生;由于每次进入都会创建新的 `runId`,同一作品多次进入也会得到不同打乱样式。
|
||||
3. 洗牌后若极端情况下仍为完成态,强制旋转一次,保证新关卡不是已完成局面。
|
||||
4. 初始棋盘不得存在任何已经正确相邻的两块;初始化会多次洗牌筛选,若极端情况下未命中,则使用反序排列兜底,避免开局自动出现合并块。
|
||||
5. `module-puzzle` 与本地 fallback 的测试都必须直接断言初始棋盘不存在正确相邻对,不能只检查 `mergedGroups = []`。
|
||||
|
||||
### 11.2 局部重算与合并
|
||||
|
||||
1. 交换后只把源格、目标格和四向邻格纳入重算范围。
|
||||
2. 拖动后把源格、目标格、被移动合并块边界格、被拆分目标合并块格子纳入重算范围。
|
||||
3. 对受影响范围内的旧合并组先拆回单块,再按正确四向相邻关系重新生成合并组;未受影响的旧合并组保留。
|
||||
4. 每次生成快照时统一重编号合并组,避免保留组与新组出现重复 `groupId`。
|
||||
|
||||
### 11.3 拖动与拆分
|
||||
|
||||
1. 单块拖到单块位置时执行交换。
|
||||
2. 合并块拖动时保持内部相对布局,以被拖动块作为锚点整体平移。
|
||||
3. 单块拖入合并块占据位置时,先拆分目标合并块,再完成本次交换,最后按受影响范围重新合并。
|
||||
|
||||
### 11.4 本次新增验证
|
||||
|
||||
1. `cargo test -p module-puzzle` 覆盖:每次 run 不同打乱、正确相邻自动合并、单块拖入合并块拆分目标组。
|
||||
2. `npm run test -- src/services/puzzle-runtime/puzzleLocalRuntime.test.ts` 覆盖:本地兜底每次启动不同打乱、交换后正确相邻自动合并、通关后推进下一关。
|
||||
3. `npm run check:encoding` 已通过,确认中文文档未被编码写坏。
|
||||
|
||||
## 12. 2026-04-26 二次运行态缺口补齐
|
||||
|
||||
本次继续按 PRD 第 9.12 与第 14.4 节收敛两个剩余缺口:
|
||||
|
||||
1. 通关判定必须同时支持“所有拼块回到正确位置”和“所有拼块汇成一个覆盖全盘的大合并块”。领域层以 `all_tiles_resolved` 作为唯一对外真相,但其计算来源必须包含这两个条件。
|
||||
2. 运行态底部不再常驻玩法说明文字,只保留短状态反馈、错误反馈和下一关动作;点击/拖动规则不写成长期 UI 文案。
|
||||
|
||||
### 12.1 合并块可见性修正
|
||||
|
||||
用户反馈“正确连接的块自动合并没有看到”后,确认原实现只把已合并格子染成绿色,仍按单块逐格渲染,视觉上无法形成“合并块”。本次运行态画布改为:
|
||||
|
||||
1. 根据 `mergedGroups` 计算合并块外接矩形。
|
||||
2. 原单格位置让位为透明占位。
|
||||
3. 在棋盘上叠加一个跨格整体层,内部仍按原图切片拼接,但外边框、阴影和拖动事件都属于同一个合并块。
|
||||
4. 合并块整体层以组内第一块作为拖动锚点,继续沿用后端/本地运行态的合并块拖动裁决。
|
||||
|
||||
### 12.2 拖动可用性修正
|
||||
|
||||
用户反馈“没有办法拖动拼图块”后,确认原交互只在 pointer move 超过阈值后记录 `dragging = true`,没有持续记录当前指针位置,也没有把拖动中的块做视觉平移;移动端还可能被浏览器默认触控手势抢占。修正如下:
|
||||
|
||||
1. `dragState` 持续记录 `currentX/currentY`,拖动中按指针偏移对单块或合并块做 `translate3d` 跟手反馈。
|
||||
2. 棋盘与合并块交互层增加 `touch-none select-none`,避免移动端滚动、选中文本等默认行为打断拖动。
|
||||
3. 松手后仍只提交 `pieceId + targetRow + targetCol`,最终交换、合并、拆分和通关继续以后端/本地运行态快照为准。
|
||||
|
||||
Reference in New Issue
Block a user